From 0d4cd3e103d6613b26e3e4eea9927123d75cff8c Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Thu, 23 May 2024 10:03:27 +0100
Subject: [PATCH 001/140] Swift: Add more sensitive data test cases.
---
.../CWE-311/CleartextStorageDatabase.expected | 16 ++++++++++++++++
.../Security/CWE-311/SensitiveExprs.expected | 2 ++
.../Security/CWE-311/testRealm2.swift | 18 +++++++++++++++++-
3 files changed, 35 insertions(+), 1 deletion(-)
diff --git a/swift/ql/test/query-tests/Security/CWE-311/CleartextStorageDatabase.expected b/swift/ql/test/query-tests/Security/CWE-311/CleartextStorageDatabase.expected
index 051f846c5b1dd..e609a3211549a 100644
--- a/swift/ql/test/query-tests/Security/CWE-311/CleartextStorageDatabase.expected
+++ b/swift/ql/test/query-tests/Security/CWE-311/CleartextStorageDatabase.expected
@@ -297,6 +297,12 @@ edges
| testRealm2.swift:18:2:18:2 | [post] o [data] | testRealm2.swift:18:2:18:2 | [post] o | provenance | |
| testRealm2.swift:18:11:18:11 | myPassword | testRealm2.swift:13:6:13:6 | value | provenance | |
| testRealm2.swift:18:11:18:11 | myPassword | testRealm2.swift:18:2:18:2 | [post] o [data] | provenance | |
+| testRealm2.swift:24:2:24:2 | [post] o [data] | testRealm2.swift:24:2:24:2 | [post] o | provenance | |
+| testRealm2.swift:24:11:24:11 | socialSecurityNumber | testRealm2.swift:13:6:13:6 | value | provenance | |
+| testRealm2.swift:24:11:24:11 | socialSecurityNumber | testRealm2.swift:24:2:24:2 | [post] o [data] | provenance | |
+| testRealm2.swift:32:2:32:2 | [post] o [data] | testRealm2.swift:32:2:32:2 | [post] o | provenance | |
+| testRealm2.swift:32:11:32:11 | creditCardNumber | testRealm2.swift:13:6:13:6 | value | provenance | |
+| testRealm2.swift:32:11:32:11 | creditCardNumber | testRealm2.swift:32:2:32:2 | [post] o [data] | provenance | |
| testRealm.swift:27:6:27:6 | value | file://:0:0:0:0 | value | provenance | |
| testRealm.swift:34:6:34:6 | value | file://:0:0:0:0 | value | provenance | |
| testRealm.swift:41:2:41:2 | [post] a [data] | testRealm.swift:41:2:41:2 | [post] a | provenance | |
@@ -721,6 +727,12 @@ nodes
| testRealm2.swift:18:2:18:2 | [post] o | semmle.label | [post] o |
| testRealm2.swift:18:2:18:2 | [post] o [data] | semmle.label | [post] o [data] |
| testRealm2.swift:18:11:18:11 | myPassword | semmle.label | myPassword |
+| testRealm2.swift:24:2:24:2 | [post] o | semmle.label | [post] o |
+| testRealm2.swift:24:2:24:2 | [post] o [data] | semmle.label | [post] o [data] |
+| testRealm2.swift:24:11:24:11 | socialSecurityNumber | semmle.label | socialSecurityNumber |
+| testRealm2.swift:32:2:32:2 | [post] o | semmle.label | [post] o |
+| testRealm2.swift:32:2:32:2 | [post] o [data] | semmle.label | [post] o [data] |
+| testRealm2.swift:32:11:32:11 | creditCardNumber | semmle.label | creditCardNumber |
| testRealm.swift:27:6:27:6 | self [Return] [data] | semmle.label | self [Return] [data] |
| testRealm.swift:27:6:27:6 | value | semmle.label | value |
| testRealm.swift:34:6:34:6 | self [Return] [password] | semmle.label | self [Return] [password] |
@@ -756,6 +768,8 @@ subpaths
| testCoreData2.swift:104:18:104:18 | e | testCoreData2.swift:70:9:70:9 | self | file://:0:0:0:0 | .value | testCoreData2.swift:104:18:104:20 | .value |
| testCoreData2.swift:105:18:105:18 | e | testCoreData2.swift:71:9:71:9 | self | file://:0:0:0:0 | .value2 | testCoreData2.swift:105:18:105:20 | .value2 |
| testRealm2.swift:18:11:18:11 | myPassword | testRealm2.swift:13:6:13:6 | value | testRealm2.swift:13:6:13:6 | self [Return] [data] | testRealm2.swift:18:2:18:2 | [post] o [data] |
+| testRealm2.swift:24:11:24:11 | socialSecurityNumber | testRealm2.swift:13:6:13:6 | value | testRealm2.swift:13:6:13:6 | self [Return] [data] | testRealm2.swift:24:2:24:2 | [post] o [data] |
+| testRealm2.swift:32:11:32:11 | creditCardNumber | testRealm2.swift:13:6:13:6 | value | testRealm2.swift:13:6:13:6 | self [Return] [data] | testRealm2.swift:32:2:32:2 | [post] o [data] |
| testRealm.swift:41:11:41:11 | myPassword | testRealm.swift:27:6:27:6 | value | testRealm.swift:27:6:27:6 | self [Return] [data] | testRealm.swift:41:2:41:2 | [post] a [data] |
| testRealm.swift:49:11:49:11 | myPassword | testRealm.swift:27:6:27:6 | value | testRealm.swift:27:6:27:6 | self [Return] [data] | testRealm.swift:49:2:49:2 | [post] c [data] |
| testRealm.swift:59:12:59:12 | myPassword | testRealm.swift:27:6:27:6 | value | testRealm.swift:27:6:27:6 | self [Return] [data] | testRealm.swift:59:2:59:3 | [post] ...! [data] |
@@ -890,6 +904,8 @@ subpaths
| testGRDB.swift:210:84:210:93 | [...] | testGRDB.swift:210:85:210:85 | password | testGRDB.swift:210:84:210:93 | [...] | This operation stores '[...]' in a database. It may contain unencrypted sensitive data from $@. | testGRDB.swift:210:85:210:85 | password | password |
| testGRDB.swift:212:98:212:107 | [...] | testGRDB.swift:212:99:212:99 | password | testGRDB.swift:212:98:212:107 | [...] | This operation stores '[...]' in a database. It may contain unencrypted sensitive data from $@. | testGRDB.swift:212:99:212:99 | password | password |
| testRealm2.swift:18:2:18:2 | o | testRealm2.swift:18:11:18:11 | myPassword | testRealm2.swift:18:2:18:2 | [post] o | This operation stores 'o' in a database. It may contain unencrypted sensitive data from $@. | testRealm2.swift:18:11:18:11 | myPassword | myPassword |
+| testRealm2.swift:24:2:24:2 | o | testRealm2.swift:24:11:24:11 | socialSecurityNumber | testRealm2.swift:24:2:24:2 | [post] o | This operation stores 'o' in a database. It may contain unencrypted sensitive data from $@. | testRealm2.swift:24:11:24:11 | socialSecurityNumber | socialSecurityNumber |
+| testRealm2.swift:32:2:32:2 | o | testRealm2.swift:32:11:32:11 | creditCardNumber | testRealm2.swift:32:2:32:2 | [post] o | This operation stores 'o' in a database. It may contain unencrypted sensitive data from $@. | testRealm2.swift:32:11:32:11 | creditCardNumber | creditCardNumber |
| testRealm.swift:41:2:41:2 | a | testRealm.swift:41:11:41:11 | myPassword | testRealm.swift:41:2:41:2 | [post] a | This operation stores 'a' in a database. It may contain unencrypted sensitive data from $@. | testRealm.swift:41:11:41:11 | myPassword | myPassword |
| testRealm.swift:49:2:49:2 | c | testRealm.swift:49:11:49:11 | myPassword | testRealm.swift:49:2:49:2 | [post] c | This operation stores 'c' in a database. It may contain unencrypted sensitive data from $@. | testRealm.swift:49:11:49:11 | myPassword | myPassword |
| testRealm.swift:59:2:59:3 | ...! | testRealm.swift:59:12:59:12 | myPassword | testRealm.swift:59:2:59:3 | [post] ...! | This operation stores '...!' in a database. It may contain unencrypted sensitive data from $@. | testRealm.swift:59:12:59:12 | myPassword | myPassword |
diff --git a/swift/ql/test/query-tests/Security/CWE-311/SensitiveExprs.expected b/swift/ql/test/query-tests/Security/CWE-311/SensitiveExprs.expected
index 57e4267d9e43a..b5f6abb01a409 100644
--- a/swift/ql/test/query-tests/Security/CWE-311/SensitiveExprs.expected
+++ b/swift/ql/test/query-tests/Security/CWE-311/SensitiveExprs.expected
@@ -141,6 +141,8 @@
| testGRDB.swift:210:85:210:85 | password | label:password, type:password |
| testGRDB.swift:212:99:212:99 | password | label:password, type:password |
| testRealm2.swift:18:11:18:11 | myPassword | label:myPassword, type:password |
+| testRealm2.swift:24:11:24:11 | socialSecurityNumber | label:socialSecurityNumber, type:private information |
+| testRealm2.swift:32:11:32:11 | creditCardNumber | label:creditCardNumber, type:private information |
| testRealm.swift:31:20:31:20 | .password | label:password, type:password |
| testRealm.swift:41:11:41:11 | myPassword | label:myPassword, type:password |
| testRealm.swift:49:11:49:11 | myPassword | label:myPassword, type:password |
diff --git a/swift/ql/test/query-tests/Security/CWE-311/testRealm2.swift b/swift/ql/test/query-tests/Security/CWE-311/testRealm2.swift
index 2c1850ee62097..8fcfcb0021146 100644
--- a/swift/ql/test/query-tests/Security/CWE-311/testRealm2.swift
+++ b/swift/ql/test/query-tests/Security/CWE-311/testRealm2.swift
@@ -13,9 +13,25 @@ class MyRealmSwiftObject3 : Object {
var data: String
}
-func test1(o: MyRealmSwiftObject3, myHarmless: String, myPassword : String) {
+func test1(o: MyRealmSwiftObject3, myHarmless: String, myPassword: String) {
// ...
o.data = myPassword // BAD
o.data = myHarmless
// ...
}
+
+func test2(o: MyRealmSwiftObject3, ccn: String, socialSecurityNumber: String, ssn: String, ssn_int: Int, userSSN: String, classno: String) {
+ o.data = socialSecurityNumber // BAD
+ o.data = ssn // BAD [NOT DETECTED]
+ o.data = String(ssn_int) // BAD [NOT DETECTED]
+ o.data = userSSN // BAD [NOT DETECTED]
+ o.data = classno // GOOD
+}
+
+func test3(o: MyRealmSwiftObject3, ccn: String, creditCardNumber: String, CCN: String, int_ccn: Int, userCcn: String, succnode: String) {
+ o.data = creditCardNumber // BAD
+ o.data = CCN // BAD [NOT DETECTED]
+ o.data = String(int_ccn) // BAD [NOT DETECTED]
+ o.data = userCcn // BAD [NOT DETECTED]
+ o.data = succnode // GOOD
+}
From 06dea2d27ff3884109b85b8e7293db65e20c6a45 Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Thu, 9 May 2024 18:09:55 +0100
Subject: [PATCH 002/140] Swift: Use sensitive private info regex from the
shared library, now that it has that.
---
.../codeql/swift/security/SensitiveExprs.qll | 30 +---------
.../CWE-311/CleartextStorageDatabase.expected | 57 +++++++++++++++++++
.../Security/CWE-311/SensitiveExprs.expected | 4 ++
.../Security/CWE-311/testRealm2.swift | 8 +--
4 files changed, 68 insertions(+), 31 deletions(-)
diff --git a/swift/ql/lib/codeql/swift/security/SensitiveExprs.qll b/swift/ql/lib/codeql/swift/security/SensitiveExprs.qll
index 0c712b4fbfdf1..a00d73c0a9f5e 100644
--- a/swift/ql/lib/codeql/swift/security/SensitiveExprs.qll
+++ b/swift/ql/lib/codeql/swift/security/SensitiveExprs.qll
@@ -64,33 +64,9 @@ class SensitivePrivateInfo extends SensitiveDataType, TPrivateInfo {
override string toString() { result = "private information" }
override string getRegexp() {
- result =
- "(?is).*(" +
- // Inspired by the list on https://cwe.mitre.org/data/definitions/359.html
- // Government identifiers, such as Social Security Numbers
- "social.?security|employer.?identification|national.?insurance|resident.?id|" +
- "passport.?(num|no)|" +
- // Contact information, such as home addresses
- "post.?code|zip.?code|home.?addr|" +
- // and telephone numbers
- "(mob(ile)?|home).?(num|no|tel|phone)|(tel|fax|phone).?(num|no)|telephone|" +
- "emergency.?contact|" +
- // Geographic location - where the user is (or was)
- "l(atitude|ongitude)|nationality|" +
- // Financial data - such as credit card numbers, salary, bank accounts, and debts
- "(credit|debit|bank|visa).?(card|num|no|acc(ou?)nt)|acc(ou)?nt.?(no|num|credit)|" +
- "salary|billing|credit.?(rating|score)|" +
- // Communications - e-mail addresses, private e-mail messages, SMS text messages, chat logs, etc.
- "e(mail|_mail)|" +
- // Health - medical conditions, insurance status, prescription records
- "birth.?da(te|y)|da(te|y).?(of.?)?birth|" +
- "medical|(health|care).?plan|healthkit|appointment|prescription|" +
- "blood.?(type|alcohol|glucose|pressure)|heart.?(rate|rhythm)|body.?(mass|fat)|" +
- "menstrua|pregnan|insulin|inhaler|" +
- // Relationships - work and family
- "employ(er|ee)|spouse|maiden.?name" +
- // ---
- ").*"
+ result = HeuristicNames::maybeSensitiveRegexp(SensitiveDataClassification::private())
+ or
+ result = "(?is).*e(mail|_mail).*"
}
}
diff --git a/swift/ql/test/query-tests/Security/CWE-311/CleartextStorageDatabase.expected b/swift/ql/test/query-tests/Security/CWE-311/CleartextStorageDatabase.expected
index e609a3211549a..83fb7d9c1fe83 100644
--- a/swift/ql/test/query-tests/Security/CWE-311/CleartextStorageDatabase.expected
+++ b/swift/ql/test/query-tests/Security/CWE-311/CleartextStorageDatabase.expected
@@ -69,6 +69,7 @@ edges
| SQLite.swift:197:17:197:49 | [...] [Collection element] | SQLite.swift:197:16:197:50 | [...] [Collection element, Collection element] | provenance | |
| SQLite.swift:197:18:197:32 | ... <-(_:_:) ... | SQLite.swift:197:17:197:49 | [...] [Collection element] | provenance | |
| SQLite.swift:197:32:197:32 | mobilePhoneNumber | SQLite.swift:197:18:197:32 | ... <-(_:_:) ... | provenance | |
+| file://:0:0:0:0 | [post] self [data, Collection element] | testRealm2.swift:13:6:13:6 | self [Return] [data, Collection element] | provenance | |
| file://:0:0:0:0 | [post] self [data] | testRealm2.swift:13:6:13:6 | self [Return] [data] | provenance | |
| file://:0:0:0:0 | [post] self [data] | testRealm.swift:27:6:27:6 | self [Return] [data] | provenance | |
| file://:0:0:0:0 | [post] self [notStoredBankAccountNumber] | testCoreData2.swift:23:13:23:13 | self [Return] [notStoredBankAccountNumber] | provenance | |
@@ -82,6 +83,7 @@ edges
| file://:0:0:0:0 | value | file://:0:0:0:0 | [post] self [notStoredBankAccountNumber] | provenance | |
| file://:0:0:0:0 | value | file://:0:0:0:0 | [post] self [password] | provenance | |
| file://:0:0:0:0 | value | file://:0:0:0:0 | [post] self [value] | provenance | |
+| file://:0:0:0:0 | value [Collection element] | file://:0:0:0:0 | [post] self [data, Collection element] | provenance | |
| sqlite3_c_api.swift:42:69:42:69 | medicalNotes | sqlite3_c_api.swift:46:27:46:27 | insertQuery | provenance | |
| sqlite3_c_api.swift:43:49:43:49 | medicalNotes | sqlite3_c_api.swift:47:27:47:27 | updateQuery | provenance | |
| testCoreData2.swift:23:13:23:13 | value | file://:0:0:0:0 | value | provenance | |
@@ -294,15 +296,38 @@ edges
| testGRDB.swift:212:98:212:107 | [...] [Collection element] | testGRDB.swift:212:98:212:107 | [...] | provenance | |
| testGRDB.swift:212:99:212:99 | password | testGRDB.swift:212:98:212:107 | [...] [Collection element] | provenance | |
| testRealm2.swift:13:6:13:6 | value | file://:0:0:0:0 | value | provenance | |
+| testRealm2.swift:13:6:13:6 | value [Collection element] | file://:0:0:0:0 | value [Collection element] | provenance | |
| testRealm2.swift:18:2:18:2 | [post] o [data] | testRealm2.swift:18:2:18:2 | [post] o | provenance | |
| testRealm2.swift:18:11:18:11 | myPassword | testRealm2.swift:13:6:13:6 | value | provenance | |
| testRealm2.swift:18:11:18:11 | myPassword | testRealm2.swift:18:2:18:2 | [post] o [data] | provenance | |
| testRealm2.swift:24:2:24:2 | [post] o [data] | testRealm2.swift:24:2:24:2 | [post] o | provenance | |
| testRealm2.swift:24:11:24:11 | socialSecurityNumber | testRealm2.swift:13:6:13:6 | value | provenance | |
| testRealm2.swift:24:11:24:11 | socialSecurityNumber | testRealm2.swift:24:2:24:2 | [post] o [data] | provenance | |
+| testRealm2.swift:25:2:25:2 | [post] o [data] | testRealm2.swift:25:2:25:2 | [post] o | provenance | |
+| testRealm2.swift:25:11:25:11 | ssn | testRealm2.swift:13:6:13:6 | value | provenance | |
+| testRealm2.swift:25:11:25:11 | ssn | testRealm2.swift:25:2:25:2 | [post] o [data] | provenance | |
+| testRealm2.swift:26:2:26:2 | [post] o [data, Collection element] | testRealm2.swift:26:2:26:2 | [post] o | provenance | |
+| testRealm2.swift:26:2:26:2 | [post] o [data] | testRealm2.swift:26:2:26:2 | [post] o | provenance | |
+| testRealm2.swift:26:11:26:25 | call to String.init(_:) | testRealm2.swift:13:6:13:6 | value | provenance | |
+| testRealm2.swift:26:11:26:25 | call to String.init(_:) | testRealm2.swift:26:2:26:2 | [post] o [data] | provenance | |
+| testRealm2.swift:26:11:26:25 | call to String.init(_:) [Collection element] | testRealm2.swift:13:6:13:6 | value [Collection element] | provenance | |
+| testRealm2.swift:26:11:26:25 | call to String.init(_:) [Collection element] | testRealm2.swift:26:2:26:2 | [post] o [data, Collection element] | provenance | |
+| testRealm2.swift:26:18:26:18 | ssn_int | testRealm2.swift:26:11:26:25 | call to String.init(_:) | provenance | |
+| testRealm2.swift:26:18:26:18 | ssn_int | testRealm2.swift:26:11:26:25 | call to String.init(_:) [Collection element] | provenance | |
| testRealm2.swift:32:2:32:2 | [post] o [data] | testRealm2.swift:32:2:32:2 | [post] o | provenance | |
| testRealm2.swift:32:11:32:11 | creditCardNumber | testRealm2.swift:13:6:13:6 | value | provenance | |
| testRealm2.swift:32:11:32:11 | creditCardNumber | testRealm2.swift:32:2:32:2 | [post] o [data] | provenance | |
+| testRealm2.swift:33:2:33:2 | [post] o [data] | testRealm2.swift:33:2:33:2 | [post] o | provenance | |
+| testRealm2.swift:33:11:33:11 | CCN | testRealm2.swift:13:6:13:6 | value | provenance | |
+| testRealm2.swift:33:11:33:11 | CCN | testRealm2.swift:33:2:33:2 | [post] o [data] | provenance | |
+| testRealm2.swift:34:2:34:2 | [post] o [data, Collection element] | testRealm2.swift:34:2:34:2 | [post] o | provenance | |
+| testRealm2.swift:34:2:34:2 | [post] o [data] | testRealm2.swift:34:2:34:2 | [post] o | provenance | |
+| testRealm2.swift:34:11:34:25 | call to String.init(_:) | testRealm2.swift:13:6:13:6 | value | provenance | |
+| testRealm2.swift:34:11:34:25 | call to String.init(_:) | testRealm2.swift:34:2:34:2 | [post] o [data] | provenance | |
+| testRealm2.swift:34:11:34:25 | call to String.init(_:) [Collection element] | testRealm2.swift:13:6:13:6 | value [Collection element] | provenance | |
+| testRealm2.swift:34:11:34:25 | call to String.init(_:) [Collection element] | testRealm2.swift:34:2:34:2 | [post] o [data, Collection element] | provenance | |
+| testRealm2.swift:34:18:34:18 | int_ccn | testRealm2.swift:34:11:34:25 | call to String.init(_:) | provenance | |
+| testRealm2.swift:34:18:34:18 | int_ccn | testRealm2.swift:34:11:34:25 | call to String.init(_:) [Collection element] | provenance | |
| testRealm.swift:27:6:27:6 | value | file://:0:0:0:0 | value | provenance | |
| testRealm.swift:34:6:34:6 | value | file://:0:0:0:0 | value | provenance | |
| testRealm.swift:41:2:41:2 | [post] a [data] | testRealm.swift:41:2:41:2 | [post] a | provenance | |
@@ -419,6 +444,7 @@ nodes
| file://:0:0:0:0 | .value | semmle.label | .value |
| file://:0:0:0:0 | .value | semmle.label | .value |
| file://:0:0:0:0 | .value2 | semmle.label | .value2 |
+| file://:0:0:0:0 | [post] self [data, Collection element] | semmle.label | [post] self [data, Collection element] |
| file://:0:0:0:0 | [post] self [data] | semmle.label | [post] self [data] |
| file://:0:0:0:0 | [post] self [data] | semmle.label | [post] self [data] |
| file://:0:0:0:0 | [post] self [notStoredBankAccountNumber] | semmle.label | [post] self [notStoredBankAccountNumber] |
@@ -432,6 +458,7 @@ nodes
| file://:0:0:0:0 | value | semmle.label | value |
| file://:0:0:0:0 | value | semmle.label | value |
| file://:0:0:0:0 | value | semmle.label | value |
+| file://:0:0:0:0 | value [Collection element] | semmle.label | value [Collection element] |
| sqlite3_c_api.swift:42:69:42:69 | medicalNotes | semmle.label | medicalNotes |
| sqlite3_c_api.swift:43:49:43:49 | medicalNotes | semmle.label | medicalNotes |
| sqlite3_c_api.swift:46:27:46:27 | insertQuery | semmle.label | insertQuery |
@@ -722,17 +749,37 @@ nodes
| testGRDB.swift:212:98:212:107 | [...] | semmle.label | [...] |
| testGRDB.swift:212:98:212:107 | [...] [Collection element] | semmle.label | [...] [Collection element] |
| testGRDB.swift:212:99:212:99 | password | semmle.label | password |
+| testRealm2.swift:13:6:13:6 | self [Return] [data, Collection element] | semmle.label | self [Return] [data, Collection element] |
| testRealm2.swift:13:6:13:6 | self [Return] [data] | semmle.label | self [Return] [data] |
| testRealm2.swift:13:6:13:6 | value | semmle.label | value |
+| testRealm2.swift:13:6:13:6 | value [Collection element] | semmle.label | value [Collection element] |
| testRealm2.swift:18:2:18:2 | [post] o | semmle.label | [post] o |
| testRealm2.swift:18:2:18:2 | [post] o [data] | semmle.label | [post] o [data] |
| testRealm2.swift:18:11:18:11 | myPassword | semmle.label | myPassword |
| testRealm2.swift:24:2:24:2 | [post] o | semmle.label | [post] o |
| testRealm2.swift:24:2:24:2 | [post] o [data] | semmle.label | [post] o [data] |
| testRealm2.swift:24:11:24:11 | socialSecurityNumber | semmle.label | socialSecurityNumber |
+| testRealm2.swift:25:2:25:2 | [post] o | semmle.label | [post] o |
+| testRealm2.swift:25:2:25:2 | [post] o [data] | semmle.label | [post] o [data] |
+| testRealm2.swift:25:11:25:11 | ssn | semmle.label | ssn |
+| testRealm2.swift:26:2:26:2 | [post] o | semmle.label | [post] o |
+| testRealm2.swift:26:2:26:2 | [post] o [data, Collection element] | semmle.label | [post] o [data, Collection element] |
+| testRealm2.swift:26:2:26:2 | [post] o [data] | semmle.label | [post] o [data] |
+| testRealm2.swift:26:11:26:25 | call to String.init(_:) | semmle.label | call to String.init(_:) |
+| testRealm2.swift:26:11:26:25 | call to String.init(_:) [Collection element] | semmle.label | call to String.init(_:) [Collection element] |
+| testRealm2.swift:26:18:26:18 | ssn_int | semmle.label | ssn_int |
| testRealm2.swift:32:2:32:2 | [post] o | semmle.label | [post] o |
| testRealm2.swift:32:2:32:2 | [post] o [data] | semmle.label | [post] o [data] |
| testRealm2.swift:32:11:32:11 | creditCardNumber | semmle.label | creditCardNumber |
+| testRealm2.swift:33:2:33:2 | [post] o | semmle.label | [post] o |
+| testRealm2.swift:33:2:33:2 | [post] o [data] | semmle.label | [post] o [data] |
+| testRealm2.swift:33:11:33:11 | CCN | semmle.label | CCN |
+| testRealm2.swift:34:2:34:2 | [post] o | semmle.label | [post] o |
+| testRealm2.swift:34:2:34:2 | [post] o [data, Collection element] | semmle.label | [post] o [data, Collection element] |
+| testRealm2.swift:34:2:34:2 | [post] o [data] | semmle.label | [post] o [data] |
+| testRealm2.swift:34:11:34:25 | call to String.init(_:) | semmle.label | call to String.init(_:) |
+| testRealm2.swift:34:11:34:25 | call to String.init(_:) [Collection element] | semmle.label | call to String.init(_:) [Collection element] |
+| testRealm2.swift:34:18:34:18 | int_ccn | semmle.label | int_ccn |
| testRealm.swift:27:6:27:6 | self [Return] [data] | semmle.label | self [Return] [data] |
| testRealm.swift:27:6:27:6 | value | semmle.label | value |
| testRealm.swift:34:6:34:6 | self [Return] [password] | semmle.label | self [Return] [password] |
@@ -769,7 +816,13 @@ subpaths
| testCoreData2.swift:105:18:105:18 | e | testCoreData2.swift:71:9:71:9 | self | file://:0:0:0:0 | .value2 | testCoreData2.swift:105:18:105:20 | .value2 |
| testRealm2.swift:18:11:18:11 | myPassword | testRealm2.swift:13:6:13:6 | value | testRealm2.swift:13:6:13:6 | self [Return] [data] | testRealm2.swift:18:2:18:2 | [post] o [data] |
| testRealm2.swift:24:11:24:11 | socialSecurityNumber | testRealm2.swift:13:6:13:6 | value | testRealm2.swift:13:6:13:6 | self [Return] [data] | testRealm2.swift:24:2:24:2 | [post] o [data] |
+| testRealm2.swift:25:11:25:11 | ssn | testRealm2.swift:13:6:13:6 | value | testRealm2.swift:13:6:13:6 | self [Return] [data] | testRealm2.swift:25:2:25:2 | [post] o [data] |
+| testRealm2.swift:26:11:26:25 | call to String.init(_:) | testRealm2.swift:13:6:13:6 | value | testRealm2.swift:13:6:13:6 | self [Return] [data] | testRealm2.swift:26:2:26:2 | [post] o [data] |
+| testRealm2.swift:26:11:26:25 | call to String.init(_:) [Collection element] | testRealm2.swift:13:6:13:6 | value [Collection element] | testRealm2.swift:13:6:13:6 | self [Return] [data, Collection element] | testRealm2.swift:26:2:26:2 | [post] o [data, Collection element] |
| testRealm2.swift:32:11:32:11 | creditCardNumber | testRealm2.swift:13:6:13:6 | value | testRealm2.swift:13:6:13:6 | self [Return] [data] | testRealm2.swift:32:2:32:2 | [post] o [data] |
+| testRealm2.swift:33:11:33:11 | CCN | testRealm2.swift:13:6:13:6 | value | testRealm2.swift:13:6:13:6 | self [Return] [data] | testRealm2.swift:33:2:33:2 | [post] o [data] |
+| testRealm2.swift:34:11:34:25 | call to String.init(_:) | testRealm2.swift:13:6:13:6 | value | testRealm2.swift:13:6:13:6 | self [Return] [data] | testRealm2.swift:34:2:34:2 | [post] o [data] |
+| testRealm2.swift:34:11:34:25 | call to String.init(_:) [Collection element] | testRealm2.swift:13:6:13:6 | value [Collection element] | testRealm2.swift:13:6:13:6 | self [Return] [data, Collection element] | testRealm2.swift:34:2:34:2 | [post] o [data, Collection element] |
| testRealm.swift:41:11:41:11 | myPassword | testRealm.swift:27:6:27:6 | value | testRealm.swift:27:6:27:6 | self [Return] [data] | testRealm.swift:41:2:41:2 | [post] a [data] |
| testRealm.swift:49:11:49:11 | myPassword | testRealm.swift:27:6:27:6 | value | testRealm.swift:27:6:27:6 | self [Return] [data] | testRealm.swift:49:2:49:2 | [post] c [data] |
| testRealm.swift:59:12:59:12 | myPassword | testRealm.swift:27:6:27:6 | value | testRealm.swift:27:6:27:6 | self [Return] [data] | testRealm.swift:59:2:59:3 | [post] ...! [data] |
@@ -905,7 +958,11 @@ subpaths
| testGRDB.swift:212:98:212:107 | [...] | testGRDB.swift:212:99:212:99 | password | testGRDB.swift:212:98:212:107 | [...] | This operation stores '[...]' in a database. It may contain unencrypted sensitive data from $@. | testGRDB.swift:212:99:212:99 | password | password |
| testRealm2.swift:18:2:18:2 | o | testRealm2.swift:18:11:18:11 | myPassword | testRealm2.swift:18:2:18:2 | [post] o | This operation stores 'o' in a database. It may contain unencrypted sensitive data from $@. | testRealm2.swift:18:11:18:11 | myPassword | myPassword |
| testRealm2.swift:24:2:24:2 | o | testRealm2.swift:24:11:24:11 | socialSecurityNumber | testRealm2.swift:24:2:24:2 | [post] o | This operation stores 'o' in a database. It may contain unencrypted sensitive data from $@. | testRealm2.swift:24:11:24:11 | socialSecurityNumber | socialSecurityNumber |
+| testRealm2.swift:25:2:25:2 | o | testRealm2.swift:25:11:25:11 | ssn | testRealm2.swift:25:2:25:2 | [post] o | This operation stores 'o' in a database. It may contain unencrypted sensitive data from $@. | testRealm2.swift:25:11:25:11 | ssn | ssn |
+| testRealm2.swift:26:2:26:2 | o | testRealm2.swift:26:18:26:18 | ssn_int | testRealm2.swift:26:2:26:2 | [post] o | This operation stores 'o' in a database. It may contain unencrypted sensitive data from $@. | testRealm2.swift:26:18:26:18 | ssn_int | ssn_int |
| testRealm2.swift:32:2:32:2 | o | testRealm2.swift:32:11:32:11 | creditCardNumber | testRealm2.swift:32:2:32:2 | [post] o | This operation stores 'o' in a database. It may contain unencrypted sensitive data from $@. | testRealm2.swift:32:11:32:11 | creditCardNumber | creditCardNumber |
+| testRealm2.swift:33:2:33:2 | o | testRealm2.swift:33:11:33:11 | CCN | testRealm2.swift:33:2:33:2 | [post] o | This operation stores 'o' in a database. It may contain unencrypted sensitive data from $@. | testRealm2.swift:33:11:33:11 | CCN | CCN |
+| testRealm2.swift:34:2:34:2 | o | testRealm2.swift:34:18:34:18 | int_ccn | testRealm2.swift:34:2:34:2 | [post] o | This operation stores 'o' in a database. It may contain unencrypted sensitive data from $@. | testRealm2.swift:34:18:34:18 | int_ccn | int_ccn |
| testRealm.swift:41:2:41:2 | a | testRealm.swift:41:11:41:11 | myPassword | testRealm.swift:41:2:41:2 | [post] a | This operation stores 'a' in a database. It may contain unencrypted sensitive data from $@. | testRealm.swift:41:11:41:11 | myPassword | myPassword |
| testRealm.swift:49:2:49:2 | c | testRealm.swift:49:11:49:11 | myPassword | testRealm.swift:49:2:49:2 | [post] c | This operation stores 'c' in a database. It may contain unencrypted sensitive data from $@. | testRealm.swift:49:11:49:11 | myPassword | myPassword |
| testRealm.swift:59:2:59:3 | ...! | testRealm.swift:59:12:59:12 | myPassword | testRealm.swift:59:2:59:3 | [post] ...! | This operation stores '...!' in a database. It may contain unencrypted sensitive data from $@. | testRealm.swift:59:12:59:12 | myPassword | myPassword |
diff --git a/swift/ql/test/query-tests/Security/CWE-311/SensitiveExprs.expected b/swift/ql/test/query-tests/Security/CWE-311/SensitiveExprs.expected
index b5f6abb01a409..353d6d0a63151 100644
--- a/swift/ql/test/query-tests/Security/CWE-311/SensitiveExprs.expected
+++ b/swift/ql/test/query-tests/Security/CWE-311/SensitiveExprs.expected
@@ -142,7 +142,11 @@
| testGRDB.swift:212:99:212:99 | password | label:password, type:password |
| testRealm2.swift:18:11:18:11 | myPassword | label:myPassword, type:password |
| testRealm2.swift:24:11:24:11 | socialSecurityNumber | label:socialSecurityNumber, type:private information |
+| testRealm2.swift:25:11:25:11 | ssn | label:ssn, type:private information |
+| testRealm2.swift:26:18:26:18 | ssn_int | label:ssn_int, type:private information |
| testRealm2.swift:32:11:32:11 | creditCardNumber | label:creditCardNumber, type:private information |
+| testRealm2.swift:33:11:33:11 | CCN | label:CCN, type:private information |
+| testRealm2.swift:34:18:34:18 | int_ccn | label:int_ccn, type:private information |
| testRealm.swift:31:20:31:20 | .password | label:password, type:password |
| testRealm.swift:41:11:41:11 | myPassword | label:myPassword, type:password |
| testRealm.swift:49:11:49:11 | myPassword | label:myPassword, type:password |
diff --git a/swift/ql/test/query-tests/Security/CWE-311/testRealm2.swift b/swift/ql/test/query-tests/Security/CWE-311/testRealm2.swift
index 8fcfcb0021146..f9a325c42bbdf 100644
--- a/swift/ql/test/query-tests/Security/CWE-311/testRealm2.swift
+++ b/swift/ql/test/query-tests/Security/CWE-311/testRealm2.swift
@@ -22,16 +22,16 @@ func test1(o: MyRealmSwiftObject3, myHarmless: String, myPassword: String) {
func test2(o: MyRealmSwiftObject3, ccn: String, socialSecurityNumber: String, ssn: String, ssn_int: Int, userSSN: String, classno: String) {
o.data = socialSecurityNumber // BAD
- o.data = ssn // BAD [NOT DETECTED]
- o.data = String(ssn_int) // BAD [NOT DETECTED]
+ o.data = ssn // BAD
+ o.data = String(ssn_int) // BAD
o.data = userSSN // BAD [NOT DETECTED]
o.data = classno // GOOD
}
func test3(o: MyRealmSwiftObject3, ccn: String, creditCardNumber: String, CCN: String, int_ccn: Int, userCcn: String, succnode: String) {
o.data = creditCardNumber // BAD
- o.data = CCN // BAD [NOT DETECTED]
- o.data = String(int_ccn) // BAD [NOT DETECTED]
+ o.data = CCN // BAD
+ o.data = String(int_ccn) // BAD
o.data = userCcn // BAD [NOT DETECTED]
o.data = succnode // GOOD
}
From 1f13e462b15ae420e1bc6bfd3db2019f22273631 Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Thu, 23 May 2024 10:14:59 +0100
Subject: [PATCH 003/140] Swift: Change note.
---
swift/ql/lib/change-notes/2024-05-23-sensitive-data.md | 4 ++++
1 file changed, 4 insertions(+)
create mode 100644 swift/ql/lib/change-notes/2024-05-23-sensitive-data.md
diff --git a/swift/ql/lib/change-notes/2024-05-23-sensitive-data.md b/swift/ql/lib/change-notes/2024-05-23-sensitive-data.md
new file mode 100644
index 0000000000000..f42901c458956
--- /dev/null
+++ b/swift/ql/lib/change-notes/2024-05-23-sensitive-data.md
@@ -0,0 +1,4 @@
+---
+category: minorAnalysis
+---
+* Additional heuristics for sensitive private information have been added to the `SensitiveExprs.qll` library, improving coverage for credit card and social security numbers. This may result in additional results for queries that use sensitive data such as `swift/cleartext-transmission`.
From d4203d92860dc659c4e4ea19a6e0b33a223359c6 Mon Sep 17 00:00:00 2001
From: Alex Ford
Date: Mon, 17 Jun 2024 11:11:28 +0100
Subject: [PATCH 004/140] Ruby: minimal port of py/weak-sensitive-data-hashing
---
.../codeql/ruby/security/SensitiveActions.qll | 1 +
...WeakSensitiveDataHashingCustomizations.qll | 157 ++++++++++++++++++
.../WeakSensitiveDataHashingQuery.qll | 87 ++++++++++
.../cwe-327/WeakSensitiveDataHashing.ql | 43 +++++
4 files changed, 288 insertions(+)
create mode 100644 ruby/ql/lib/codeql/ruby/security/WeakSensitiveDataHashingCustomizations.qll
create mode 100644 ruby/ql/lib/codeql/ruby/security/WeakSensitiveDataHashingQuery.qll
create mode 100644 ruby/ql/src/queries/security/cwe-327/WeakSensitiveDataHashing.ql
diff --git a/ruby/ql/lib/codeql/ruby/security/SensitiveActions.qll b/ruby/ql/lib/codeql/ruby/security/SensitiveActions.qll
index 34beb33604b72..091ac7efdfd64 100644
--- a/ruby/ql/lib/codeql/ruby/security/SensitiveActions.qll
+++ b/ruby/ql/lib/codeql/ruby/security/SensitiveActions.qll
@@ -14,6 +14,7 @@ private import codeql.ruby.DataFlow
import codeql.ruby.security.internal.SensitiveDataHeuristics
private import HeuristicNames
private import codeql.ruby.CFG
+private import codeql.ruby.typetracking.TypeTracking
/** An expression that might contain sensitive data. */
cached
diff --git a/ruby/ql/lib/codeql/ruby/security/WeakSensitiveDataHashingCustomizations.qll b/ruby/ql/lib/codeql/ruby/security/WeakSensitiveDataHashingCustomizations.qll
new file mode 100644
index 0000000000000..b1a6e8c801cbb
--- /dev/null
+++ b/ruby/ql/lib/codeql/ruby/security/WeakSensitiveDataHashingCustomizations.qll
@@ -0,0 +1,157 @@
+/**
+ * Provides default sources, sinks and sanitizers for detecting
+ * "use of a broken or weak cryptographic hashing algorithm on sensitive data"
+ * vulnerabilities, as well as extension points for adding your own.
+ */
+
+private import ruby
+private import codeql.ruby.Concepts
+private import codeql.ruby.security.SensitiveActions
+private import codeql.ruby.dataflow.BarrierGuards
+
+/**
+ * Provides default sources, sinks and sanitizers for detecting
+ * "use of a broken or weak cryptographic hashing algorithm on sensitive data"
+ * vulnerabilities on sensitive data that does NOT require computationally expensive
+ * hashing, as well as extension points for adding your own.
+ *
+ * Also see the `ComputationallyExpensiveHashFunction` module.
+ */
+module NormalHashFunction {
+ /**
+ * A data flow source for "use of a broken or weak cryptographic hashing algorithm on
+ * sensitive data" vulnerabilities.
+ */
+ abstract class Source extends DataFlow::Node {
+ Source() { not this instanceof ComputationallyExpensiveHashFunction::Source }
+
+ /** Gets the classification of the sensitive data. */
+ abstract string getClassification();
+ }
+
+ /**
+ * A data flow sink for "use of a broken or weak cryptographic hashing algorithm on
+ * sensitive data" vulnerabilities.
+ */
+ abstract class Sink extends DataFlow::Node {
+ /**
+ * Gets the name of the weak hashing algorithm.
+ */
+ abstract string getAlgorithmName();
+ }
+
+ /**
+ * A sanitizer for "use of a broken or weak cryptographic hashing algorithm on
+ * sensitive data" vulnerabilities.
+ */
+ abstract class Sanitizer extends DataFlow::Node { }
+
+ /**
+ * A source of sensitive data, considered as a flow source.
+ */
+ class SensitiveNodeSourceAsSource extends Source instanceof SensitiveNode {
+ override SensitiveDataClassification getClassification() {
+ result = SensitiveNode.super.getClassification()
+ }
+ }
+
+ /** The input to a hashing operation using a weak algorithm, considered as a flow sink. */
+ class WeakHashingOperationInputSink extends Sink {
+ Cryptography::HashingAlgorithm algorithm;
+
+ WeakHashingOperationInputSink() {
+ exists(Cryptography::CryptographicOperation operation |
+ algorithm = operation.getAlgorithm() and
+ algorithm.isWeak() and
+ this = operation.getAnInput()
+ )
+ }
+
+ override string getAlgorithmName() { result = algorithm.getName() }
+ }
+}
+
+/**
+ * Provides default sources, sinks and sanitizers for detecting
+ * "use of a broken or weak cryptographic hashing algorithm on sensitive data"
+ * vulnerabilities on sensitive data that DOES require computationally expensive
+ * hashing, as well as extension points for adding your own.
+ *
+ * Also see the `NormalHashFunction` module.
+ */
+module ComputationallyExpensiveHashFunction {
+ /**
+ * A data flow source of sensitive data that requires computationally expensive
+ * hashing for "use of a broken or weak cryptographic hashing algorithm on sensitive
+ * data" vulnerabilities.
+ */
+ abstract class Source extends DataFlow::Node {
+ /** Gets the classification of the sensitive data. */
+ abstract string getClassification();
+ }
+
+ /**
+ * A data flow sink for sensitive data that requires computationally expensive
+ * hashing for "use of a broken or weak cryptographic hashing algorithm on sensitive
+ * data" vulnerabilities.
+ */
+ abstract class Sink extends DataFlow::Node {
+ /**
+ * Gets the name of the weak hashing algorithm.
+ */
+ abstract string getAlgorithmName();
+
+ /**
+ * Holds if this sink is for a computationally expensive hash function (meaning that
+ * hash function is just weak in some other regard.
+ */
+ abstract predicate isComputationallyExpensive();
+ }
+
+ /**
+ * A sanitizer of sensitive data that requires computationally expensive
+ * hashing for "use of a broken or weak cryptographic hashing
+ * algorithm on sensitive data" vulnerabilities.
+ */
+ abstract class Sanitizer extends DataFlow::Node { }
+
+ /**
+ * A source of passwords, considered as a flow source.
+ */
+ class PasswordSourceAsSource extends Source instanceof SensitiveNode {
+ PasswordSourceAsSource() {
+ this.(SensitiveNode).getClassification() = SensitiveDataClassification::password()
+ }
+
+ override SensitiveDataClassification getClassification() {
+ result = SensitiveNode.super.getClassification()
+ }
+ }
+
+ /**
+ * The input to a password hashing operation using a weak algorithm, considered as a
+ * flow sink.
+ */
+ class WeakPasswordHashingOperationInputSink extends Sink {
+ Cryptography::CryptographicAlgorithm algorithm;
+
+ WeakPasswordHashingOperationInputSink() {
+ (
+ algorithm instanceof Cryptography::PasswordHashingAlgorithm and
+ algorithm.isWeak()
+ or
+ algorithm instanceof Cryptography::HashingAlgorithm // Note that HashingAlgorithm and PasswordHashingAlgorithm are disjoint
+ ) and
+ exists(Cryptography::CryptographicOperation operation |
+ algorithm = operation.getAlgorithm() and
+ this = operation.getAnInput()
+ )
+ }
+
+ override string getAlgorithmName() { result = algorithm.getName() }
+
+ override predicate isComputationallyExpensive() {
+ algorithm instanceof Cryptography::PasswordHashingAlgorithm
+ }
+ }
+}
diff --git a/ruby/ql/lib/codeql/ruby/security/WeakSensitiveDataHashingQuery.qll b/ruby/ql/lib/codeql/ruby/security/WeakSensitiveDataHashingQuery.qll
new file mode 100644
index 0000000000000..dd9c389b4c348
--- /dev/null
+++ b/ruby/ql/lib/codeql/ruby/security/WeakSensitiveDataHashingQuery.qll
@@ -0,0 +1,87 @@
+/**
+ * Provides a taint-tracking configuration for detecting use of a broken or weak
+ * cryptographic hashing algorithm on sensitive data.
+ *
+ * Note, for performance reasons: only import this file if
+ * `WeakSensitiveDataHashing::Configuration` is needed, otherwise
+ * `WeakSensitiveDataHashingCustomizations` should be imported instead.
+ */
+
+private import ruby
+private import codeql.ruby.Concepts
+private import codeql.ruby.TaintTracking
+private import codeql.ruby.dataflow.RemoteFlowSources
+private import codeql.ruby.dataflow.BarrierGuards
+private import codeql.ruby.security.SensitiveActions
+
+/**
+ * Provides a taint-tracking configuration for detecting use of a broken or weak
+ * cryptographic hash function on sensitive data, that does NOT require a
+ * computationally expensive hash function.
+ */
+module NormalHashFunction {
+ import WeakSensitiveDataHashingCustomizations::NormalHashFunction
+
+ private module Config implements DataFlow::ConfigSig {
+ predicate isSource(DataFlow::Node source) { source instanceof Source }
+
+ predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
+
+ predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer }
+ }
+
+ /** Global taint-tracking for detecting "use of a broken or weak cryptographic hashing algorithm on sensitive data" vulnerabilities. */
+ module Flow = TaintTracking::Global;
+}
+
+/**
+ * Provides a taint-tracking configuration for detecting use of a broken or weak
+ * cryptographic hashing algorithm on passwords.
+ *
+ * Passwords has stricter requirements on the hashing algorithm used (must be
+ * computationally expensive to prevent brute-force attacks).
+ */
+module ComputationallyExpensiveHashFunction {
+ import WeakSensitiveDataHashingCustomizations::ComputationallyExpensiveHashFunction
+
+ /**
+ * Passwords has stricter requirements on the hashing algorithm used (must be
+ * computationally expensive to prevent brute-force attacks).
+ */
+ private module Config implements DataFlow::ConfigSig {
+ predicate isSource(DataFlow::Node source) { source instanceof Source }
+
+ predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
+
+ predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer }
+ }
+
+ /** Global taint-tracking for detecting "use of a broken or weak cryptographic hashing algorithm on passwords" vulnerabilities. */
+ module Flow = TaintTracking::Global;
+}
+
+/**
+ * Global taint-tracking for detecting both variants of "use of a broken or weak
+ * cryptographic hashing algorithm on sensitive data" vulnerabilities.
+ *
+ * See convenience predicates `normalHashFunctionFlowPath` and
+ * `computationallyExpensiveHashFunctionFlowPath`.
+ */
+module WeakSensitiveDataHashingFlow =
+ DataFlow::MergePathGraph;
+
+/** Holds if data can flow from `source` to `sink` with `NormalHashFunction::Flow`. */
+predicate normalHashFunctionFlowPath(
+ WeakSensitiveDataHashingFlow::PathNode source, WeakSensitiveDataHashingFlow::PathNode sink
+) {
+ NormalHashFunction::Flow::flowPath(source.asPathNode1(), sink.asPathNode1())
+}
+
+/** Holds if data can flow from `source` to `sink` with `ComputationallyExpensiveHashFunction::Flow`. */
+predicate computationallyExpensiveHashFunctionFlowPath(
+ WeakSensitiveDataHashingFlow::PathNode source, WeakSensitiveDataHashingFlow::PathNode sink
+) {
+ ComputationallyExpensiveHashFunction::Flow::flowPath(source.asPathNode2(), sink.asPathNode2())
+}
diff --git a/ruby/ql/src/queries/security/cwe-327/WeakSensitiveDataHashing.ql b/ruby/ql/src/queries/security/cwe-327/WeakSensitiveDataHashing.ql
new file mode 100644
index 0000000000000..64d9615837df1
--- /dev/null
+++ b/ruby/ql/src/queries/security/cwe-327/WeakSensitiveDataHashing.ql
@@ -0,0 +1,43 @@
+/**
+ * @name Use of a broken or weak cryptographic hashing algorithm on sensitive data
+ * @description Using broken or weak cryptographic hashing algorithms can compromise security.
+ * @kind path-problem
+ * @problem.severity warning
+ * @security-severity 7.5
+ * @precision high
+ * @id rb/weak-sensitive-data-hashing
+ * @tags security
+ * external/cwe/cwe-327
+ * external/cwe/cwe-328
+ * external/cwe/cwe-916
+ */
+
+import ruby
+import codeql.ruby.security.WeakSensitiveDataHashingQuery
+import WeakSensitiveDataHashingFlow::PathGraph
+
+from
+ WeakSensitiveDataHashingFlow::PathNode source, WeakSensitiveDataHashingFlow::PathNode sink,
+ string ending, string algorithmName, string classification
+where
+ normalHashFunctionFlowPath(source, sink) and
+ algorithmName = sink.getNode().(NormalHashFunction::Sink).getAlgorithmName() and
+ classification = source.getNode().(NormalHashFunction::Source).getClassification() and
+ ending = "."
+ or
+ computationallyExpensiveHashFunctionFlowPath(source, sink) and
+ algorithmName = sink.getNode().(ComputationallyExpensiveHashFunction::Sink).getAlgorithmName() and
+ classification =
+ source.getNode().(ComputationallyExpensiveHashFunction::Source).getClassification() and
+ (
+ sink.getNode().(ComputationallyExpensiveHashFunction::Sink).isComputationallyExpensive() and
+ ending = "."
+ or
+ not sink.getNode().(ComputationallyExpensiveHashFunction::Sink).isComputationallyExpensive() and
+ ending =
+ " for " + classification +
+ " hashing, since it is not a computationally expensive hash function."
+ )
+select sink.getNode(), source, sink,
+ "$@ is used in a hashing algorithm (" + algorithmName + ") that is insecure" + ending,
+ source.getNode(), "Sensitive data (" + classification + ")"
From f017821062dc4cfba9fe7dd3e5482d516cee6d7c Mon Sep 17 00:00:00 2001
From: Alex Ford
Date: Mon, 17 Jun 2024 15:29:53 +0100
Subject: [PATCH 005/140] Ruby: rb/weak-sensitive-data-hashing qhelp
---
.../cwe-327/WeakSensitiveDataHashing.qhelp | 104 ++++++++++++++++++
.../examples/weak_certificate_hashing.rb | 11 ++
.../examples/weak_password_hashing_bad.rb | 5 +
.../examples/weak_password_hashing_good.rb | 9 ++
4 files changed, 129 insertions(+)
create mode 100644 ruby/ql/src/queries/security/cwe-327/WeakSensitiveDataHashing.qhelp
create mode 100644 ruby/ql/src/queries/security/cwe-327/examples/weak_certificate_hashing.rb
create mode 100644 ruby/ql/src/queries/security/cwe-327/examples/weak_password_hashing_bad.rb
create mode 100644 ruby/ql/src/queries/security/cwe-327/examples/weak_password_hashing_good.rb
diff --git a/ruby/ql/src/queries/security/cwe-327/WeakSensitiveDataHashing.qhelp b/ruby/ql/src/queries/security/cwe-327/WeakSensitiveDataHashing.qhelp
new file mode 100644
index 0000000000000..422cbb835141e
--- /dev/null
+++ b/ruby/ql/src/queries/security/cwe-327/WeakSensitiveDataHashing.qhelp
@@ -0,0 +1,104 @@
+
+
+
+
+ Using a broken or weak cryptographic hash function can leave data
+ vulnerable, and should not be used in security related code.
+
+
+
+ A strong cryptographic hash function should be resistant to:
+
+
+ -
+ pre-image attacks: if you know a hash value
h(x)
,
+ you should not be able to easily find the input x
.
+
+ -
+ collision attacks: if you know a hash value
h(x)
,
+ you should not be able to easily find a different input y
+ with the same hash value h(x) = h(y)
.
+
+
+
+ In cases with a limited input space, such as for passwords, the hash
+ function also needs to be computationally expensive to be resistant to
+ brute-force attacks. Passwords should also have an unique salt applied
+ before hashing, but that is not considered by this query.
+
+
+
+ As an example, both MD5 and SHA-1 are known to be vulnerable to collision attacks.
+
+
+
+ Since it's OK to use a weak cryptographic hash function in a non-security
+ context, this query only alerts when these are used to hash sensitive
+ data (such as passwords, certificates, usernames).
+
+
+
+ Use of broken or weak cryptographic algorithms that are not hashing algorithms, is
+ handled by the rb/weak-cryptographic-algorithm
query.
+
+
+
+
+
+
+ Ensure that you use a strong, modern cryptographic hash function:
+
+
+
+ -
+ such as Argon2, scrypt, bcrypt, or PBKDF2 for passwords and other data with limited input space.
+
+ -
+ such as SHA-2, or SHA-3 in other cases.
+
+
+
+
+
+
+
+ The following example shows two functions for checking whether the hash
+ of a certificate matches a known value -- to prevent tampering.
+
+ The first function uses MD5 that is known to be vulnerable to collision attacks.
+
+ The second function uses SHA-256 that is a strong cryptographic hashing function.
+
+
+
+
+
+
+
+ The following example shows two functions for hashing passwords.
+
+ The first function uses SHA-256 to hash passwords. Although SHA-256 is a
+ strong cryptographic hash function, it is not suitable for password
+ hashing since it is not computationally expensive.
+
+
+
+
+
+
+ The second function uses Argon2 (through the argon2
+ gem), which is a strong password hashing algorithm (and
+ includes a per-password salt by default).
+
+
+
+
+
+
+
+ OWASP: Password Storage Cheat Sheet
+
+
+
diff --git a/ruby/ql/src/queries/security/cwe-327/examples/weak_certificate_hashing.rb b/ruby/ql/src/queries/security/cwe-327/examples/weak_certificate_hashing.rb
new file mode 100644
index 0000000000000..f2456a42b0741
--- /dev/null
+++ b/ruby/ql/src/queries/security/cwe-327/examples/weak_certificate_hashing.rb
@@ -0,0 +1,11 @@
+require 'openssl'
+
+def certificate_matches_known_hash_bad(certificate, known_hash)
+ hash = OpenSSL::Digest.new('SHA1').digest certificate
+ hash == known_hash
+end
+
+def certificate_matches_known_hash_good(certificate, known_hash)
+ hash = OpenSSL::Digest.new('SHA256').digest certificate
+ hash == known_hash
+end
diff --git a/ruby/ql/src/queries/security/cwe-327/examples/weak_password_hashing_bad.rb b/ruby/ql/src/queries/security/cwe-327/examples/weak_password_hashing_bad.rb
new file mode 100644
index 0000000000000..db0968f0c3b55
--- /dev/null
+++ b/ruby/ql/src/queries/security/cwe-327/examples/weak_password_hashing_bad.rb
@@ -0,0 +1,5 @@
+require 'openssl'
+
+def get_password_hash(password, salt)
+ OpenSSL::Digest.new('SHA256').digest(password + salt) # BAD
+end
diff --git a/ruby/ql/src/queries/security/cwe-327/examples/weak_password_hashing_good.rb b/ruby/ql/src/queries/security/cwe-327/examples/weak_password_hashing_good.rb
new file mode 100644
index 0000000000000..37a18753aee76
--- /dev/null
+++ b/ruby/ql/src/queries/security/cwe-327/examples/weak_password_hashing_good.rb
@@ -0,0 +1,9 @@
+require 'argon2'
+
+def get_initial_hash(password)
+ Argon2::Password.create(password)
+end
+
+def check_password(password, known_hash)
+ Argon2::Password.verify_password(password, known_hash)
+end
From 6a46fb54c532ded6dfe175e7b7011fb4f2d60546 Mon Sep 17 00:00:00 2001
From: Alex Ford
Date: Tue, 18 Jun 2024 12:11:28 +0100
Subject: [PATCH 006/140] Ruby: Add SensitiveDataSource abstract class
---
.../codeql/ruby/security/SensitiveActions.qll | 76 +++++++++++++++++++
...WeakSensitiveDataHashingCustomizations.qll | 10 +--
2 files changed, 81 insertions(+), 5 deletions(-)
diff --git a/ruby/ql/lib/codeql/ruby/security/SensitiveActions.qll b/ruby/ql/lib/codeql/ruby/security/SensitiveActions.qll
index 091ac7efdfd64..2d2963c921949 100644
--- a/ruby/ql/lib/codeql/ruby/security/SensitiveActions.qll
+++ b/ruby/ql/lib/codeql/ruby/security/SensitiveActions.qll
@@ -224,3 +224,79 @@ class AuthorizationCall extends SensitiveAction, DataFlow::CallNode {
)
}
}
+
+/**
+ * A data flow source of sensitive data, such as secrets, certificates, or passwords.
+ *
+ * Extend this class to refine existing API models. If you want to model new APIs,
+ * extend `SensitiveDataSource::Range` instead.
+ */
+class SensitiveDataSource extends DataFlow::Node instanceof SensitiveDataSource::Range {
+ /**
+ * Gets the classification of the sensitive data.
+ */
+ SensitiveDataClassification getClassification() { result = super.getClassification() }
+}
+
+/** Provides a class for modeling new sources of sensitive data, such as secrets, certificates, or passwords. */
+module SensitiveDataSource {
+ /**
+ * A data flow source of sensitive data, such as secrets, certificates, or passwords.
+ *
+ * Extend this class to model new APIs. If you want to refine existing API models,
+ * extend `SensitiveDataSource` instead.
+ */
+ abstract class Range extends DataFlow::Node {
+ /**
+ * Gets the classification of the sensitive data.
+ */
+ abstract SensitiveDataClassification getClassification();
+ }
+}
+
+/**
+ * A call to a method that may return sensitive data.
+ */
+class SensitiveMethodCall extends SensitiveDataSource::Range, DataFlow::CallNode instanceof SensitiveNode
+{
+ SensitiveDataMethodName methodName;
+
+ SensitiveMethodCall() { methodName = this.getMethodName() }
+
+ override SensitiveDataClassification getClassification() {
+ result = methodName.getClassification()
+ }
+}
+
+/**
+ * An assignment to a variable that may contain sensitive data.
+ */
+class SensitiveVariableAssignment extends SensitiveDataSource::Range instanceof BasicSensitiveWrite {
+ override SensitiveDataClassification getClassification() {
+ result = BasicSensitiveWrite.super.getClassification()
+ }
+}
+
+/**
+ * A read from a hash value that may return sensitive data.
+ */
+class SensitiveHashValueAccess extends SensitiveDataSource::Range instanceof BasicSensitiveVariableAccess
+{
+ SensitiveHashValueAccess() {
+ this.asExpr() instanceof CfgNodes::ExprNodes::ElementReferenceCfgNode
+ }
+
+ override SensitiveDataClassification getClassification() {
+ result = BasicSensitiveVariableAccess.super.getClassification()
+ }
+}
+
+/**
+ * A parameter node that may contain sensitive data.
+ */
+class SensitiveParameter extends SensitiveDataSource::Range, DataFlow::ParameterNode instanceof SensitiveNode
+{
+ override SensitiveDataClassification getClassification() {
+ result = SensitiveNode.super.getClassification()
+ }
+}
diff --git a/ruby/ql/lib/codeql/ruby/security/WeakSensitiveDataHashingCustomizations.qll b/ruby/ql/lib/codeql/ruby/security/WeakSensitiveDataHashingCustomizations.qll
index b1a6e8c801cbb..119f01979c045 100644
--- a/ruby/ql/lib/codeql/ruby/security/WeakSensitiveDataHashingCustomizations.qll
+++ b/ruby/ql/lib/codeql/ruby/security/WeakSensitiveDataHashingCustomizations.qll
@@ -49,9 +49,9 @@ module NormalHashFunction {
/**
* A source of sensitive data, considered as a flow source.
*/
- class SensitiveNodeSourceAsSource extends Source instanceof SensitiveNode {
+ class SensitiveDataSourceAsSource extends Source instanceof SensitiveDataSource {
override SensitiveDataClassification getClassification() {
- result = SensitiveNode.super.getClassification()
+ result = SensitiveDataSource.super.getClassification()
}
}
@@ -118,13 +118,13 @@ module ComputationallyExpensiveHashFunction {
/**
* A source of passwords, considered as a flow source.
*/
- class PasswordSourceAsSource extends Source instanceof SensitiveNode {
+ class PasswordSourceAsSource extends Source instanceof SensitiveDataSource {
PasswordSourceAsSource() {
- this.(SensitiveNode).getClassification() = SensitiveDataClassification::password()
+ this.(SensitiveDataSource).getClassification() = SensitiveDataClassification::password()
}
override SensitiveDataClassification getClassification() {
- result = SensitiveNode.super.getClassification()
+ result = SensitiveDataSource.super.getClassification()
}
}
From f217de962387c008228e2aaf6496d5033ea4e6e9 Mon Sep 17 00:00:00 2001
From: Alex Ford
Date: Tue, 18 Jun 2024 16:58:30 +0100
Subject: [PATCH 007/140] Ruby: Move SensitiveDataSource logic into a private
module
---
.../codeql/ruby/security/SensitiveActions.qll | 76 ---------------
...WeakSensitiveDataHashingCustomizations.qll | 94 ++++++++++++++++++-
2 files changed, 89 insertions(+), 81 deletions(-)
diff --git a/ruby/ql/lib/codeql/ruby/security/SensitiveActions.qll b/ruby/ql/lib/codeql/ruby/security/SensitiveActions.qll
index 2d2963c921949..091ac7efdfd64 100644
--- a/ruby/ql/lib/codeql/ruby/security/SensitiveActions.qll
+++ b/ruby/ql/lib/codeql/ruby/security/SensitiveActions.qll
@@ -224,79 +224,3 @@ class AuthorizationCall extends SensitiveAction, DataFlow::CallNode {
)
}
}
-
-/**
- * A data flow source of sensitive data, such as secrets, certificates, or passwords.
- *
- * Extend this class to refine existing API models. If you want to model new APIs,
- * extend `SensitiveDataSource::Range` instead.
- */
-class SensitiveDataSource extends DataFlow::Node instanceof SensitiveDataSource::Range {
- /**
- * Gets the classification of the sensitive data.
- */
- SensitiveDataClassification getClassification() { result = super.getClassification() }
-}
-
-/** Provides a class for modeling new sources of sensitive data, such as secrets, certificates, or passwords. */
-module SensitiveDataSource {
- /**
- * A data flow source of sensitive data, such as secrets, certificates, or passwords.
- *
- * Extend this class to model new APIs. If you want to refine existing API models,
- * extend `SensitiveDataSource` instead.
- */
- abstract class Range extends DataFlow::Node {
- /**
- * Gets the classification of the sensitive data.
- */
- abstract SensitiveDataClassification getClassification();
- }
-}
-
-/**
- * A call to a method that may return sensitive data.
- */
-class SensitiveMethodCall extends SensitiveDataSource::Range, DataFlow::CallNode instanceof SensitiveNode
-{
- SensitiveDataMethodName methodName;
-
- SensitiveMethodCall() { methodName = this.getMethodName() }
-
- override SensitiveDataClassification getClassification() {
- result = methodName.getClassification()
- }
-}
-
-/**
- * An assignment to a variable that may contain sensitive data.
- */
-class SensitiveVariableAssignment extends SensitiveDataSource::Range instanceof BasicSensitiveWrite {
- override SensitiveDataClassification getClassification() {
- result = BasicSensitiveWrite.super.getClassification()
- }
-}
-
-/**
- * A read from a hash value that may return sensitive data.
- */
-class SensitiveHashValueAccess extends SensitiveDataSource::Range instanceof BasicSensitiveVariableAccess
-{
- SensitiveHashValueAccess() {
- this.asExpr() instanceof CfgNodes::ExprNodes::ElementReferenceCfgNode
- }
-
- override SensitiveDataClassification getClassification() {
- result = BasicSensitiveVariableAccess.super.getClassification()
- }
-}
-
-/**
- * A parameter node that may contain sensitive data.
- */
-class SensitiveParameter extends SensitiveDataSource::Range, DataFlow::ParameterNode instanceof SensitiveNode
-{
- override SensitiveDataClassification getClassification() {
- result = SensitiveNode.super.getClassification()
- }
-}
diff --git a/ruby/ql/lib/codeql/ruby/security/WeakSensitiveDataHashingCustomizations.qll b/ruby/ql/lib/codeql/ruby/security/WeakSensitiveDataHashingCustomizations.qll
index 119f01979c045..4397f1f0c1f63 100644
--- a/ruby/ql/lib/codeql/ruby/security/WeakSensitiveDataHashingCustomizations.qll
+++ b/ruby/ql/lib/codeql/ruby/security/WeakSensitiveDataHashingCustomizations.qll
@@ -9,6 +9,88 @@ private import codeql.ruby.Concepts
private import codeql.ruby.security.SensitiveActions
private import codeql.ruby.dataflow.BarrierGuards
+private module SensitiveDataSources {
+ /**
+ * A data flow source of sensitive data, such as secrets, certificates, or passwords.
+ *
+ * Extend this class to refine existing API models. If you want to model new APIs,
+ * extend `SensitiveDataSource::Range` instead.
+ */
+ class SensitiveDataSource extends DataFlow::Node instanceof SensitiveDataSource::Range {
+ /**
+ * Gets the classification of the sensitive data.
+ */
+ SensitiveDataClassification getClassification() { result = super.getClassification() }
+ }
+
+ /** Provides a class for modeling new sources of sensitive data, such as secrets, certificates, or passwords. */
+ module SensitiveDataSource {
+ /**
+ * A data flow source of sensitive data, such as secrets, certificates, or passwords.
+ *
+ * Extend this class to model new APIs. If you want to refine existing API models,
+ * extend `SensitiveDataSource` instead.
+ */
+ abstract class Range extends DataFlow::Node {
+ /**
+ * Gets the classification of the sensitive data.
+ */
+ abstract SensitiveDataClassification getClassification();
+ }
+ }
+
+ /**
+ * A call to a method that may return sensitive data.
+ */
+ class SensitiveMethodCall extends SensitiveDataSource::Range, DataFlow::CallNode instanceof SensitiveNode
+ {
+ SensitiveDataMethodName methodName;
+
+ SensitiveMethodCall() { methodName = this.getMethodName() }
+
+ override SensitiveDataClassification getClassification() {
+ result = methodName.getClassification()
+ }
+ }
+
+ /**
+ * An assignment to a variable that may contain sensitive data.
+ */
+ class SensitiveVariableAssignment extends SensitiveDataSource::Range instanceof SensitiveNode {
+ SensitiveVariableAssignment() {
+ this.(DataFlow::VariableAccessNode).asVariableAccessAstNode() instanceof
+ Ast::VariableWriteAccess
+ }
+
+ override SensitiveDataClassification getClassification() {
+ result = SensitiveNode.super.getClassification()
+ }
+ }
+
+ /**
+ * A read from a hash value that may return sensitive data.
+ */
+ class SensitiveHashValueAccess extends SensitiveDataSource::Range instanceof SensitiveNode {
+ SensitiveHashValueAccess() {
+ this.asExpr() instanceof Cfg::CfgNodes::ExprNodes::ElementReferenceCfgNode
+ }
+
+ override SensitiveDataClassification getClassification() {
+ result = SensitiveNode.super.getClassification()
+ }
+ }
+
+ /**
+ * A parameter node that may contain sensitive data.
+ */
+ class SensitiveParameter extends SensitiveDataSource::Range, DataFlow::ParameterNode instanceof SensitiveNode
+ {
+ override SensitiveDataClassification getClassification() {
+ result = SensitiveNode.super.getClassification()
+ }
+ }
+}
+
/**
* Provides default sources, sinks and sanitizers for detecting
* "use of a broken or weak cryptographic hashing algorithm on sensitive data"
@@ -49,9 +131,10 @@ module NormalHashFunction {
/**
* A source of sensitive data, considered as a flow source.
*/
- class SensitiveDataSourceAsSource extends Source instanceof SensitiveDataSource {
+ class SensitiveDataSourceAsSource extends Source instanceof SensitiveDataSources::SensitiveDataSource
+ {
override SensitiveDataClassification getClassification() {
- result = SensitiveDataSource.super.getClassification()
+ result = SensitiveDataSources::SensitiveDataSource.super.getClassification()
}
}
@@ -118,13 +201,14 @@ module ComputationallyExpensiveHashFunction {
/**
* A source of passwords, considered as a flow source.
*/
- class PasswordSourceAsSource extends Source instanceof SensitiveDataSource {
+ class PasswordSourceAsSource extends Source instanceof SensitiveDataSources::SensitiveDataSource {
PasswordSourceAsSource() {
- this.(SensitiveDataSource).getClassification() = SensitiveDataClassification::password()
+ this.(SensitiveDataSources::SensitiveDataSource).getClassification() =
+ SensitiveDataClassification::password()
}
override SensitiveDataClassification getClassification() {
- result = SensitiveDataSource.super.getClassification()
+ result = SensitiveDataSources::SensitiveDataSource.super.getClassification()
}
}
From 81ec6861f9518a058fe582f01cfc887d920922e2 Mon Sep 17 00:00:00 2001
From: Alex Ford
Date: Tue, 18 Jun 2024 17:46:52 +0100
Subject: [PATCH 008/140] Ruby: fix some SensitiveDataSource definitions
---
...WeakSensitiveDataHashingCustomizations.qll | 19 ++++++++-----------
1 file changed, 8 insertions(+), 11 deletions(-)
diff --git a/ruby/ql/lib/codeql/ruby/security/WeakSensitiveDataHashingCustomizations.qll b/ruby/ql/lib/codeql/ruby/security/WeakSensitiveDataHashingCustomizations.qll
index 4397f1f0c1f63..92ba8492c5ac4 100644
--- a/ruby/ql/lib/codeql/ruby/security/WeakSensitiveDataHashingCustomizations.qll
+++ b/ruby/ql/lib/codeql/ruby/security/WeakSensitiveDataHashingCustomizations.qll
@@ -8,6 +8,7 @@ private import ruby
private import codeql.ruby.Concepts
private import codeql.ruby.security.SensitiveActions
private import codeql.ruby.dataflow.BarrierGuards
+private import codeql.ruby.dataflow.SSA
private module SensitiveDataSources {
/**
@@ -42,28 +43,24 @@ private module SensitiveDataSources {
/**
* A call to a method that may return sensitive data.
*/
- class SensitiveMethodCall extends SensitiveDataSource::Range, DataFlow::CallNode instanceof SensitiveNode
- {
- SensitiveDataMethodName methodName;
-
- SensitiveMethodCall() { methodName = this.getMethodName() }
-
+ class SensitiveMethodCall extends SensitiveDataSource::Range instanceof SensitiveCall {
override SensitiveDataClassification getClassification() {
- result = methodName.getClassification()
+ result = SensitiveCall.super.getClassification()
}
}
/**
* An assignment to a variable that may contain sensitive data.
*/
- class SensitiveVariableAssignment extends SensitiveDataSource::Range instanceof SensitiveNode {
+ class SensitiveVariableAssignment extends SensitiveDataSource::Range, DataFlow::SsaDefinitionNode {
+ SensitiveNode sensitiveNode;
+
SensitiveVariableAssignment() {
- this.(DataFlow::VariableAccessNode).asVariableAccessAstNode() instanceof
- Ast::VariableWriteAccess
+ this.getDefinition().(Ssa::WriteDefinition).getWriteAccess() = sensitiveNode.asExpr()
}
override SensitiveDataClassification getClassification() {
- result = SensitiveNode.super.getClassification()
+ result = sensitiveNode.getClassification()
}
}
From d994959720e7ada947eb54b3f9ebd01993acf38d Mon Sep 17 00:00:00 2001
From: Alex Ford
Date: Tue, 18 Jun 2024 17:47:32 +0100
Subject: [PATCH 009/140] Ruby: add tests for rb/weak-sensitive-data-hashing
---
.../cwe-327/WeakSensitiveDataHashing.expected | 28 ++++++++++++++++
.../cwe-327/WeakSensitiveDataHashing.qlref | 1 +
.../security/cwe-327/weak_hashing.rb | 33 +++++++++++++++++++
3 files changed, 62 insertions(+)
create mode 100644 ruby/ql/test/query-tests/security/cwe-327/WeakSensitiveDataHashing.expected
create mode 100644 ruby/ql/test/query-tests/security/cwe-327/WeakSensitiveDataHashing.qlref
create mode 100644 ruby/ql/test/query-tests/security/cwe-327/weak_hashing.rb
diff --git a/ruby/ql/test/query-tests/security/cwe-327/WeakSensitiveDataHashing.expected b/ruby/ql/test/query-tests/security/cwe-327/WeakSensitiveDataHashing.expected
new file mode 100644
index 0000000000000..0ad72554019fa
--- /dev/null
+++ b/ruby/ql/test/query-tests/security/cwe-327/WeakSensitiveDataHashing.expected
@@ -0,0 +1,28 @@
+edges
+| weak_hashing.rb:3:1:3:8 | password | weak_hashing.rb:6:1:6:1 | x | provenance | |
+| weak_hashing.rb:3:1:3:8 | password | weak_hashing.rb:10:23:10:30 | password | provenance | |
+| weak_hashing.rb:3:1:3:8 | password | weak_hashing.rb:11:32:11:39 | password | provenance | |
+| weak_hashing.rb:4:1:4:8 | username | weak_hashing.rb:12:23:12:30 | username | provenance | |
+| weak_hashing.rb:6:1:6:1 | x | weak_hashing.rb:13:23:13:23 | x | provenance | |
+| weak_hashing.rb:30:25:30:38 | password_param | weak_hashing.rb:32:25:32:38 | password_param | provenance | |
+nodes
+| weak_hashing.rb:3:1:3:8 | password | semmle.label | password |
+| weak_hashing.rb:4:1:4:8 | username | semmle.label | username |
+| weak_hashing.rb:6:1:6:1 | x | semmle.label | x |
+| weak_hashing.rb:10:23:10:30 | password | semmle.label | password |
+| weak_hashing.rb:11:32:11:39 | password | semmle.label | password |
+| weak_hashing.rb:12:23:12:30 | username | semmle.label | username |
+| weak_hashing.rb:13:23:13:23 | x | semmle.label | x |
+| weak_hashing.rb:24:23:24:36 | call to get_password | semmle.label | call to get_password |
+| weak_hashing.rb:28:23:28:42 | ...[...] | semmle.label | ...[...] |
+| weak_hashing.rb:30:25:30:38 | password_param | semmle.label | password_param |
+| weak_hashing.rb:32:25:32:38 | password_param | semmle.label | password_param |
+subpaths
+#select
+| weak_hashing.rb:10:23:10:30 | password | weak_hashing.rb:3:1:3:8 | password | weak_hashing.rb:10:23:10:30 | password | $@ is used in a hashing algorithm (MD5) that is insecure for password hashing, since it is not a computationally expensive hash function. | weak_hashing.rb:3:1:3:8 | password | Sensitive data (password) |
+| weak_hashing.rb:11:32:11:39 | password | weak_hashing.rb:3:1:3:8 | password | weak_hashing.rb:11:32:11:39 | password | $@ is used in a hashing algorithm (SHA1) that is insecure for password hashing, since it is not a computationally expensive hash function. | weak_hashing.rb:3:1:3:8 | password | Sensitive data (password) |
+| weak_hashing.rb:12:23:12:30 | username | weak_hashing.rb:4:1:4:8 | username | weak_hashing.rb:12:23:12:30 | username | $@ is used in a hashing algorithm (MD5) that is insecure. | weak_hashing.rb:4:1:4:8 | username | Sensitive data (id) |
+| weak_hashing.rb:13:23:13:23 | x | weak_hashing.rb:3:1:3:8 | password | weak_hashing.rb:13:23:13:23 | x | $@ is used in a hashing algorithm (MD5) that is insecure for password hashing, since it is not a computationally expensive hash function. | weak_hashing.rb:3:1:3:8 | password | Sensitive data (password) |
+| weak_hashing.rb:24:23:24:36 | call to get_password | weak_hashing.rb:24:23:24:36 | call to get_password | weak_hashing.rb:24:23:24:36 | call to get_password | $@ is used in a hashing algorithm (MD5) that is insecure for password hashing, since it is not a computationally expensive hash function. | weak_hashing.rb:24:23:24:36 | call to get_password | Sensitive data (password) |
+| weak_hashing.rb:28:23:28:42 | ...[...] | weak_hashing.rb:28:23:28:42 | ...[...] | weak_hashing.rb:28:23:28:42 | ...[...] | $@ is used in a hashing algorithm (MD5) that is insecure for password hashing, since it is not a computationally expensive hash function. | weak_hashing.rb:28:23:28:42 | ...[...] | Sensitive data (password) |
+| weak_hashing.rb:32:25:32:38 | password_param | weak_hashing.rb:30:25:30:38 | password_param | weak_hashing.rb:32:25:32:38 | password_param | $@ is used in a hashing algorithm (MD5) that is insecure for password hashing, since it is not a computationally expensive hash function. | weak_hashing.rb:30:25:30:38 | password_param | Sensitive data (password) |
diff --git a/ruby/ql/test/query-tests/security/cwe-327/WeakSensitiveDataHashing.qlref b/ruby/ql/test/query-tests/security/cwe-327/WeakSensitiveDataHashing.qlref
new file mode 100644
index 0000000000000..dcb5a4e62a7e5
--- /dev/null
+++ b/ruby/ql/test/query-tests/security/cwe-327/WeakSensitiveDataHashing.qlref
@@ -0,0 +1 @@
+queries/security/cwe-327/WeakSensitiveDataHashing.ql
\ No newline at end of file
diff --git a/ruby/ql/test/query-tests/security/cwe-327/weak_hashing.rb b/ruby/ql/test/query-tests/security/cwe-327/weak_hashing.rb
new file mode 100644
index 0000000000000..b7dfd44e7af93
--- /dev/null
+++ b/ruby/ql/test/query-tests/security/cwe-327/weak_hashing.rb
@@ -0,0 +1,33 @@
+require 'openssl'
+
+password = "abcde"
+username = "some_user"
+some_data = "foo"
+x = password
+
+Digest::MD5.hexdigest(some_data) # OK: input is not sensitive
+Digest::SHA256.hexdigest(password) # OK: strong hash algorithm
+Digest::MD5.hexdigest(password) # BAD: weak hash function used for sensitive data
+OpenSSL::Digest.digest('SHA1', password) # BAD: weak hash function used for sensitive data
+Digest::MD5.hexdigest(username) # BAD: weak hash function used for sensitive data
+Digest::MD5.hexdigest(x) # BAD: weak hash function used for sensitive data
+
+def get_safe_data()
+ return "hello"
+end
+def get_password()
+ return "changeme"
+end
+
+# FIXME
+Digest::MD5.hexdigest(get_safe_data()) # OK: input is not sensitive
+Digest::MD5.hexdigest(get_password()) # BAD: weak hash function used for sensitive data
+
+some_hash = {password: "changeme", foo: "bar"}
+Digest::MD5.hexdigest(some_hash[:foo]) # OK: input is not sensitive
+Digest::MD5.hexdigest(some_hash[:password]) # BAD: weak hash function used for sensitive data
+
+def a_method(safe_data, password_param)
+ Digest::MD5.hexdigest(safe_data) # OK: input is not sensitive
+ Digest::MD5.hexdigest(password_param) # BAD: weak hash function used for sensitive data
+end
From 7380e297743e11c2e2c5db7f152007e7e49f825d Mon Sep 17 00:00:00 2001
From: Alex Ford
Date: Tue, 18 Jun 2024 17:48:51 +0100
Subject: [PATCH 010/140] Ruby: changenote for rb/weak-sensitive-data-hashing
---
.../2024-06-18-weak-sensitive-data-hashing-query.md | 4 ++++
1 file changed, 4 insertions(+)
create mode 100644 ruby/ql/src/change-notes/2024-06-18-weak-sensitive-data-hashing-query.md
diff --git a/ruby/ql/src/change-notes/2024-06-18-weak-sensitive-data-hashing-query.md b/ruby/ql/src/change-notes/2024-06-18-weak-sensitive-data-hashing-query.md
new file mode 100644
index 0000000000000..6fffd21d616c6
--- /dev/null
+++ b/ruby/ql/src/change-notes/2024-06-18-weak-sensitive-data-hashing-query.md
@@ -0,0 +1,4 @@
+---
+category: newQuery
+---
+* Added a new query, `rb/weak-sensitive-data-hashing`, to detect cases where sensitive data is hashed using a weak cryptographic hashing algorithm.
From d79a253c2083a333cf01e693a4eb2961522c5f28 Mon Sep 17 00:00:00 2001
From: Alex Ford
Date: Tue, 18 Jun 2024 17:49:14 +0100
Subject: [PATCH 011/140] Ruby: remove unused import
---
ruby/ql/lib/codeql/ruby/security/SensitiveActions.qll | 1 -
1 file changed, 1 deletion(-)
diff --git a/ruby/ql/lib/codeql/ruby/security/SensitiveActions.qll b/ruby/ql/lib/codeql/ruby/security/SensitiveActions.qll
index 091ac7efdfd64..34beb33604b72 100644
--- a/ruby/ql/lib/codeql/ruby/security/SensitiveActions.qll
+++ b/ruby/ql/lib/codeql/ruby/security/SensitiveActions.qll
@@ -14,7 +14,6 @@ private import codeql.ruby.DataFlow
import codeql.ruby.security.internal.SensitiveDataHeuristics
private import HeuristicNames
private import codeql.ruby.CFG
-private import codeql.ruby.typetracking.TypeTracking
/** An expression that might contain sensitive data. */
cached
From 51f3f15e42aa1ce0eedf50d0253b54a1e64d3c94 Mon Sep 17 00:00:00 2001
From: Alex Ford
Date: Tue, 18 Jun 2024 17:51:49 +0100
Subject: [PATCH 012/140] Ruby: remove outdated test comment
---
ruby/ql/test/query-tests/security/cwe-327/weak_hashing.rb | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/ruby/ql/test/query-tests/security/cwe-327/weak_hashing.rb b/ruby/ql/test/query-tests/security/cwe-327/weak_hashing.rb
index b7dfd44e7af93..cff4263c40d86 100644
--- a/ruby/ql/test/query-tests/security/cwe-327/weak_hashing.rb
+++ b/ruby/ql/test/query-tests/security/cwe-327/weak_hashing.rb
@@ -15,11 +15,11 @@
def get_safe_data()
return "hello"
end
+
def get_password()
return "changeme"
end
-# FIXME
Digest::MD5.hexdigest(get_safe_data()) # OK: input is not sensitive
Digest::MD5.hexdigest(get_password()) # BAD: weak hash function used for sensitive data
From 91db2b6c9c95c756a6174133888af5ad880ebe79 Mon Sep 17 00:00:00 2001
From: Owen Mansel-Chan
Date: Fri, 14 Jun 2024 13:23:17 +0100
Subject: [PATCH 013/140] Make new threat model kind "reverse-dns"
---
.../semmle/code/java/dataflow/FlowSources.qll | 33 ++++++++++---------
1 file changed, 18 insertions(+), 15 deletions(-)
diff --git a/java/ql/lib/semmle/code/java/dataflow/FlowSources.qll b/java/ql/lib/semmle/code/java/dataflow/FlowSources.qll
index f2b2f8c20086b..93a3a4a322b98 100644
--- a/java/ql/lib/semmle/code/java/dataflow/FlowSources.qll
+++ b/java/ql/lib/semmle/code/java/dataflow/FlowSources.qll
@@ -119,21 +119,6 @@ private predicate variableStep(Expr tracked, VarAccess sink) {
)
}
-private class ReverseDnsSource extends RemoteFlowSource {
- ReverseDnsSource() {
- // Try not to trigger on `localhost`.
- exists(MethodCall m | m = this.asExpr() |
- m.getMethod() instanceof ReverseDnsMethod and
- not exists(MethodCall l |
- (variableStep(l, m.getQualifier()) or l = m.getQualifier()) and
- (l.getMethod().getName() = "getLocalHost" or l.getMethod().getName() = "getLoopbackAddress")
- )
- )
- }
-
- override string getSourceType() { result = "reverse DNS lookup" }
-}
-
private class MessageBodyReaderParameterSource extends RemoteFlowSource {
MessageBodyReaderParameterSource() {
exists(MessageBodyReaderRead m |
@@ -388,6 +373,24 @@ class AndroidJavascriptInterfaceMethodParameter extends RemoteFlowSource {
}
}
+/** A node with input that may be controlled by a local user. */
+abstract class ReverseDnsUserInput extends UserInput {
+ override string getThreatModel() { result = "reverse-dns" }
+}
+
+private class ReverseDnsSource extends ReverseDnsUserInput {
+ ReverseDnsSource() {
+ // Try not to trigger on `localhost`.
+ exists(MethodCall m | m = this.asExpr() |
+ m.getMethod() instanceof ReverseDnsMethod and
+ not exists(MethodCall l |
+ (variableStep(l, m.getQualifier()) or l = m.getQualifier()) and
+ (l.getMethod().getName() = "getLocalHost" or l.getMethod().getName() = "getLoopbackAddress")
+ )
+ )
+ }
+}
+
/**
* A data flow source node for an API, which should be considered
* supported for a modeling perspective.
From 878867205ef42614cc230fd53abdc32eb3e99e2b Mon Sep 17 00:00:00 2001
From: Owen Mansel-Chan
Date: Fri, 14 Jun 2024 15:47:15 +0100
Subject: [PATCH 014/140] Fix taintsources test
---
.../dataflow/taintsources/A.java | 2 +-
.../dataflow/taintsources/local.ql | 8 +---
.../dataflow/taintsources/reversedns.expected | 2 +
.../dataflow/taintsources/reversedns.ql | 47 +++++++++++++++++++
4 files changed, 52 insertions(+), 7 deletions(-)
create mode 100644 java/ql/test/library-tests/dataflow/taintsources/reversedns.expected
create mode 100644 java/ql/test/library-tests/dataflow/taintsources/reversedns.ql
diff --git a/java/ql/test/library-tests/dataflow/taintsources/A.java b/java/ql/test/library-tests/dataflow/taintsources/A.java
index 25320b315ad50..6b91a4ca1bfe3 100644
--- a/java/ql/test/library-tests/dataflow/taintsources/A.java
+++ b/java/ql/test/library-tests/dataflow/taintsources/A.java
@@ -43,7 +43,7 @@ public void test(ResultSet rs) throws SQLException {
};
sink(new URL("test").openConnection().getInputStream()); // $hasRemoteValueFlow
sink(new Socket("test", 1234).getInputStream()); // $hasRemoteValueFlow
- sink(InetAddress.getByName("test").getHostName()); // $hasRemoteValueFlow
+ sink(InetAddress.getByName("test").getHostName()); // $hasReverseDnsValueFlow
sink(System.in); // $hasLocalValueFlow
sink(new FileInputStream("test")); // $hasLocalValueFlow
diff --git a/java/ql/test/library-tests/dataflow/taintsources/local.ql b/java/ql/test/library-tests/dataflow/taintsources/local.ql
index 1cbe8dbbf6c47..d4a08d836bb60 100644
--- a/java/ql/test/library-tests/dataflow/taintsources/local.ql
+++ b/java/ql/test/library-tests/dataflow/taintsources/local.ql
@@ -2,16 +2,12 @@ import java
import semmle.code.java.dataflow.FlowSources
import TestUtilities.InlineExpectationsTest
-class LocalSource extends DataFlow::Node instanceof UserInput {
- LocalSource() { not this instanceof RemoteFlowSource }
-}
-
predicate isTestSink(DataFlow::Node n) {
exists(MethodCall ma | ma.getMethod().hasName("sink") | n.asExpr() = ma.getAnArgument())
}
module LocalValueConfig implements DataFlow::ConfigSig {
- predicate isSource(DataFlow::Node n) { n instanceof LocalSource }
+ predicate isSource(DataFlow::Node n) { n instanceof LocalUserInput }
predicate isSink(DataFlow::Node n) { isTestSink(n) }
}
@@ -19,7 +15,7 @@ module LocalValueConfig implements DataFlow::ConfigSig {
module LocalValueFlow = DataFlow::Global;
module LocalTaintConfig implements DataFlow::ConfigSig {
- predicate isSource(DataFlow::Node n) { n instanceof LocalSource }
+ predicate isSource(DataFlow::Node n) { n instanceof LocalUserInput }
predicate isSink(DataFlow::Node n) { isTestSink(n) }
}
diff --git a/java/ql/test/library-tests/dataflow/taintsources/reversedns.expected b/java/ql/test/library-tests/dataflow/taintsources/reversedns.expected
new file mode 100644
index 0000000000000..48de9172b362f
--- /dev/null
+++ b/java/ql/test/library-tests/dataflow/taintsources/reversedns.expected
@@ -0,0 +1,2 @@
+failures
+testFailures
diff --git a/java/ql/test/library-tests/dataflow/taintsources/reversedns.ql b/java/ql/test/library-tests/dataflow/taintsources/reversedns.ql
new file mode 100644
index 0000000000000..8ec5acab5e54a
--- /dev/null
+++ b/java/ql/test/library-tests/dataflow/taintsources/reversedns.ql
@@ -0,0 +1,47 @@
+import java
+import semmle.code.java.dataflow.FlowSources
+import TestUtilities.InlineExpectationsTest
+
+predicate isTestSink(DataFlow::Node n) {
+ exists(MethodCall ma | ma.getMethod().hasName("sink") | n.asExpr() = ma.getAnArgument())
+}
+
+module ReverseDnsValueConfig implements DataFlow::ConfigSig {
+ predicate isSource(DataFlow::Node n) { n instanceof ReverseDnsUserInput }
+
+ predicate isSink(DataFlow::Node n) { isTestSink(n) }
+}
+
+module ReverseDnsValueFlow = DataFlow::Global;
+
+module ReverseDnsTaintConfig implements DataFlow::ConfigSig {
+ predicate isSource(DataFlow::Node n) { n instanceof ReverseDnsUserInput }
+
+ predicate isSink(DataFlow::Node n) { isTestSink(n) }
+}
+
+module ReverseDnsTaintFlow = TaintTracking::Global;
+
+module ReverseDnsFlowTest implements TestSig {
+ string getARelevantTag() { result = ["hasReverseDnsValueFlow", "hasReverseDnsTaintFlow"] }
+
+ predicate hasActualResult(Location location, string element, string tag, string value) {
+ tag = "hasReverseDnsValueFlow" and
+ exists(DataFlow::Node sink | ReverseDnsValueFlow::flowTo(sink) |
+ sink.getLocation() = location and
+ element = sink.toString() and
+ value = ""
+ )
+ or
+ tag = "hasReverseDnsTaintFlow" and
+ exists(DataFlow::Node src, DataFlow::Node sink |
+ ReverseDnsTaintFlow::flow(src, sink) and not ReverseDnsValueFlow::flow(src, sink)
+ |
+ sink.getLocation() = location and
+ element = sink.toString() and
+ value = ""
+ )
+ }
+}
+
+import MakeTest
From 059ef42f412ce25216b49267c41ff9d3564d411d Mon Sep 17 00:00:00 2001
From: Owen Mansel-Chan
Date: Fri, 14 Jun 2024 13:35:27 +0100
Subject: [PATCH 015/140] Add change note
---
.../2024-06-14-reverse-dns-separate-threat-model-kind.md | 4 ++++
1 file changed, 4 insertions(+)
create mode 100644 java/ql/lib/change-notes/2024-06-14-reverse-dns-separate-threat-model-kind.md
diff --git a/java/ql/lib/change-notes/2024-06-14-reverse-dns-separate-threat-model-kind.md b/java/ql/lib/change-notes/2024-06-14-reverse-dns-separate-threat-model-kind.md
new file mode 100644
index 0000000000000..81048da7221b9
--- /dev/null
+++ b/java/ql/lib/change-notes/2024-06-14-reverse-dns-separate-threat-model-kind.md
@@ -0,0 +1,4 @@
+---
+category: minorAnalysis
+---
+* We previously considered reverse DNS resolutions (IP address -> domain name) as sources of untrusted data, since compromised/malicious DNS servers could potentially return malicious responses to arbitrary requests. We have now removed this source from the default set of untrusted sources and made a new threat model kind for them, called "reverse-dns".
From 162245fb9a4c05da5824d6e3f3c9235fd7293a05 Mon Sep 17 00:00:00 2001
From: Owen Mansel-Chan
Date: Fri, 14 Jun 2024 16:08:32 +0100
Subject: [PATCH 016/140] Fix unrelated test using reverse DNS as source
---
.../security/CWE-022/semmle/tests/Test.java | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/java/ql/test/query-tests/security/CWE-022/semmle/tests/Test.java b/java/ql/test/query-tests/security/CWE-022/semmle/tests/Test.java
index f8b37428e25b5..d8cd210b70cfa 100644
--- a/java/ql/test/query-tests/security/CWE-022/semmle/tests/Test.java
+++ b/java/ql/test/query-tests/security/CWE-022/semmle/tests/Test.java
@@ -5,12 +5,14 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
-import java.net.InetAddress;
import java.net.URL;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
+
+import javax.servlet.http.HttpServletRequest;
import javax.xml.transform.stream.StreamResult;
+
import org.apache.commons.io.FileUtils;
import org.apache.tools.ant.AntClassLoader;
import org.apache.tools.ant.DirectoryScanner;
@@ -24,10 +26,10 @@
public class Test {
- private InetAddress address;
+ private HttpServletRequest request;
public Object source() {
- return address.getHostName();
+ return request.getParameter("source");
}
void test() throws IOException {
@@ -166,8 +168,8 @@ void test(AntClassLoader acl) {
new LargeText((File) source(), null, false, false); // $ hasTaintFlow
}
- void doGet6(String root, InetAddress address) throws IOException {
- String temp = address.getHostName();
+ void doGet6(String root, HttpServletRequest request) throws IOException {
+ String temp = request.getParameter("source");
// GOOD: Use `contains` and `startsWith` to check if the path is safe
if (!temp.contains("..") && temp.startsWith(root + "/")) {
File file = new File(temp);
From 9e25279cb82837a35f6057cb57c0a9bf6b7a849f Mon Sep 17 00:00:00 2001
From: Owen Mansel-Chan
Date: Fri, 14 Jun 2024 16:34:04 +0100
Subject: [PATCH 017/140] Change category in change note to "majorAnalysis"
---
.../2024-06-14-reverse-dns-separate-threat-model-kind.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/java/ql/lib/change-notes/2024-06-14-reverse-dns-separate-threat-model-kind.md b/java/ql/lib/change-notes/2024-06-14-reverse-dns-separate-threat-model-kind.md
index 81048da7221b9..b19e90a307ff2 100644
--- a/java/ql/lib/change-notes/2024-06-14-reverse-dns-separate-threat-model-kind.md
+++ b/java/ql/lib/change-notes/2024-06-14-reverse-dns-separate-threat-model-kind.md
@@ -1,4 +1,4 @@
---
-category: minorAnalysis
+category: majorAnalysis
---
* We previously considered reverse DNS resolutions (IP address -> domain name) as sources of untrusted data, since compromised/malicious DNS servers could potentially return malicious responses to arbitrary requests. We have now removed this source from the default set of untrusted sources and made a new threat model kind for them, called "reverse-dns".
From 8458bde51e7a81e33165906d71c97116f7e9fbde Mon Sep 17 00:00:00 2001
From: Owen Mansel-Chan
Date: Sun, 23 Jun 2024 07:09:11 +0100
Subject: [PATCH 018/140] Add comment that "reverse-dns" is an ungrouped threat
model
---
shared/threat-models/ext/threat-model-grouping.model.yml | 3 +++
1 file changed, 3 insertions(+)
diff --git a/shared/threat-models/ext/threat-model-grouping.model.yml b/shared/threat-models/ext/threat-model-grouping.model.yml
index 7cc650d334154..70493c253866b 100644
--- a/shared/threat-models/ext/threat-model-grouping.model.yml
+++ b/shared/threat-models/ext/threat-model-grouping.model.yml
@@ -21,3 +21,6 @@ extensions:
# Android threat models
- ["android-external-storage-dir", "android"]
- ["contentprovider", "android"]
+
+ # Threat models that are not grouped with any other threat models
+ # "reverse-dns"
From 60b9d19d72683cb12735a94d1dbae6a366836d4c Mon Sep 17 00:00:00 2001
From: Owen Mansel-Chan
Date: Sat, 29 Jun 2024 21:29:21 +0100
Subject: [PATCH 019/140] Add explicit relation between "reverse-dns" and "all"
---
shared/threat-models/ext/threat-model-grouping.model.yml | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/shared/threat-models/ext/threat-model-grouping.model.yml b/shared/threat-models/ext/threat-model-grouping.model.yml
index 70493c253866b..b4f67c1044547 100644
--- a/shared/threat-models/ext/threat-model-grouping.model.yml
+++ b/shared/threat-models/ext/threat-model-grouping.model.yml
@@ -22,5 +22,7 @@ extensions:
- ["android-external-storage-dir", "android"]
- ["contentprovider", "android"]
- # Threat models that are not grouped with any other threat models
- # "reverse-dns"
+ # Threat models that are not grouped with any other threat models.
+ # (Note that all threat models are a child of "all" implicitly, and we
+ # make it explicit here just to make sure all threat models are listed.)
+ - ["reverse-dns", "all"]
From 173cd13deda889fb6307713bff39e0756fdf1060 Mon Sep 17 00:00:00 2001
From: Rasmus Wriedt Larsen
Date: Mon, 8 Jul 2024 12:06:53 +0200
Subject: [PATCH 020/140] Python: Add test for impossible isinstance flow
---
.../tainttracking/isinstance/InlineTaintTest.expected | 4 ++++
.../tainttracking/isinstance/InlineTaintTest.ql | 2 ++
.../dataflow/tainttracking/isinstance/test.py | 11 +++++++++++
3 files changed, 17 insertions(+)
create mode 100644 python/ql/test/library-tests/dataflow/tainttracking/isinstance/InlineTaintTest.expected
create mode 100644 python/ql/test/library-tests/dataflow/tainttracking/isinstance/InlineTaintTest.ql
create mode 100644 python/ql/test/library-tests/dataflow/tainttracking/isinstance/test.py
diff --git a/python/ql/test/library-tests/dataflow/tainttracking/isinstance/InlineTaintTest.expected b/python/ql/test/library-tests/dataflow/tainttracking/isinstance/InlineTaintTest.expected
new file mode 100644
index 0000000000000..366de37b86775
--- /dev/null
+++ b/python/ql/test/library-tests/dataflow/tainttracking/isinstance/InlineTaintTest.expected
@@ -0,0 +1,4 @@
+argumentToEnsureNotTaintedNotMarkedAsSpurious
+untaintedArgumentToEnsureTaintedNotMarkedAsMissing
+testFailures
+failures
diff --git a/python/ql/test/library-tests/dataflow/tainttracking/isinstance/InlineTaintTest.ql b/python/ql/test/library-tests/dataflow/tainttracking/isinstance/InlineTaintTest.ql
new file mode 100644
index 0000000000000..8524da5fe7dbc
--- /dev/null
+++ b/python/ql/test/library-tests/dataflow/tainttracking/isinstance/InlineTaintTest.ql
@@ -0,0 +1,2 @@
+import experimental.meta.InlineTaintTest
+import MakeInlineTaintTest
diff --git a/python/ql/test/library-tests/dataflow/tainttracking/isinstance/test.py b/python/ql/test/library-tests/dataflow/tainttracking/isinstance/test.py
new file mode 100644
index 0000000000000..edd9eba2c243d
--- /dev/null
+++ b/python/ql/test/library-tests/dataflow/tainttracking/isinstance/test.py
@@ -0,0 +1,11 @@
+def impossible_flow(cond: bool):
+ TAINTED_STRING = "ts"
+ x = (TAINTED_STRING, 42) if cond else "SAFE"
+
+ if isinstance(x, str):
+ # tainted-flow to here is impossible, replicated from path-flow seen in a real
+ # repo.
+ ensure_not_tainted(x) # $ SPURIOUS: tainted
+ else:
+ ensure_tainted(x) # $ tainted
+ ensure_tainted(x[0]) # $ tainted
From 8526510783e450716616f16596b48f6a7c30fb1e Mon Sep 17 00:00:00 2001
From: Owen Mansel-Chan
Date: Mon, 8 Jul 2024 15:15:40 +0100
Subject: [PATCH 021/140] Add ungrouped threat models to
threat-model-grouping.model.yml
---
shared/threat-models/ext/threat-model-grouping.model.yml | 2 ++
1 file changed, 2 insertions(+)
diff --git a/shared/threat-models/ext/threat-model-grouping.model.yml b/shared/threat-models/ext/threat-model-grouping.model.yml
index b4f67c1044547..fcd27205d62ba 100644
--- a/shared/threat-models/ext/threat-model-grouping.model.yml
+++ b/shared/threat-models/ext/threat-model-grouping.model.yml
@@ -25,4 +25,6 @@ extensions:
# Threat models that are not grouped with any other threat models.
# (Note that all threat models are a child of "all" implicitly, and we
# make it explicit here just to make sure all threat models are listed.)
+ - ["database-access-result", "all"]
+ - ["file-write", "all"]
- ["reverse-dns", "all"]
From 64432215a99572ec1f20902a3136ddb7aa872988 Mon Sep 17 00:00:00 2001
From: Owen Mansel-Chan
Date: Mon, 8 Jul 2024 15:16:14 +0100
Subject: [PATCH 022/140] Make "reverse-dns" pass validation
---
shared/mad/codeql/mad/ModelValidation.qll | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/shared/mad/codeql/mad/ModelValidation.qll b/shared/mad/codeql/mad/ModelValidation.qll
index d403ecdb05324..bd2c497ea4c26 100644
--- a/shared/mad/codeql/mad/ModelValidation.qll
+++ b/shared/mad/codeql/mad/ModelValidation.qll
@@ -118,7 +118,7 @@ module KindValidation {
this =
[
// shared
- "local", "remote", "file", "commandargs", "database", "environment",
+ "local", "remote", "file", "commandargs", "database", "environment", "reverse-dns",
// Java
"android-external-storage-dir", "contentprovider",
// C#
From 07a25a233de85845e822f6cd9d1c05cf78087980 Mon Sep 17 00:00:00 2001
From: Owen Mansel-Chan
Date: Mon, 8 Jul 2024 15:32:47 +0100
Subject: [PATCH 023/140] Update threat model documentation
---
docs/codeql/reusables/threat-model-description.rst | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/docs/codeql/reusables/threat-model-description.rst b/docs/codeql/reusables/threat-model-description.rst
index 53a872487bfa2..e35db8b21c22f 100644
--- a/docs/codeql/reusables/threat-model-description.rst
+++ b/docs/codeql/reusables/threat-model-description.rst
@@ -4,7 +4,16 @@ A threat model is a named class of dataflow sources that can be enabled or disab
The ``kind`` property of the ``sourceModel`` determines which threat model a source is associated with. There are two main categories:
-- ``remote`` which represents requests and responses from the network.
-- ``local`` which represents data from local files (``file``), command-line arguments (``commandargs``), database reads (``database``), and environment variables(``environment``).
+- ``remote`` which represents requests (``request``) and responses (``response``) from the network.
+- ``local`` which represents data from local files (``file``), command-line arguments (``commandargs``), database reads (``database``), environment variables(``environment``) and Windows registry values ("windows-registry").
+
+Note that subcategories can be turned included or excluded separately, so you can specify ``local`` without ``database``, or just ``commandargs`` and ``environment`` without the rest of ``local``.
+
+The less commonly used categories are:
+
+- ``android`` which represents reads from external files in Android (``android-external-storage-dir``) and parameter of an entry-point method declared in a ``ContentProvider`` class (``contentprovider``).
+- ``database-access-result`` which represents a database access (currently only used by javascript).
+- ``file-write`` which represents opening a file in write mode (currently only used in C#).
+- ``reverse-dns`` which represents reverse DNS lookups (currently only used in java).
When running a CodeQL analysis, the ``remote`` threat model is included by default. You can optionally include other threat models as appropriate when using the CodeQL CLI and in GitHub code scanning. For more information, see `Analyzing your code with CodeQL queries `__ and `Customizing your advanced setup for code scanning `__.
From 8241d0b7efff45087a1105a1b0061ad286b06b93 Mon Sep 17 00:00:00 2001
From: Owen Mansel-Chan
Date: Mon, 8 Jul 2024 15:33:39 +0100
Subject: [PATCH 024/140] Update QLDoc for ReverseDnsUserInput
---
java/ql/lib/semmle/code/java/dataflow/FlowSources.qll | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/java/ql/lib/semmle/code/java/dataflow/FlowSources.qll b/java/ql/lib/semmle/code/java/dataflow/FlowSources.qll
index 93a3a4a322b98..c97a97f27972a 100644
--- a/java/ql/lib/semmle/code/java/dataflow/FlowSources.qll
+++ b/java/ql/lib/semmle/code/java/dataflow/FlowSources.qll
@@ -373,7 +373,7 @@ class AndroidJavascriptInterfaceMethodParameter extends RemoteFlowSource {
}
}
-/** A node with input that may be controlled by a local user. */
+/** A node with input that comes from a reverse DNS lookup. */
abstract class ReverseDnsUserInput extends UserInput {
override string getThreatModel() { result = "reverse-dns" }
}
From b83147fa44e909b0855d6a06061b40ca34ce27df Mon Sep 17 00:00:00 2001
From: Owen Mansel-Chan
Date: Mon, 8 Jul 2024 15:39:27 +0100
Subject: [PATCH 025/140] Add links on threat models to change note
---
.../2024-06-14-reverse-dns-separate-threat-model-kind.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/java/ql/lib/change-notes/2024-06-14-reverse-dns-separate-threat-model-kind.md b/java/ql/lib/change-notes/2024-06-14-reverse-dns-separate-threat-model-kind.md
index b19e90a307ff2..f5e39a0b5ea54 100644
--- a/java/ql/lib/change-notes/2024-06-14-reverse-dns-separate-threat-model-kind.md
+++ b/java/ql/lib/change-notes/2024-06-14-reverse-dns-separate-threat-model-kind.md
@@ -1,4 +1,4 @@
---
category: majorAnalysis
---
-* We previously considered reverse DNS resolutions (IP address -> domain name) as sources of untrusted data, since compromised/malicious DNS servers could potentially return malicious responses to arbitrary requests. We have now removed this source from the default set of untrusted sources and made a new threat model kind for them, called "reverse-dns".
+* We previously considered reverse DNS resolutions (IP address -> domain name) as sources of untrusted data, since compromised/malicious DNS servers could potentially return malicious responses to arbitrary requests. We have now removed this source from the default set of untrusted sources and made a new threat model kind for them, called "reverse-dns". You can optionally include other threat models as appropriate when using the CodeQL CLI and in GitHub code scanning. For more information, see [Analyzing your code with CodeQL queries](https://docs.github.com/code-security/codeql-cli/getting-started-with-the-codeql-cli/analyzing-your-code-with-codeql-queries#including-model-packs-to-add-potential-sources-of-tainted-data>) and [Customizing your advanced setup for code scanning](https://docs.github.com/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning#extending-codeql-coverage-with-threat-models).
From d4bfab47352868e3313b66a3d724135a25110865 Mon Sep 17 00:00:00 2001
From: Owen Mansel-Chan
Date: Tue, 9 Jul 2024 07:00:01 +0100
Subject: [PATCH 026/140] Accept minor copy-editing suggestions.
---
docs/codeql/reusables/threat-model-description.rst | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/docs/codeql/reusables/threat-model-description.rst b/docs/codeql/reusables/threat-model-description.rst
index e35db8b21c22f..bc21e7ad170b2 100644
--- a/docs/codeql/reusables/threat-model-description.rst
+++ b/docs/codeql/reusables/threat-model-description.rst
@@ -5,15 +5,15 @@ A threat model is a named class of dataflow sources that can be enabled or disab
The ``kind`` property of the ``sourceModel`` determines which threat model a source is associated with. There are two main categories:
- ``remote`` which represents requests (``request``) and responses (``response``) from the network.
-- ``local`` which represents data from local files (``file``), command-line arguments (``commandargs``), database reads (``database``), environment variables(``environment``) and Windows registry values ("windows-registry").
+- ``local`` which represents data from local files (``file``), command-line arguments (``commandargs``), database reads (``database``), environment variables(``environment``) and Windows registry values ("windows-registry"). Currently, Windows registry values are used by C# only.
Note that subcategories can be turned included or excluded separately, so you can specify ``local`` without ``database``, or just ``commandargs`` and ``environment`` without the rest of ``local``.
The less commonly used categories are:
-- ``android`` which represents reads from external files in Android (``android-external-storage-dir``) and parameter of an entry-point method declared in a ``ContentProvider`` class (``contentprovider``).
-- ``database-access-result`` which represents a database access (currently only used by javascript).
-- ``file-write`` which represents opening a file in write mode (currently only used in C#).
-- ``reverse-dns`` which represents reverse DNS lookups (currently only used in java).
+- ``android`` which represents reads from external files in Android (``android-external-storage-dir``) and parameter of an entry-point method declared in a ``ContentProvider`` class (``contentprovider``). Currently only used by Java/Kotlin.
+- ``database-access-result`` which represents a database access. Currently only used by JavaScript.
+- ``file-write`` which represents opening a file in write mode. Currently only used in C#.
+- ``reverse-dns`` which represents reverse DNS lookups. Currently only used in Java.
When running a CodeQL analysis, the ``remote`` threat model is included by default. You can optionally include other threat models as appropriate when using the CodeQL CLI and in GitHub code scanning. For more information, see `Analyzing your code with CodeQL queries `__ and `Customizing your advanced setup for code scanning `__.
From 123214cb2b498bffb57fd961ce2892807b69627d Mon Sep 17 00:00:00 2001
From: Joe Farebrother
Date: Tue, 2 Jul 2024 21:57:16 +0100
Subject: [PATCH 027/140] Promoto cookie injection query
---
.../CookieInjectionCustomizations.qll | 48 +++++++++++++++++++
.../dataflow/CookieInjectionQuery.qll | 26 ++++++++++
.../src/Security/CWE-614/CookieInjection.ql | 20 ++++++++
3 files changed, 94 insertions(+)
create mode 100644 python/ql/lib/semmle/python/security/dataflow/CookieInjectionCustomizations.qll
create mode 100644 python/ql/lib/semmle/python/security/dataflow/CookieInjectionQuery.qll
create mode 100644 python/ql/src/Security/CWE-614/CookieInjection.ql
diff --git a/python/ql/lib/semmle/python/security/dataflow/CookieInjectionCustomizations.qll b/python/ql/lib/semmle/python/security/dataflow/CookieInjectionCustomizations.qll
new file mode 100644
index 0000000000000..dd3792182de8f
--- /dev/null
+++ b/python/ql/lib/semmle/python/security/dataflow/CookieInjectionCustomizations.qll
@@ -0,0 +1,48 @@
+/**
+ * Provides default sources, sinks and sanitizers for detecting
+ * "cookie injection"
+ * vulnerabilities, as well as extension points for adding your own.
+ */
+
+private import python
+private import semmle.python.dataflow.new.DataFlow
+private import semmle.python.Concepts
+private import semmle.python.dataflow.new.RemoteFlowSources
+
+/**
+ * Provides default sources, sinks and sanitizers for detecting
+ * "cookie injection"
+ * vulnerabilities, as well as extension points for adding your own.
+ */
+module CookieInjection {
+ /**
+ * A data flow source for "cookie injection" vulnerabilities.
+ */
+ abstract class Source extends DataFlow::Node { }
+
+ /**
+ * A data flow sink for "cookie injection" vulnerabilities.
+ */
+ abstract class Sink extends DataFlow::Node { }
+
+ /**
+ * A sanitizer for "cookie injection" vulnerabilities.
+ */
+ abstract class Sanitizer extends DataFlow::Node { }
+
+ /**
+ * A source of remote user input, considered as a flow source.
+ */
+ class RemoteFlowSourceAsSource extends Source, RemoteFlowSource { }
+
+ /**
+ * A write to a cookie, considered as a sink.
+ */
+ class CookieWriteSink extends Sink {
+ CookieWriteSink() {
+ exists(Http::Server::CookieWrite cw |
+ this = [cw.getNameArg(), cw.getValueArg(), cw.getHeaderArg()]
+ )
+ }
+ }
+}
diff --git a/python/ql/lib/semmle/python/security/dataflow/CookieInjectionQuery.qll b/python/ql/lib/semmle/python/security/dataflow/CookieInjectionQuery.qll
new file mode 100644
index 0000000000000..2b089fb277936
--- /dev/null
+++ b/python/ql/lib/semmle/python/security/dataflow/CookieInjectionQuery.qll
@@ -0,0 +1,26 @@
+/**
+ * Provides a taint-tracking configuration for detecting "cookie injection" vulnerabilities.
+ *
+ * Note, for performance reasons: only import this file if
+ * `CookieInjectionFlow` is needed, otherwise
+ * `CookieInjectionCustomizations` should be imported instead.
+ */
+
+private import python
+import semmle.python.dataflow.new.DataFlow
+import semmle.python.dataflow.new.TaintTracking
+import CookieInjectionCustomizations::CookieInjection
+
+/**
+ * A taint-tracking configuration for detecting "cookie injection" vulnerabilities.
+ */
+module CookieInjectionConfig implements DataFlow::ConfigSig {
+ predicate isSource(DataFlow::Node source) { source instanceof Source }
+
+ predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
+
+ predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer }
+}
+
+/** Global taint-tracking for detecting "cookie injection" vulnerabilities. */
+module CookieInjectionFlow = TaintTracking::Global;
diff --git a/python/ql/src/Security/CWE-614/CookieInjection.ql b/python/ql/src/Security/CWE-614/CookieInjection.ql
new file mode 100644
index 0000000000000..d18694906e0d0
--- /dev/null
+++ b/python/ql/src/Security/CWE-614/CookieInjection.ql
@@ -0,0 +1,20 @@
+/**
+ * @name Construction of a cookie using user-supplied input.
+ * @description Constructing cookies from user input may allow an attacker to perform a Cookie Poisoning attack.
+ * @kind path-problem
+ * @problem.severity error
+ * @precision high
+ * @id py/cookie-injection
+ * @tags security
+ * external/cwe/cwe-614
+ */
+
+import python
+import semmle.python.dataflow.new.DataFlow
+import semmle.python.security.dataflow.CookieInjectionQuery
+import CookieInjectionFlow::PathGraph
+
+from CookieInjectionFlow::PathNode source, CookieInjectionFlow::PathNode sink
+where CookieInjectionFlow::flowPath(source, sink)
+select sink.getNode(), source, sink, "Cookie is constructed from a $@.", source.getNode(),
+ "user-supplied input"
From 983bdb92a12866e877092e261587150c4c273f6f Mon Sep 17 00:00:00 2001
From: Joe Farebrother
Date: Wed, 3 Jul 2024 22:26:25 +0100
Subject: [PATCH 028/140] Add test cases + remove redundant import
---
.../src/Security/CWE-614/CookieInjection.ql | 1 -
.../CookieInjection.expected | 28 +++++++++++++++++++
.../CookieInjection.qlref | 1 +
.../CWE-614-CookieInjection/django_tests.py | 20 +++++++++++++
4 files changed, 49 insertions(+), 1 deletion(-)
create mode 100644 python/ql/test/query-tests/Security/CWE-614-CookieInjection/CookieInjection.expected
create mode 100644 python/ql/test/query-tests/Security/CWE-614-CookieInjection/CookieInjection.qlref
create mode 100644 python/ql/test/query-tests/Security/CWE-614-CookieInjection/django_tests.py
diff --git a/python/ql/src/Security/CWE-614/CookieInjection.ql b/python/ql/src/Security/CWE-614/CookieInjection.ql
index d18694906e0d0..bd50a07732635 100644
--- a/python/ql/src/Security/CWE-614/CookieInjection.ql
+++ b/python/ql/src/Security/CWE-614/CookieInjection.ql
@@ -10,7 +10,6 @@
*/
import python
-import semmle.python.dataflow.new.DataFlow
import semmle.python.security.dataflow.CookieInjectionQuery
import CookieInjectionFlow::PathGraph
diff --git a/python/ql/test/query-tests/Security/CWE-614-CookieInjection/CookieInjection.expected b/python/ql/test/query-tests/Security/CWE-614-CookieInjection/CookieInjection.expected
new file mode 100644
index 0000000000000..cf3a06ac7c8f1
--- /dev/null
+++ b/python/ql/test/query-tests/Security/CWE-614-CookieInjection/CookieInjection.expected
@@ -0,0 +1,28 @@
+edges
+| django_tests.py:4:25:4:31 | ControlFlowNode for request | django_tests.py:6:21:6:31 | ControlFlowNode for Attribute | provenance | AdditionalTaintStep |
+| django_tests.py:4:25:4:31 | ControlFlowNode for request | django_tests.py:7:21:7:31 | ControlFlowNode for Attribute | provenance | AdditionalTaintStep |
+| django_tests.py:6:21:6:31 | ControlFlowNode for Attribute | django_tests.py:6:21:6:43 | ControlFlowNode for Attribute() | provenance | dict.get |
+| django_tests.py:7:21:7:31 | ControlFlowNode for Attribute | django_tests.py:7:21:7:44 | ControlFlowNode for Attribute() | provenance | dict.get |
+| django_tests.py:11:26:11:32 | ControlFlowNode for request | django_tests.py:13:33:13:43 | ControlFlowNode for Attribute | provenance | AdditionalTaintStep |
+| django_tests.py:11:26:11:32 | ControlFlowNode for request | django_tests.py:13:59:13:69 | ControlFlowNode for Attribute | provenance | AdditionalTaintStep |
+| django_tests.py:13:33:13:43 | ControlFlowNode for Attribute | django_tests.py:13:33:13:55 | ControlFlowNode for Attribute() | provenance | dict.get |
+| django_tests.py:13:33:13:55 | ControlFlowNode for Attribute() | django_tests.py:13:30:13:100 | ControlFlowNode for Fstring | provenance | |
+| django_tests.py:13:59:13:69 | ControlFlowNode for Attribute | django_tests.py:13:59:13:82 | ControlFlowNode for Attribute() | provenance | dict.get |
+| django_tests.py:13:59:13:82 | ControlFlowNode for Attribute() | django_tests.py:13:30:13:100 | ControlFlowNode for Fstring | provenance | |
+nodes
+| django_tests.py:4:25:4:31 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
+| django_tests.py:6:21:6:31 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
+| django_tests.py:6:21:6:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
+| django_tests.py:7:21:7:31 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
+| django_tests.py:7:21:7:44 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
+| django_tests.py:11:26:11:32 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
+| django_tests.py:13:30:13:100 | ControlFlowNode for Fstring | semmle.label | ControlFlowNode for Fstring |
+| django_tests.py:13:33:13:43 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
+| django_tests.py:13:33:13:55 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
+| django_tests.py:13:59:13:69 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
+| django_tests.py:13:59:13:82 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
+subpaths
+#select
+| django_tests.py:6:21:6:43 | ControlFlowNode for Attribute() | django_tests.py:4:25:4:31 | ControlFlowNode for request | django_tests.py:6:21:6:43 | ControlFlowNode for Attribute() | Cookie is constructed from a $@. | django_tests.py:4:25:4:31 | ControlFlowNode for request | user-supplied input |
+| django_tests.py:7:21:7:44 | ControlFlowNode for Attribute() | django_tests.py:4:25:4:31 | ControlFlowNode for request | django_tests.py:7:21:7:44 | ControlFlowNode for Attribute() | Cookie is constructed from a $@. | django_tests.py:4:25:4:31 | ControlFlowNode for request | user-supplied input |
+| django_tests.py:13:30:13:100 | ControlFlowNode for Fstring | django_tests.py:11:26:11:32 | ControlFlowNode for request | django_tests.py:13:30:13:100 | ControlFlowNode for Fstring | Cookie is constructed from a $@. | django_tests.py:11:26:11:32 | ControlFlowNode for request | user-supplied input |
diff --git a/python/ql/test/query-tests/Security/CWE-614-CookieInjection/CookieInjection.qlref b/python/ql/test/query-tests/Security/CWE-614-CookieInjection/CookieInjection.qlref
new file mode 100644
index 0000000000000..703837cf661e4
--- /dev/null
+++ b/python/ql/test/query-tests/Security/CWE-614-CookieInjection/CookieInjection.qlref
@@ -0,0 +1 @@
+Security/CWE-614/CookieInjection.ql
\ No newline at end of file
diff --git a/python/ql/test/query-tests/Security/CWE-614-CookieInjection/django_tests.py b/python/ql/test/query-tests/Security/CWE-614-CookieInjection/django_tests.py
new file mode 100644
index 0000000000000..e070f5cab82b8
--- /dev/null
+++ b/python/ql/test/query-tests/Security/CWE-614-CookieInjection/django_tests.py
@@ -0,0 +1,20 @@
+import django.http
+from django.urls import path
+
+def django_response_bad(request):
+ resp = django.http.HttpResponse()
+ resp.set_cookie(request.GET.get("name"), # BAD: Cookie is constructed from user input
+ request.GET.get("value"))
+ return resp
+
+
+def django_response_bad2(request):
+ response = django.http.HttpResponse()
+ response['Set-Cookie'] = f"{request.GET.get('name')}={request.GET.get('value')}; SameSite=None;" # BAD: Cookie header is constructed from user input.
+ return response
+
+# fake setup, you can't actually run this
+urlpatterns = [
+ path("response_bad", django_response_bad),
+ path("response_bd2", django_response_bad2)
+]
\ No newline at end of file
From e885f1f8c4bc03be71056880d24d3a935844e54e Mon Sep 17 00:00:00 2001
From: Joe Farebrother
Date: Tue, 16 Jul 2024 10:16:10 +0100
Subject: [PATCH 029/140] Add documentation
---
.../Security/CWE-614/CookieInjection.qhelp | 24 +++++++++++++++++++
.../src/Security/CWE-614/CookieInjection.ql | 3 ++-
.../CWE-614/examples/CookieInjection.py | 16 +++++++++++++
3 files changed, 42 insertions(+), 1 deletion(-)
create mode 100644 python/ql/src/Security/CWE-614/CookieInjection.qhelp
create mode 100644 python/ql/src/Security/CWE-614/examples/CookieInjection.py
diff --git a/python/ql/src/Security/CWE-614/CookieInjection.qhelp b/python/ql/src/Security/CWE-614/CookieInjection.qhelp
new file mode 100644
index 0000000000000..e3e03355cdfeb
--- /dev/null
+++ b/python/ql/src/Security/CWE-614/CookieInjection.qhelp
@@ -0,0 +1,24 @@
+
+
+
+
+Constructing cookies from user input can allow an attacker to control a user's cookie. Additionally, if the cookie is set using a raw header, cookie attributes such as the Secure
flag may be controlled by an attacker.
+
+
+
+
+Do not use raw user input to construct cookies.
+
+
+
+In the following cases, a cookie is constructed for a Flask response using user input. The first uses set_cookie
,
+and the second sets a cookie's raw value through the set-cookie
header.
+
+
+
+
+
+
+
diff --git a/python/ql/src/Security/CWE-614/CookieInjection.ql b/python/ql/src/Security/CWE-614/CookieInjection.ql
index bd50a07732635..f373386cdfbbe 100644
--- a/python/ql/src/Security/CWE-614/CookieInjection.ql
+++ b/python/ql/src/Security/CWE-614/CookieInjection.ql
@@ -2,8 +2,9 @@
* @name Construction of a cookie using user-supplied input.
* @description Constructing cookies from user input may allow an attacker to perform a Cookie Poisoning attack.
* @kind path-problem
- * @problem.severity error
+ * @problem.severity warning
* @precision high
+ * @security-severity 5.0
* @id py/cookie-injection
* @tags security
* external/cwe/cwe-614
diff --git a/python/ql/src/Security/CWE-614/examples/CookieInjection.py b/python/ql/src/Security/CWE-614/examples/CookieInjection.py
new file mode 100644
index 0000000000000..5e1c5a3ee8ef7
--- /dev/null
+++ b/python/ql/src/Security/CWE-614/examples/CookieInjection.py
@@ -0,0 +1,16 @@
+from flask import request, make_response
+
+
+@app.route("/1")
+def set_cookie():
+ resp = make_response()
+ resp.set_cookie(request.args["name"], # BAD: User input is used to set the cookie's name and value
+ value=request.args["name"])
+ return resp
+
+
+@app.route("/2")
+def set_cookie_header():
+ resp = make_response()
+ resp.headers['Set-Cookie'] = f"{request.args['name']}={request.args['name']};" # BAD: User input is used to set the raw cookie header.
+ return resp
From 8d93c3a852305c59814b0da4b64aac06e6b5055e Mon Sep 17 00:00:00 2001
From: Joe Farebrother
Date: Tue, 16 Jul 2024 16:31:23 +0100
Subject: [PATCH 030/140] Move to cwe-20
---
.../ql/src/Security/{CWE-614 => CWE-020}/CookieInjection.qhelp | 0
python/ql/src/Security/{CWE-614 => CWE-020}/CookieInjection.ql | 2 +-
.../Security/{CWE-614 => CWE-020}/examples/CookieInjection.py | 0
.../CookieInjection.expected | 0
.../Security/CWE-020-CookieInjection/CookieInjection.qlref | 1 +
.../django_tests.py | 0
.../Security/CWE-614-CookieInjection/CookieInjection.qlref | 1 -
7 files changed, 2 insertions(+), 2 deletions(-)
rename python/ql/src/Security/{CWE-614 => CWE-020}/CookieInjection.qhelp (100%)
rename python/ql/src/Security/{CWE-614 => CWE-020}/CookieInjection.ql (95%)
rename python/ql/src/Security/{CWE-614 => CWE-020}/examples/CookieInjection.py (100%)
rename python/ql/test/query-tests/Security/{CWE-614-CookieInjection => CWE-020-CookieInjection}/CookieInjection.expected (100%)
create mode 100644 python/ql/test/query-tests/Security/CWE-020-CookieInjection/CookieInjection.qlref
rename python/ql/test/query-tests/Security/{CWE-614-CookieInjection => CWE-020-CookieInjection}/django_tests.py (100%)
delete mode 100644 python/ql/test/query-tests/Security/CWE-614-CookieInjection/CookieInjection.qlref
diff --git a/python/ql/src/Security/CWE-614/CookieInjection.qhelp b/python/ql/src/Security/CWE-020/CookieInjection.qhelp
similarity index 100%
rename from python/ql/src/Security/CWE-614/CookieInjection.qhelp
rename to python/ql/src/Security/CWE-020/CookieInjection.qhelp
diff --git a/python/ql/src/Security/CWE-614/CookieInjection.ql b/python/ql/src/Security/CWE-020/CookieInjection.ql
similarity index 95%
rename from python/ql/src/Security/CWE-614/CookieInjection.ql
rename to python/ql/src/Security/CWE-020/CookieInjection.ql
index f373386cdfbbe..944db480ec8f4 100644
--- a/python/ql/src/Security/CWE-614/CookieInjection.ql
+++ b/python/ql/src/Security/CWE-020/CookieInjection.ql
@@ -7,7 +7,7 @@
* @security-severity 5.0
* @id py/cookie-injection
* @tags security
- * external/cwe/cwe-614
+ * external/cwe/cwe-20
*/
import python
diff --git a/python/ql/src/Security/CWE-614/examples/CookieInjection.py b/python/ql/src/Security/CWE-020/examples/CookieInjection.py
similarity index 100%
rename from python/ql/src/Security/CWE-614/examples/CookieInjection.py
rename to python/ql/src/Security/CWE-020/examples/CookieInjection.py
diff --git a/python/ql/test/query-tests/Security/CWE-614-CookieInjection/CookieInjection.expected b/python/ql/test/query-tests/Security/CWE-020-CookieInjection/CookieInjection.expected
similarity index 100%
rename from python/ql/test/query-tests/Security/CWE-614-CookieInjection/CookieInjection.expected
rename to python/ql/test/query-tests/Security/CWE-020-CookieInjection/CookieInjection.expected
diff --git a/python/ql/test/query-tests/Security/CWE-020-CookieInjection/CookieInjection.qlref b/python/ql/test/query-tests/Security/CWE-020-CookieInjection/CookieInjection.qlref
new file mode 100644
index 0000000000000..a405c564b1bfb
--- /dev/null
+++ b/python/ql/test/query-tests/Security/CWE-020-CookieInjection/CookieInjection.qlref
@@ -0,0 +1 @@
+Security/CWE-020/CookieInjection.ql
\ No newline at end of file
diff --git a/python/ql/test/query-tests/Security/CWE-614-CookieInjection/django_tests.py b/python/ql/test/query-tests/Security/CWE-020-CookieInjection/django_tests.py
similarity index 100%
rename from python/ql/test/query-tests/Security/CWE-614-CookieInjection/django_tests.py
rename to python/ql/test/query-tests/Security/CWE-020-CookieInjection/django_tests.py
diff --git a/python/ql/test/query-tests/Security/CWE-614-CookieInjection/CookieInjection.qlref b/python/ql/test/query-tests/Security/CWE-614-CookieInjection/CookieInjection.qlref
deleted file mode 100644
index 703837cf661e4..0000000000000
--- a/python/ql/test/query-tests/Security/CWE-614-CookieInjection/CookieInjection.qlref
+++ /dev/null
@@ -1 +0,0 @@
-Security/CWE-614/CookieInjection.ql
\ No newline at end of file
From 070d67816ddc4ac8a3a1a61bb447d1c3a965134c Mon Sep 17 00:00:00 2001
From: Joe Farebrother
Date: Tue, 16 Jul 2024 16:48:58 +0100
Subject: [PATCH 031/140] Remove experimental version
---
.../Security/CWE-614/CookieInjection.py | 16 ------
.../Security/CWE-614/CookieInjection.qhelp | 28 ----------
.../Security/CWE-614/CookieInjection.ql | 27 ----------
.../Security/CWE-614/CookieInjection.expected | 51 -------------------
.../Security/CWE-614/CookieInjection.qlref | 1 -
5 files changed, 123 deletions(-)
delete mode 100644 python/ql/src/experimental/Security/CWE-614/CookieInjection.py
delete mode 100644 python/ql/src/experimental/Security/CWE-614/CookieInjection.qhelp
delete mode 100644 python/ql/src/experimental/Security/CWE-614/CookieInjection.ql
delete mode 100644 python/ql/test/experimental/query-tests/Security/CWE-614/CookieInjection.expected
delete mode 100644 python/ql/test/experimental/query-tests/Security/CWE-614/CookieInjection.qlref
diff --git a/python/ql/src/experimental/Security/CWE-614/CookieInjection.py b/python/ql/src/experimental/Security/CWE-614/CookieInjection.py
deleted file mode 100644
index 55d211bafc1af..0000000000000
--- a/python/ql/src/experimental/Security/CWE-614/CookieInjection.py
+++ /dev/null
@@ -1,16 +0,0 @@
-from flask import request, make_response
-
-
-@app.route("/1")
-def true():
- resp = make_response()
- resp.set_cookie(request.args["name"],
- value=request.args["name"])
- return resp
-
-
-@app.route("/2")
-def flask_make_response():
- resp = make_response("hello")
- resp.headers['Set-Cookie'] = f"{request.args['name']}={request.args['name']};"
- return resp
diff --git a/python/ql/src/experimental/Security/CWE-614/CookieInjection.qhelp b/python/ql/src/experimental/Security/CWE-614/CookieInjection.qhelp
deleted file mode 100644
index 4b5ec11726c4f..0000000000000
--- a/python/ql/src/experimental/Security/CWE-614/CookieInjection.qhelp
+++ /dev/null
@@ -1,28 +0,0 @@
-
-
-
-
-Constructing cookies from user input may allow an attacker to perform a Cookie Poisoning attack.
-It is possible, however, to perform other parameter-like attacks through cookie poisoning techniques,
-such as SQL Injection, Directory Traversal, or Stealth Commanding, etc. Additionally,
-cookie injection may relate to attempts to perform Access of Administrative Interface.
-
-
-
-
-Do not use raw user input to construct cookies.
-
-
-
-This example shows two ways of adding a cookie to a Flask response. The first way uses set_cookie
's
-and the second sets a cookie's raw value through a header, both using user-supplied input.
-
-
-
-
-Imperva: Cookie injection.
-
-
-
diff --git a/python/ql/src/experimental/Security/CWE-614/CookieInjection.ql b/python/ql/src/experimental/Security/CWE-614/CookieInjection.ql
deleted file mode 100644
index 4193e37dee245..0000000000000
--- a/python/ql/src/experimental/Security/CWE-614/CookieInjection.ql
+++ /dev/null
@@ -1,27 +0,0 @@
-/**
- * @name Construction of a cookie using user-supplied input.
- * @description Constructing cookies from user input may allow an attacker to perform a Cookie Poisoning attack.
- * @kind path-problem
- * @problem.severity error
- * @id py/cookie-injection
- * @tags security
- * experimental
- * external/cwe/cwe-614
- */
-
-// determine precision above
-import python
-import semmle.python.dataflow.new.DataFlow
-import experimental.semmle.python.Concepts
-import experimental.semmle.python.CookieHeader
-import experimental.semmle.python.security.injection.CookieInjection
-import CookieInjectionFlow::PathGraph
-
-from CookieInjectionFlow::PathNode source, CookieInjectionFlow::PathNode sink, string insecure
-where
- CookieInjectionFlow::flowPath(source, sink) and
- if exists(sink.getNode().(CookieSink))
- then insecure = ",and its " + sink.getNode().(CookieSink).getFlag() + " flag is not properly set."
- else insecure = "."
-select sink.getNode(), source, sink, "Cookie is constructed from a $@" + insecure, source.getNode(),
- "user-supplied input"
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-614/CookieInjection.expected b/python/ql/test/experimental/query-tests/Security/CWE-614/CookieInjection.expected
deleted file mode 100644
index 80dcbae21773d..0000000000000
--- a/python/ql/test/experimental/query-tests/Security/CWE-614/CookieInjection.expected
+++ /dev/null
@@ -1,51 +0,0 @@
-edges
-| django_bad.py:27:33:27:67 | ControlFlowNode for Attribute() | django_bad.py:27:30:27:124 | ControlFlowNode for Fstring | provenance | |
-| django_bad.py:27:71:27:106 | ControlFlowNode for Attribute() | django_bad.py:27:30:27:124 | ControlFlowNode for Fstring | provenance | |
-| flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | flask_bad.py:1:26:1:32 | ControlFlowNode for request | provenance | |
-| flask_bad.py:1:26:1:32 | ControlFlowNode for request | flask_bad.py:24:21:24:27 | ControlFlowNode for request | provenance | |
-| flask_bad.py:1:26:1:32 | ControlFlowNode for request | flask_bad.py:24:49:24:55 | ControlFlowNode for request | provenance | |
-| flask_bad.py:1:26:1:32 | ControlFlowNode for request | flask_bad.py:32:37:32:43 | ControlFlowNode for request | provenance | |
-| flask_bad.py:1:26:1:32 | ControlFlowNode for request | flask_bad.py:32:60:32:66 | ControlFlowNode for request | provenance | |
-| flask_bad.py:24:21:24:27 | ControlFlowNode for request | flask_bad.py:24:21:24:40 | ControlFlowNode for Subscript | provenance | AdditionalTaintStep |
-| flask_bad.py:24:21:24:27 | ControlFlowNode for request | flask_bad.py:24:49:24:69 | ControlFlowNode for Subscript | provenance | AdditionalTaintStep |
-| flask_bad.py:24:49:24:55 | ControlFlowNode for request | flask_bad.py:24:49:24:69 | ControlFlowNode for Subscript | provenance | AdditionalTaintStep |
-| flask_bad.py:32:37:32:43 | ControlFlowNode for request | flask_bad.py:32:34:32:98 | ControlFlowNode for Fstring | provenance | AdditionalTaintStep |
-| flask_bad.py:32:60:32:66 | ControlFlowNode for request | flask_bad.py:32:34:32:98 | ControlFlowNode for Fstring | provenance | AdditionalTaintStep |
-nodes
-| django_bad.py:19:21:19:55 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
-| django_bad.py:20:21:20:56 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
-| django_bad.py:27:30:27:124 | ControlFlowNode for Fstring | semmle.label | ControlFlowNode for Fstring |
-| django_bad.py:27:33:27:67 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
-| django_bad.py:27:71:27:106 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
-| flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember |
-| flask_bad.py:1:26:1:32 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
-| flask_bad.py:24:21:24:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
-| flask_bad.py:24:21:24:40 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
-| flask_bad.py:24:49:24:55 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
-| flask_bad.py:24:49:24:69 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
-| flask_bad.py:32:34:32:98 | ControlFlowNode for Fstring | semmle.label | ControlFlowNode for Fstring |
-| flask_bad.py:32:37:32:43 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
-| flask_bad.py:32:60:32:66 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
-subpaths
-#select
-| django_bad.py:19:21:19:55 | ControlFlowNode for Attribute() | django_bad.py:19:21:19:55 | ControlFlowNode for Attribute() | django_bad.py:19:21:19:55 | ControlFlowNode for Attribute() | Cookie is constructed from a $@,and its httponly flag is not properly set. | django_bad.py:19:21:19:55 | ControlFlowNode for Attribute() | user-supplied input |
-| django_bad.py:19:21:19:55 | ControlFlowNode for Attribute() | django_bad.py:19:21:19:55 | ControlFlowNode for Attribute() | django_bad.py:19:21:19:55 | ControlFlowNode for Attribute() | Cookie is constructed from a $@,and its samesite flag is not properly set. | django_bad.py:19:21:19:55 | ControlFlowNode for Attribute() | user-supplied input |
-| django_bad.py:19:21:19:55 | ControlFlowNode for Attribute() | django_bad.py:19:21:19:55 | ControlFlowNode for Attribute() | django_bad.py:19:21:19:55 | ControlFlowNode for Attribute() | Cookie is constructed from a $@,and its secure flag is not properly set. | django_bad.py:19:21:19:55 | ControlFlowNode for Attribute() | user-supplied input |
-| django_bad.py:20:21:20:56 | ControlFlowNode for Attribute() | django_bad.py:20:21:20:56 | ControlFlowNode for Attribute() | django_bad.py:20:21:20:56 | ControlFlowNode for Attribute() | Cookie is constructed from a $@,and its httponly flag is not properly set. | django_bad.py:20:21:20:56 | ControlFlowNode for Attribute() | user-supplied input |
-| django_bad.py:20:21:20:56 | ControlFlowNode for Attribute() | django_bad.py:20:21:20:56 | ControlFlowNode for Attribute() | django_bad.py:20:21:20:56 | ControlFlowNode for Attribute() | Cookie is constructed from a $@,and its samesite flag is not properly set. | django_bad.py:20:21:20:56 | ControlFlowNode for Attribute() | user-supplied input |
-| django_bad.py:20:21:20:56 | ControlFlowNode for Attribute() | django_bad.py:20:21:20:56 | ControlFlowNode for Attribute() | django_bad.py:20:21:20:56 | ControlFlowNode for Attribute() | Cookie is constructed from a $@,and its secure flag is not properly set. | django_bad.py:20:21:20:56 | ControlFlowNode for Attribute() | user-supplied input |
-| django_bad.py:27:30:27:124 | ControlFlowNode for Fstring | django_bad.py:27:33:27:67 | ControlFlowNode for Attribute() | django_bad.py:27:30:27:124 | ControlFlowNode for Fstring | Cookie is constructed from a $@,and its httponly flag is not properly set. | django_bad.py:27:33:27:67 | ControlFlowNode for Attribute() | user-supplied input |
-| django_bad.py:27:30:27:124 | ControlFlowNode for Fstring | django_bad.py:27:33:27:67 | ControlFlowNode for Attribute() | django_bad.py:27:30:27:124 | ControlFlowNode for Fstring | Cookie is constructed from a $@,and its samesite flag is not properly set. | django_bad.py:27:33:27:67 | ControlFlowNode for Attribute() | user-supplied input |
-| django_bad.py:27:30:27:124 | ControlFlowNode for Fstring | django_bad.py:27:33:27:67 | ControlFlowNode for Attribute() | django_bad.py:27:30:27:124 | ControlFlowNode for Fstring | Cookie is constructed from a $@,and its secure flag is not properly set. | django_bad.py:27:33:27:67 | ControlFlowNode for Attribute() | user-supplied input |
-| django_bad.py:27:30:27:124 | ControlFlowNode for Fstring | django_bad.py:27:71:27:106 | ControlFlowNode for Attribute() | django_bad.py:27:30:27:124 | ControlFlowNode for Fstring | Cookie is constructed from a $@,and its httponly flag is not properly set. | django_bad.py:27:71:27:106 | ControlFlowNode for Attribute() | user-supplied input |
-| django_bad.py:27:30:27:124 | ControlFlowNode for Fstring | django_bad.py:27:71:27:106 | ControlFlowNode for Attribute() | django_bad.py:27:30:27:124 | ControlFlowNode for Fstring | Cookie is constructed from a $@,and its samesite flag is not properly set. | django_bad.py:27:71:27:106 | ControlFlowNode for Attribute() | user-supplied input |
-| django_bad.py:27:30:27:124 | ControlFlowNode for Fstring | django_bad.py:27:71:27:106 | ControlFlowNode for Attribute() | django_bad.py:27:30:27:124 | ControlFlowNode for Fstring | Cookie is constructed from a $@,and its secure flag is not properly set. | django_bad.py:27:71:27:106 | ControlFlowNode for Attribute() | user-supplied input |
-| flask_bad.py:24:21:24:40 | ControlFlowNode for Subscript | flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | flask_bad.py:24:21:24:40 | ControlFlowNode for Subscript | Cookie is constructed from a $@,and its httponly flag is not properly set. | flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | user-supplied input |
-| flask_bad.py:24:21:24:40 | ControlFlowNode for Subscript | flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | flask_bad.py:24:21:24:40 | ControlFlowNode for Subscript | Cookie is constructed from a $@,and its samesite flag is not properly set. | flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | user-supplied input |
-| flask_bad.py:24:21:24:40 | ControlFlowNode for Subscript | flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | flask_bad.py:24:21:24:40 | ControlFlowNode for Subscript | Cookie is constructed from a $@,and its secure flag is not properly set. | flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | user-supplied input |
-| flask_bad.py:24:49:24:69 | ControlFlowNode for Subscript | flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | flask_bad.py:24:49:24:69 | ControlFlowNode for Subscript | Cookie is constructed from a $@,and its httponly flag is not properly set. | flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | user-supplied input |
-| flask_bad.py:24:49:24:69 | ControlFlowNode for Subscript | flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | flask_bad.py:24:49:24:69 | ControlFlowNode for Subscript | Cookie is constructed from a $@,and its samesite flag is not properly set. | flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | user-supplied input |
-| flask_bad.py:24:49:24:69 | ControlFlowNode for Subscript | flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | flask_bad.py:24:49:24:69 | ControlFlowNode for Subscript | Cookie is constructed from a $@,and its secure flag is not properly set. | flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | user-supplied input |
-| flask_bad.py:32:34:32:98 | ControlFlowNode for Fstring | flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | flask_bad.py:32:34:32:98 | ControlFlowNode for Fstring | Cookie is constructed from a $@,and its httponly flag is not properly set. | flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | user-supplied input |
-| flask_bad.py:32:34:32:98 | ControlFlowNode for Fstring | flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | flask_bad.py:32:34:32:98 | ControlFlowNode for Fstring | Cookie is constructed from a $@,and its samesite flag is not properly set. | flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | user-supplied input |
-| flask_bad.py:32:34:32:98 | ControlFlowNode for Fstring | flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | flask_bad.py:32:34:32:98 | ControlFlowNode for Fstring | Cookie is constructed from a $@,and its secure flag is not properly set. | flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | user-supplied input |
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-614/CookieInjection.qlref b/python/ql/test/experimental/query-tests/Security/CWE-614/CookieInjection.qlref
deleted file mode 100644
index 5710a3322dec5..0000000000000
--- a/python/ql/test/experimental/query-tests/Security/CWE-614/CookieInjection.qlref
+++ /dev/null
@@ -1 +0,0 @@
-experimental/Security/CWE-614/CookieInjection.ql
From 9dd43d8e6fc971dacf6c86204ca0972b9c0e3331 Mon Sep 17 00:00:00 2001
From: Mathias Vorreiter Pedersen
Date: Thu, 11 Jul 2024 11:57:06 +0100
Subject: [PATCH 032/140] C++: Promote
'cpp/unsigned-difference-expression-compared-zero' to Code Scanning.
---
.../CWE/CWE-191/UnsignedDifferenceExpressionComparedZero.ql | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/cpp/ql/src/Security/CWE/CWE-191/UnsignedDifferenceExpressionComparedZero.ql b/cpp/ql/src/Security/CWE/CWE-191/UnsignedDifferenceExpressionComparedZero.ql
index 61ee5d4cad1d8..02de4223c185c 100644
--- a/cpp/ql/src/Security/CWE/CWE-191/UnsignedDifferenceExpressionComparedZero.ql
+++ b/cpp/ql/src/Security/CWE/CWE-191/UnsignedDifferenceExpressionComparedZero.ql
@@ -5,7 +5,7 @@
* @id cpp/unsigned-difference-expression-compared-zero
* @problem.severity warning
* @security-severity 9.8
- * @precision medium
+ * @precision high
* @tags security
* correctness
* external/cwe/cwe-191
From 5f70c4427024e7109b6ee2725a15f389a279f2d5 Mon Sep 17 00:00:00 2001
From: Mathias Vorreiter Pedersen
Date: Thu, 11 Jul 2024 11:57:24 +0100
Subject: [PATCH 033/140] C++: Add change note.
---
...7-11-unsigned-difference-expression-compared-zero-query.md | 4 ++++
1 file changed, 4 insertions(+)
create mode 100644 cpp/ql/src/change-notes/2024-07-11-unsigned-difference-expression-compared-zero-query.md
diff --git a/cpp/ql/src/change-notes/2024-07-11-unsigned-difference-expression-compared-zero-query.md b/cpp/ql/src/change-notes/2024-07-11-unsigned-difference-expression-compared-zero-query.md
new file mode 100644
index 0000000000000..7a1469464c277
--- /dev/null
+++ b/cpp/ql/src/change-notes/2024-07-11-unsigned-difference-expression-compared-zero-query.md
@@ -0,0 +1,4 @@
+---
+category: queryMetadata
+---
+* The precision of `cpp/unsigned-difference-expression-compared-zero` ("Unsigned difference expression compared to zero") has been increased to `high`. As a result, it will be run by default as part of the Code Scanning suite.
From 7029de59895ab00bffeece1ffe878fb80d49108f Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Wed, 17 Jul 2024 15:28:05 +0100
Subject: [PATCH 034/140] Swift: Attempt to speed up evaluation of the private
information regex for Swift.
---
swift/ql/lib/codeql/swift/security/SensitiveExprs.qll | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/swift/ql/lib/codeql/swift/security/SensitiveExprs.qll b/swift/ql/lib/codeql/swift/security/SensitiveExprs.qll
index a00d73c0a9f5e..f56a10ee772db 100644
--- a/swift/ql/lib/codeql/swift/security/SensitiveExprs.qll
+++ b/swift/ql/lib/codeql/swift/security/SensitiveExprs.qll
@@ -64,9 +64,9 @@ class SensitivePrivateInfo extends SensitiveDataType, TPrivateInfo {
override string toString() { result = "private information" }
override string getRegexp() {
+ // we've had good results for the e-mail heuristic in Swift, which isn't part of the default regex. Add it in.
result = HeuristicNames::maybeSensitiveRegexp(SensitiveDataClassification::private())
- or
- result = "(?is).*e(mail|_mail).*"
+ .replaceAll(".*(", ".*(e(mail|_mail)|")
}
}
From 1c8e0c453c2622bc7b13253b619902cffe915c7c Mon Sep 17 00:00:00 2001
From: Mathias Vorreiter Pedersen
Date: Fri, 12 Jul 2024 17:15:39 +0100
Subject: [PATCH 035/140] C++: Fix more inconsistencies.
---
.../aliased_ssa/internal/AliasAnalysis.qll | 59 ++++++++++++++++++-
.../internal/AliasConfiguration.qll | 5 ++
.../aliased_ssa/internal/AliasedSSA.qll | 2 +-
.../unaliased_ssa/internal/AliasAnalysis.qll | 59 ++++++++++++++++++-
.../internal/AliasConfiguration.qll | 3 +
.../unaliased_ssa/internal/SimpleSSA.qll | 2 +-
.../library-tests/ir/ir/aliased_ir.expected | 7 ++-
.../ir/ir/aliased_ssa_consistency.expected | 1 -
.../aliased_ssa_consistency_unsound.expected | 1 -
.../CWE/CWE-457/semmle/tests/test.cpp | 17 +++++-
10 files changed, 142 insertions(+), 14 deletions(-)
diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll
index 8f3493c1065f9..602f1ea47ff3a 100644
--- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll
+++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll
@@ -338,6 +338,57 @@ private predicate resultEscapesNonReturn(Instruction instr) {
not instr.isResultModeled()
}
+/** Holds if `operand` may (transitively) flow to an `AddressOperand` whose use is unmodeled. */
+private predicate consumedAsAddressOperand(Operand operand) {
+ operand instanceof AddressOperand and
+ exists(Instruction use | not use.isResultModeled())
+ or
+ exists(Operand address |
+ consumedAsAddressOperand(address) and
+ operandIsPropagated(operand, _, address.getDef())
+ )
+}
+
+/**
+ * Holds if `operand` may originate from a base instruction of an allocation,
+ * and that operand may transitively flow to an `AddressOperand` whose use is unmodeled.
+ */
+private predicate propagatedFromAllocationBase(Operand operand, Configuration::Allocation allocation) {
+ consumedAsAddressOperand(operand) and
+ (
+ not exists(Configuration::getOldAllocation(allocation)) and
+ operand.getDef() = allocation.getABaseInstruction()
+ or
+ exists(Operand address |
+ operandIsPropagated(address, _, operand.getDef()) and
+ propagatedFromAllocationBase(address, allocation)
+ )
+ )
+}
+
+private predicate propagatedFromNonAllocationBase(Operand operand) {
+ exists(Instruction def |
+ def = operand.getDef() and
+ not operandIsPropagated(_, _, def) and
+ not def = any(Configuration::Allocation allocation).getABaseInstruction()
+ )
+ or
+ exists(Operand address |
+ operandIsPropagated(address, _, operand.getDef()) and
+ propagatedFromNonAllocationBase(address)
+ )
+}
+
+/**
+ * Holds if we cannot see all producers of an operand for which allocation also flows into.
+ */
+private predicate operandConsumesEscaped(Configuration::Allocation allocation) {
+ exists(AddressOperand address |
+ propagatedFromAllocationBase(address, allocation) and
+ propagatedFromNonAllocationBase(address)
+ )
+}
+
/**
* Holds if the address of `allocation` escapes outside the domain of the analysis. This can occur
* either because the allocation's address is taken within the function and escapes, or because the
@@ -346,12 +397,14 @@ private predicate resultEscapesNonReturn(Instruction instr) {
predicate allocationEscapes(Configuration::Allocation allocation) {
allocation.alwaysEscapes()
or
- exists(IREscapeAnalysisConfiguration config |
- config.useSoundEscapeAnalysis() and resultEscapesNonReturn(allocation.getABaseInstruction())
+ exists(IREscapeAnalysisConfiguration config | config.useSoundEscapeAnalysis() |
+ resultEscapesNonReturn(allocation.getABaseInstruction())
+ or
+ operandConsumesEscaped(allocation)
)
or
Configuration::phaseNeedsSoundEscapeAnalysis() and
- resultEscapesNonReturn(allocation.getABaseInstruction())
+ (resultEscapesNonReturn(allocation.getABaseInstruction()) or operandConsumesEscaped(allocation))
}
/**
diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasConfiguration.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasConfiguration.qll
index ba2c1d5a22c0d..8b53e12b8a04d 100644
--- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasConfiguration.qll
+++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasConfiguration.qll
@@ -146,3 +146,8 @@ class DynamicAllocation extends Allocation, TDynamicAllocation {
}
predicate phaseNeedsSoundEscapeAnalysis() { none() }
+
+UnaliasedSsa::Allocation getOldAllocation(VariableAllocation allocation) {
+ UnaliasedSsa::canReuseSsaForVariable(allocation.getIRVariable()) and
+ result = allocation.getIRVariable()
+}
diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasedSSA.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasedSSA.qll
index aba70f8771d2f..4e1ddd6f09a98 100644
--- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasedSSA.qll
+++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasedSSA.qll
@@ -7,7 +7,7 @@ private import semmle.code.cpp.ir.implementation.unaliased_ssa.internal.SSAConst
private import semmle.code.cpp.ir.internal.IntegerConstant as Ints
private import semmle.code.cpp.ir.internal.IntegerInterval as Interval
private import semmle.code.cpp.ir.implementation.internal.OperandTag
-private import AliasConfiguration
+import AliasConfiguration
private import codeql.util.Boolean
private class IntValue = Ints::IntValue;
diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll
index 8f3493c1065f9..602f1ea47ff3a 100644
--- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll
+++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll
@@ -338,6 +338,57 @@ private predicate resultEscapesNonReturn(Instruction instr) {
not instr.isResultModeled()
}
+/** Holds if `operand` may (transitively) flow to an `AddressOperand` whose use is unmodeled. */
+private predicate consumedAsAddressOperand(Operand operand) {
+ operand instanceof AddressOperand and
+ exists(Instruction use | not use.isResultModeled())
+ or
+ exists(Operand address |
+ consumedAsAddressOperand(address) and
+ operandIsPropagated(operand, _, address.getDef())
+ )
+}
+
+/**
+ * Holds if `operand` may originate from a base instruction of an allocation,
+ * and that operand may transitively flow to an `AddressOperand` whose use is unmodeled.
+ */
+private predicate propagatedFromAllocationBase(Operand operand, Configuration::Allocation allocation) {
+ consumedAsAddressOperand(operand) and
+ (
+ not exists(Configuration::getOldAllocation(allocation)) and
+ operand.getDef() = allocation.getABaseInstruction()
+ or
+ exists(Operand address |
+ operandIsPropagated(address, _, operand.getDef()) and
+ propagatedFromAllocationBase(address, allocation)
+ )
+ )
+}
+
+private predicate propagatedFromNonAllocationBase(Operand operand) {
+ exists(Instruction def |
+ def = operand.getDef() and
+ not operandIsPropagated(_, _, def) and
+ not def = any(Configuration::Allocation allocation).getABaseInstruction()
+ )
+ or
+ exists(Operand address |
+ operandIsPropagated(address, _, operand.getDef()) and
+ propagatedFromNonAllocationBase(address)
+ )
+}
+
+/**
+ * Holds if we cannot see all producers of an operand for which allocation also flows into.
+ */
+private predicate operandConsumesEscaped(Configuration::Allocation allocation) {
+ exists(AddressOperand address |
+ propagatedFromAllocationBase(address, allocation) and
+ propagatedFromNonAllocationBase(address)
+ )
+}
+
/**
* Holds if the address of `allocation` escapes outside the domain of the analysis. This can occur
* either because the allocation's address is taken within the function and escapes, or because the
@@ -346,12 +397,14 @@ private predicate resultEscapesNonReturn(Instruction instr) {
predicate allocationEscapes(Configuration::Allocation allocation) {
allocation.alwaysEscapes()
or
- exists(IREscapeAnalysisConfiguration config |
- config.useSoundEscapeAnalysis() and resultEscapesNonReturn(allocation.getABaseInstruction())
+ exists(IREscapeAnalysisConfiguration config | config.useSoundEscapeAnalysis() |
+ resultEscapesNonReturn(allocation.getABaseInstruction())
+ or
+ operandConsumesEscaped(allocation)
)
or
Configuration::phaseNeedsSoundEscapeAnalysis() and
- resultEscapesNonReturn(allocation.getABaseInstruction())
+ (resultEscapesNonReturn(allocation.getABaseInstruction()) or operandConsumesEscaped(allocation))
}
/**
diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasConfiguration.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasConfiguration.qll
index 110e673e1d272..2ca2b4c728498 100644
--- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasConfiguration.qll
+++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasConfiguration.qll
@@ -1,4 +1,5 @@
private import AliasConfigurationImports
+private import codeql.util.Unit
/**
* A memory allocation that can be tracked by the SimpleSSA alias analysis.
@@ -16,3 +17,5 @@ class Allocation extends IRAutomaticVariable {
}
predicate phaseNeedsSoundEscapeAnalysis() { any() }
+
+Unit getOldAllocation(Allocation allocation) { any() }
diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SimpleSSA.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SimpleSSA.qll
index 8d11fdeec38e3..648fa0e197b84 100644
--- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SimpleSSA.qll
+++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SimpleSSA.qll
@@ -1,7 +1,7 @@
import AliasAnalysis
private import SimpleSSAImports
import SimpleSSAPublicImports
-private import AliasConfiguration
+import AliasConfiguration
private import codeql.util.Unit
private predicate isTotalAccess(Allocation var, AddressOperand addrOperand, IRType type) {
diff --git a/cpp/ql/test/library-tests/ir/ir/aliased_ir.expected b/cpp/ql/test/library-tests/ir/ir/aliased_ir.expected
index ea445b599fa49..dbb3e3fe0f296 100644
--- a/cpp/ql/test/library-tests/ir/ir/aliased_ir.expected
+++ b/cpp/ql/test/library-tests/ir/ir/aliased_ir.expected
@@ -18827,6 +18827,7 @@ ir.cpp:
# 2667| r2667_1(glval) = VariableAddress[intBuffer] :
# 2667| r2667_2(int) = Constant[8] :
# 2667| m2667_3(int) = Store[intBuffer] : &:r2667_1, r2667_2
+# 2667| m2667_4(unknown) = Chi : total:m2663_4, partial:m2667_3
# 2668| r2668_1(glval) = VariableAddress[intBuffer] :
# 2668| r2668_2(int *) = CopyValue : r2668_1
# 2668| r2668_3(glval) = VariableAddress[data] :
@@ -18834,15 +18835,15 @@ ir.cpp:
#-----| Goto -> Block 2
# 2670| Block 2
-# 2670| m2670_1(int) = Phi : from 1:m2667_3
+# 2670| m2670_1(unknown) = Phi : from 0:~m2663_4, from 1:~m2667_4
# 2670| m2670_2(int *) = Phi : from 0:m2665_3, from 1:m2668_4
# 2670| r2670_3(glval) = FunctionAddress[use_int] :
# 2670| r2670_4(glval) = VariableAddress[data] :
# 2670| r2670_5(int *) = Load[data] : &:r2670_4, m2670_2
# 2670| r2670_6(int) = Load[?] : &:r2670_5, ~m2670_1
# 2670| v2670_7(void) = Call[use_int] : func:r2670_3, 0:r2670_6
-# 2670| m2670_8(unknown) = ^CallSideEffect : ~m2663_4
-# 2670| m2670_9(unknown) = Chi : total:m2663_4, partial:m2670_8
+# 2670| m2670_8(unknown) = ^CallSideEffect : ~m2670_1
+# 2670| m2670_9(unknown) = Chi : total:m2670_1, partial:m2670_8
# 2671| v2671_1(void) = NoOp :
# 2663| v2663_7(void) = ReturnVoid :
# 2663| v2663_8(void) = AliasedUse : ~m2670_9
diff --git a/cpp/ql/test/library-tests/ir/ir/aliased_ssa_consistency.expected b/cpp/ql/test/library-tests/ir/ir/aliased_ssa_consistency.expected
index 17a11819e03cf..5a0234a4cc42f 100644
--- a/cpp/ql/test/library-tests/ir/ir/aliased_ssa_consistency.expected
+++ b/cpp/ql/test/library-tests/ir/ir/aliased_ssa_consistency.expected
@@ -2,7 +2,6 @@ missingOperand
unexpectedOperand
duplicateOperand
missingPhiOperand
-| ir.cpp:2670:3:2670:9 | Phi: call to use_int | Instruction 'Phi: call to use_int' is missing an operand for predecessor block 'EnterFunction: phi_with_single_input_at_merge' in function '$@'. | ir.cpp:2663:13:2663:42 | void phi_with_single_input_at_merge(bool) | void phi_with_single_input_at_merge(bool) |
missingOperandType
duplicateChiOperand
sideEffectWithoutPrimary
diff --git a/cpp/ql/test/library-tests/ir/ir/aliased_ssa_consistency_unsound.expected b/cpp/ql/test/library-tests/ir/ir/aliased_ssa_consistency_unsound.expected
index 17a11819e03cf..5a0234a4cc42f 100644
--- a/cpp/ql/test/library-tests/ir/ir/aliased_ssa_consistency_unsound.expected
+++ b/cpp/ql/test/library-tests/ir/ir/aliased_ssa_consistency_unsound.expected
@@ -2,7 +2,6 @@ missingOperand
unexpectedOperand
duplicateOperand
missingPhiOperand
-| ir.cpp:2670:3:2670:9 | Phi: call to use_int | Instruction 'Phi: call to use_int' is missing an operand for predecessor block 'EnterFunction: phi_with_single_input_at_merge' in function '$@'. | ir.cpp:2663:13:2663:42 | void phi_with_single_input_at_merge(bool) | void phi_with_single_input_at_merge(bool) |
missingOperandType
duplicateChiOperand
sideEffectWithoutPrimary
diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-457/semmle/tests/test.cpp b/cpp/ql/test/query-tests/Security/CWE/CWE-457/semmle/tests/test.cpp
index 11330ac53b6c6..5d0a0529f7ee8 100644
--- a/cpp/ql/test/query-tests/Security/CWE/CWE-457/semmle/tests/test.cpp
+++ b/cpp/ql/test/query-tests/Security/CWE/CWE-457/semmle/tests/test.cpp
@@ -565,4 +565,19 @@ void test45() {
*rP = NULL;
use(r); // GOOD
-}
\ No newline at end of file
+}
+
+void test46()
+{
+ LinkedList *r, **rP = &r;
+
+ while (getBool())
+ {
+ LinkedList *s = nullptr;
+ *rP = s;
+ rP = &s->next;
+ }
+
+ *rP = nullptr;
+ use(r);
+}
From 7b8301ac7a2bb32d962102a67b41adb500e843b3 Mon Sep 17 00:00:00 2001
From: Mathias Vorreiter Pedersen
Date: Tue, 16 Jul 2024 09:38:45 +0100
Subject: [PATCH 036/140] C++: Accept more test changes.
---
.../CWE/CWE-457/semmle/tests/LoopConditionsConst.expected | 1 +
1 file changed, 1 insertion(+)
diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-457/semmle/tests/LoopConditionsConst.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-457/semmle/tests/LoopConditionsConst.expected
index 07ca32b1718c5..f0ada1ce16a4f 100644
--- a/cpp/ql/test/query-tests/Security/CWE/CWE-457/semmle/tests/LoopConditionsConst.expected
+++ b/cpp/ql/test/query-tests/Security/CWE/CWE-457/semmle/tests/LoopConditionsConst.expected
@@ -23,3 +23,4 @@
| test.cpp:424:2:425:2 | for(...;...;...) ... | test.cpp:424:18:424:23 | ... < ... | 1 | i | { ... } | i | return ... |
| test.cpp:433:2:434:2 | for(...;...;...) ... | test.cpp:433:18:433:22 | 0 | 0 | | { ... } | 0 | return ... |
| test.cpp:559:3:564:3 | while (...) ... | test.cpp:559:9:559:15 | call to getBool | | call to getBool | { ... } | call to getBool | ExprStmt |
+| test.cpp:574:3:579:3 | while (...) ... | test.cpp:574:10:574:16 | call to getBool | | call to getBool | { ... } | call to getBool | ExprStmt |
From 8bc883274f6d24e1299c4ce7db9750e23f586822 Mon Sep 17 00:00:00 2001
From: Owen Mansel-Chan
Date: Thu, 18 Jul 2024 07:38:23 +0100
Subject: [PATCH 037/140] Minor improvement to jsoniter test
---
.../library-tests/semmle/go/frameworks/Encoding/jsoniter.ql | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/go/ql/test/library-tests/semmle/go/frameworks/Encoding/jsoniter.ql b/go/ql/test/library-tests/semmle/go/frameworks/Encoding/jsoniter.ql
index 1d761c2a67956..d55ef5b31d810 100644
--- a/go/ql/test/library-tests/semmle/go/frameworks/Encoding/jsoniter.ql
+++ b/go/ql/test/library-tests/semmle/go/frameworks/Encoding/jsoniter.ql
@@ -9,7 +9,7 @@ class UntrustedFunction extends Function {
}
class RemoteSource extends DataFlow::Node, RemoteFlowSource::Range {
- RemoteSource() { this = any(UntrustedFunction f).getACall() }
+ RemoteSource() { this = any(UntrustedFunction f).getACall().getResult() }
}
from CommandInjection::Flow::PathNode source, CommandInjection::Flow::PathNode sink
From 1e4aadfbfd1ed4fb567f4a112ce70061fce10343 Mon Sep 17 00:00:00 2001
From: Owen Mansel-Chan
Date: Thu, 18 Jul 2024 07:44:19 +0100
Subject: [PATCH 038/140] Trivial: improve variable name
---
.../library-tests/semmle/go/concepts/HTTP/RemoteFlowSources.ql | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/go/ql/test/library-tests/semmle/go/concepts/HTTP/RemoteFlowSources.ql b/go/ql/test/library-tests/semmle/go/concepts/HTTP/RemoteFlowSources.ql
index d56a98686e0cc..9e68fd210ff23 100644
--- a/go/ql/test/library-tests/semmle/go/concepts/HTTP/RemoteFlowSources.ql
+++ b/go/ql/test/library-tests/semmle/go/concepts/HTTP/RemoteFlowSources.ql
@@ -1,3 +1,3 @@
import go
-select any(RemoteFlowSource ufs)
+select any(RemoteFlowSource rfs)
From 0a2ed8302ab51a1e688aee18f12273c240b69da0 Mon Sep 17 00:00:00 2001
From: Owen Mansel-Chan
Date: Thu, 18 Jul 2024 07:45:03 +0100
Subject: [PATCH 039/140] Add test for websocket remote flow sources
---
.../go/frameworks/WebSocket/RemoteFlowSources.expected | 9 +++++++++
.../semmle/go/frameworks/WebSocket/RemoteFlowSources.ql | 3 +++
2 files changed, 12 insertions(+)
create mode 100644 go/ql/test/library-tests/semmle/go/frameworks/WebSocket/RemoteFlowSources.expected
create mode 100644 go/ql/test/library-tests/semmle/go/frameworks/WebSocket/RemoteFlowSources.ql
diff --git a/go/ql/test/library-tests/semmle/go/frameworks/WebSocket/RemoteFlowSources.expected b/go/ql/test/library-tests/semmle/go/frameworks/WebSocket/RemoteFlowSources.expected
new file mode 100644
index 0000000000000..0124cf73218ff
--- /dev/null
+++ b/go/ql/test/library-tests/semmle/go/frameworks/WebSocket/RemoteFlowSources.expected
@@ -0,0 +1,9 @@
+| WebSocketReadWrite.go:27:9:27:16 | selection of Header |
+| WebSocketReadWrite.go:31:7:31:10 | definition of xnet |
+| WebSocketReadWrite.go:35:3:35:7 | definition of xnet2 |
+| WebSocketReadWrite.go:41:3:41:40 | ... := ...[1] |
+| WebSocketReadWrite.go:44:3:44:48 | ... := ...[1] |
+| WebSocketReadWrite.go:51:7:51:16 | definition of gorillaMsg |
+| WebSocketReadWrite.go:55:3:55:10 | definition of gorilla2 |
+| WebSocketReadWrite.go:61:3:61:38 | ... := ...[1] |
+| WebSocketReadWrite.go:67:3:67:36 | ... := ...[0] |
diff --git a/go/ql/test/library-tests/semmle/go/frameworks/WebSocket/RemoteFlowSources.ql b/go/ql/test/library-tests/semmle/go/frameworks/WebSocket/RemoteFlowSources.ql
new file mode 100644
index 0000000000000..9e68fd210ff23
--- /dev/null
+++ b/go/ql/test/library-tests/semmle/go/frameworks/WebSocket/RemoteFlowSources.ql
@@ -0,0 +1,3 @@
+import go
+
+select any(RemoteFlowSource rfs)
From fc17b905f095244e2a0387af1b40f40bc838d61c Mon Sep 17 00:00:00 2001
From: Owen Mansel-Chan
Date: Thu, 18 Jul 2024 10:53:13 +0100
Subject: [PATCH 040/140] Convert WebSocketReaderAsSource to MaD
---
go/ql/lib/ext/github.com.gobwas.ws.model.yml | 7 +++++++
go/ql/lib/ext/github.com.gorilla.websocket.model.yml | 8 ++++++++
go/ql/lib/ext/github.com.revel.revel.model.yml | 2 ++
go/ql/lib/ext/golang.org.x.net.websocket.model.yml | 7 +++++++
go/ql/lib/ext/nhooyr.io.websocket.model.yml | 7 +++++++
go/ql/lib/semmle/go/frameworks/WebSocket.qll | 4 +++-
6 files changed, 34 insertions(+), 1 deletion(-)
create mode 100644 go/ql/lib/ext/github.com.gobwas.ws.model.yml
create mode 100644 go/ql/lib/ext/github.com.gorilla.websocket.model.yml
create mode 100644 go/ql/lib/ext/golang.org.x.net.websocket.model.yml
create mode 100644 go/ql/lib/ext/nhooyr.io.websocket.model.yml
diff --git a/go/ql/lib/ext/github.com.gobwas.ws.model.yml b/go/ql/lib/ext/github.com.gobwas.ws.model.yml
new file mode 100644
index 0000000000000..bb03c8220c883
--- /dev/null
+++ b/go/ql/lib/ext/github.com.gobwas.ws.model.yml
@@ -0,0 +1,7 @@
+extensions:
+ - addsTo:
+ pack: codeql/go-all
+ extensible: sourceModel
+ data:
+ - ["github.com/gobwas/ws", "", True, "ReadFrame", "", "", "ReturnValue[0]", "remote", "manual"]
+ - ["github.com/gobwas/ws", "", True, "ReadHeader", "", "", "ReturnValue[0]", "remote", "manual"]
diff --git a/go/ql/lib/ext/github.com.gorilla.websocket.model.yml b/go/ql/lib/ext/github.com.gorilla.websocket.model.yml
new file mode 100644
index 0000000000000..a4dafa18b0b23
--- /dev/null
+++ b/go/ql/lib/ext/github.com.gorilla.websocket.model.yml
@@ -0,0 +1,8 @@
+extensions:
+ - addsTo:
+ pack: codeql/go-all
+ extensible: sourceModel
+ data:
+ - ["github.com/gorilla/websocket", "", True, "ReadJSON", "", "", "Argument[1]", "remote", "manual"]
+ - ["github.com/gorilla/websocket", "Conn", True, "ReadJSON", "", "", "Argument[0]", "remote", "manual"]
+ - ["github.com/gorilla/websocket", "Conn", True, "ReadMessage", "", "", "ReturnValue[1]", "remote", "manual"]
diff --git a/go/ql/lib/ext/github.com.revel.revel.model.yml b/go/ql/lib/ext/github.com.revel.revel.model.yml
index 42f77a42ba42b..e5907088dff11 100644
--- a/go/ql/lib/ext/github.com.revel.revel.model.yml
+++ b/go/ql/lib/ext/github.com.revel.revel.model.yml
@@ -30,6 +30,8 @@ extensions:
- ["group:revel", "Request", True, "PostFormValue", "", "", "ReturnValue", "remote", "manual"]
- ["group:revel", "Request", True, "Referer", "", "", "ReturnValue", "remote", "manual"]
- ["group:revel", "Request", True, "UserAgent", "", "", "ReturnValue", "remote", "manual"]
+ - ["group:revel", "ServerWebSocket", True, "MessageReceive", "", "", "Argument[0]", "remote", "manual"]
+ - ["group:revel", "ServerWebSocket", True, "MessageReceiveJSON", "", "", "Argument[0]", "remote", "manual"]
- addsTo:
pack: codeql/go-all
extensible: summaryModel
diff --git a/go/ql/lib/ext/golang.org.x.net.websocket.model.yml b/go/ql/lib/ext/golang.org.x.net.websocket.model.yml
new file mode 100644
index 0000000000000..422d74248a59d
--- /dev/null
+++ b/go/ql/lib/ext/golang.org.x.net.websocket.model.yml
@@ -0,0 +1,7 @@
+extensions:
+ - addsTo:
+ pack: codeql/go-all
+ extensible: sourceModel
+ data:
+ - ["golang.org/x/net/websocket", "Codec", True, "Receive", "", "", "Argument[1]", "remote", "manual"]
+ - ["golang.org/x/net/websocket", "Conn", True, "Read", "", "", "Argument[0]", "remote", "manual"]
diff --git a/go/ql/lib/ext/nhooyr.io.websocket.model.yml b/go/ql/lib/ext/nhooyr.io.websocket.model.yml
new file mode 100644
index 0000000000000..bb94c1ce2d4c1
--- /dev/null
+++ b/go/ql/lib/ext/nhooyr.io.websocket.model.yml
@@ -0,0 +1,7 @@
+extensions:
+ - addsTo:
+ pack: codeql/go-all
+ extensible: sourceModel
+ data:
+ - ["nhooyr.io/websocket", "Conn", True, "Read", "", "", "ReturnValue[1]", "remote", "manual"]
+ - ["nhooyr.io/websocket", "Conn", True, "Reader", "", "", "ReturnValue[1]", "remote", "manual"]
diff --git a/go/ql/lib/semmle/go/frameworks/WebSocket.qll b/go/ql/lib/semmle/go/frameworks/WebSocket.qll
index 8d201a1f1a1fb..eb6160214cced 100644
--- a/go/ql/lib/semmle/go/frameworks/WebSocket.qll
+++ b/go/ql/lib/semmle/go/frameworks/WebSocket.qll
@@ -125,9 +125,11 @@ module WebSocketRequestCall {
}
/**
+ * DEPRECATED: Use `WebSocketReader` or `RemoteFlowSource::Range` instead.
+ *
* A message written to a WebSocket, considered as a flow sink for reflected XSS.
*/
-class WebSocketReaderAsSource extends RemoteFlowSource::Range {
+deprecated class WebSocketReaderAsSource extends RemoteFlowSource::Range {
WebSocketReaderAsSource() {
exists(WebSocketReader r | this = r.getAnOutput().getNode(r.getACall()))
}
From cb0589dfb7a0593fb42760722e5669e007af3262 Mon Sep 17 00:00:00 2001
From: Owen Mansel-Chan
Date: Thu, 18 Jul 2024 11:35:52 +0100
Subject: [PATCH 041/140] Tests: accept model numbering changes
---
.../CWE-090/LDAPInjection.expected | 28 ++++----
.../test/experimental/CWE-203/Timing.expected | 6 +-
.../CWE-287/ImproperLdapAuth.expected | 2 +-
.../CWE-369/DivideByZero.expected | 12 ++--
.../DecompressionBombs.expected | 44 ++++++-------
.../experimental/CWE-74/DsnInjection.expected | 2 +-
.../HTMLTemplateEscapingPassthrough.expected | 26 ++++----
go/ql/test/experimental/CWE-918/SSRF.expected | 22 +++----
.../DefaultSanitizer.expected | 6 +-
.../threat-models-flowtest1.expected | 4 +-
.../threat-models-flowtest2.expected | 4 +-
.../threat-models-flowtest3.expected | 4 +-
.../threat-models-flowtest4.expected | 4 +-
.../threat-models-flowtest5.expected | 4 +-
.../threat-models-flowtest6.expected | 4 +-
.../go/frameworks/Beego/ReflectedXss.expected | 4 +-
.../frameworks/BeegoOrm/SqlInjection.expected | 64 +++++++++----------
.../go/frameworks/Chi/ReflectedXss.expected | 2 +-
.../go/frameworks/Echo/OpenRedirect.expected | 6 +-
.../go/frameworks/Echo/ReflectedXss.expected | 50 +++++++--------
.../go/frameworks/Echo/TaintedPath.expected | 4 +-
.../go/frameworks/Encoding/jsoniter.expected | 8 +--
.../go/frameworks/Revel/OpenRedirect.expected | 4 +-
.../go/frameworks/Revel/ReflectedXss.expected | 16 ++---
.../go/frameworks/Revel/TaintedPath.expected | 8 +--
.../frameworks/Twirp/RequestForgery.expected | 4 +-
.../frameworks/XNetHtml/ReflectedXss.expected | 38 +++++------
.../frameworks/XNetHtml/SqlInjection.expected | 4 +-
.../Security/CWE-022/ZipSlip.expected | 4 +-
.../CWE-078/CommandInjection.expected | 16 ++---
.../Security/CWE-079/ReflectedXss.expected | 48 +++++++-------
.../Security/CWE-089/SqlInjection.expected | 24 +++----
.../Security/CWE-089/StringBreak.expected | 4 +-
.../CWE-312/CleartextLogging.expected | 4 +-
.../InsecureRandomness.expected | 2 +-
.../CWE-347/MissingJwtSignatureCheck.expected | 10 +--
.../BadRedirectCheck.expected | 4 +-
.../OpenUrlRedirect/OpenUrlRedirect.expected | 30 ++++-----
.../Security/CWE-640/EmailInjection.expected | 26 ++++----
.../Security/CWE-643/XPathInjection.expected | 24 +++----
.../Security/CWE-918/RequestForgery.expected | 34 +++++-----
41 files changed, 307 insertions(+), 307 deletions(-)
diff --git a/go/ql/test/experimental/CWE-090/LDAPInjection.expected b/go/ql/test/experimental/CWE-090/LDAPInjection.expected
index f9dbef7f0c309..514d041628925 100644
--- a/go/ql/test/experimental/CWE-090/LDAPInjection.expected
+++ b/go/ql/test/experimental/CWE-090/LDAPInjection.expected
@@ -1,18 +1,18 @@
edges
-| LDAPInjection.go:57:15:57:29 | call to UserAgent | LDAPInjection.go:59:3:59:11 | untrusted | provenance | Src:MaD:785 |
-| LDAPInjection.go:57:15:57:29 | call to UserAgent | LDAPInjection.go:61:3:61:51 | ...+... | provenance | Src:MaD:785 |
-| LDAPInjection.go:57:15:57:29 | call to UserAgent | LDAPInjection.go:62:3:62:33 | slice literal | provenance | Src:MaD:785 |
-| LDAPInjection.go:57:15:57:29 | call to UserAgent | LDAPInjection.go:62:24:62:32 | untrusted | provenance | Src:MaD:785 |
-| LDAPInjection.go:57:15:57:29 | call to UserAgent | LDAPInjection.go:66:3:66:11 | untrusted | provenance | Src:MaD:785 |
-| LDAPInjection.go:57:15:57:29 | call to UserAgent | LDAPInjection.go:68:3:68:51 | ...+... | provenance | Src:MaD:785 |
-| LDAPInjection.go:57:15:57:29 | call to UserAgent | LDAPInjection.go:69:3:69:33 | slice literal | provenance | Src:MaD:785 |
-| LDAPInjection.go:57:15:57:29 | call to UserAgent | LDAPInjection.go:69:24:69:32 | untrusted | provenance | Src:MaD:785 |
-| LDAPInjection.go:57:15:57:29 | call to UserAgent | LDAPInjection.go:73:3:73:11 | untrusted | provenance | Src:MaD:785 |
-| LDAPInjection.go:57:15:57:29 | call to UserAgent | LDAPInjection.go:75:3:75:51 | ...+... | provenance | Src:MaD:785 |
-| LDAPInjection.go:57:15:57:29 | call to UserAgent | LDAPInjection.go:76:3:76:33 | slice literal | provenance | Src:MaD:785 |
-| LDAPInjection.go:57:15:57:29 | call to UserAgent | LDAPInjection.go:76:24:76:32 | untrusted | provenance | Src:MaD:785 |
-| LDAPInjection.go:57:15:57:29 | call to UserAgent | LDAPInjection.go:80:22:80:30 | untrusted | provenance | Src:MaD:785 |
-| LDAPInjection.go:57:15:57:29 | call to UserAgent | LDAPInjection.go:81:25:81:33 | untrusted | provenance | Src:MaD:785 |
+| LDAPInjection.go:57:15:57:29 | call to UserAgent | LDAPInjection.go:59:3:59:11 | untrusted | provenance | Src:MaD:794 |
+| LDAPInjection.go:57:15:57:29 | call to UserAgent | LDAPInjection.go:61:3:61:51 | ...+... | provenance | Src:MaD:794 |
+| LDAPInjection.go:57:15:57:29 | call to UserAgent | LDAPInjection.go:62:3:62:33 | slice literal | provenance | Src:MaD:794 |
+| LDAPInjection.go:57:15:57:29 | call to UserAgent | LDAPInjection.go:62:24:62:32 | untrusted | provenance | Src:MaD:794 |
+| LDAPInjection.go:57:15:57:29 | call to UserAgent | LDAPInjection.go:66:3:66:11 | untrusted | provenance | Src:MaD:794 |
+| LDAPInjection.go:57:15:57:29 | call to UserAgent | LDAPInjection.go:68:3:68:51 | ...+... | provenance | Src:MaD:794 |
+| LDAPInjection.go:57:15:57:29 | call to UserAgent | LDAPInjection.go:69:3:69:33 | slice literal | provenance | Src:MaD:794 |
+| LDAPInjection.go:57:15:57:29 | call to UserAgent | LDAPInjection.go:69:24:69:32 | untrusted | provenance | Src:MaD:794 |
+| LDAPInjection.go:57:15:57:29 | call to UserAgent | LDAPInjection.go:73:3:73:11 | untrusted | provenance | Src:MaD:794 |
+| LDAPInjection.go:57:15:57:29 | call to UserAgent | LDAPInjection.go:75:3:75:51 | ...+... | provenance | Src:MaD:794 |
+| LDAPInjection.go:57:15:57:29 | call to UserAgent | LDAPInjection.go:76:3:76:33 | slice literal | provenance | Src:MaD:794 |
+| LDAPInjection.go:57:15:57:29 | call to UserAgent | LDAPInjection.go:76:24:76:32 | untrusted | provenance | Src:MaD:794 |
+| LDAPInjection.go:57:15:57:29 | call to UserAgent | LDAPInjection.go:80:22:80:30 | untrusted | provenance | Src:MaD:794 |
+| LDAPInjection.go:57:15:57:29 | call to UserAgent | LDAPInjection.go:81:25:81:33 | untrusted | provenance | Src:MaD:794 |
| LDAPInjection.go:62:3:62:33 | slice literal [array] | LDAPInjection.go:62:3:62:33 | slice literal | provenance | |
| LDAPInjection.go:62:24:62:32 | untrusted | LDAPInjection.go:62:3:62:33 | slice literal [array] | provenance | |
| LDAPInjection.go:69:3:69:33 | slice literal [array] | LDAPInjection.go:69:3:69:33 | slice literal | provenance | |
diff --git a/go/ql/test/experimental/CWE-203/Timing.expected b/go/ql/test/experimental/CWE-203/Timing.expected
index 7082b67f8e7d7..11ccfa802c34b 100644
--- a/go/ql/test/experimental/CWE-203/Timing.expected
+++ b/go/ql/test/experimental/CWE-203/Timing.expected
@@ -1,9 +1,9 @@
edges
-| timing.go:15:18:15:27 | selection of Header | timing.go:15:18:15:45 | call to Get | provenance | Src:MaD:791 MaD:766 |
+| timing.go:15:18:15:27 | selection of Header | timing.go:15:18:15:45 | call to Get | provenance | Src:MaD:800 MaD:775 |
| timing.go:15:18:15:45 | call to Get | timing.go:17:31:17:42 | headerSecret | provenance | |
-| timing.go:28:18:28:27 | selection of Header | timing.go:28:18:28:45 | call to Get | provenance | Src:MaD:791 MaD:766 |
+| timing.go:28:18:28:27 | selection of Header | timing.go:28:18:28:45 | call to Get | provenance | Src:MaD:800 MaD:775 |
| timing.go:28:18:28:45 | call to Get | timing.go:30:47:30:58 | headerSecret | provenance | |
-| timing.go:41:18:41:27 | selection of Header | timing.go:41:18:41:45 | call to Get | provenance | Src:MaD:791 MaD:766 |
+| timing.go:41:18:41:27 | selection of Header | timing.go:41:18:41:45 | call to Get | provenance | Src:MaD:800 MaD:775 |
| timing.go:41:18:41:45 | call to Get | timing.go:42:25:42:36 | headerSecret | provenance | |
nodes
| timing.go:15:18:15:27 | selection of Header | semmle.label | selection of Header |
diff --git a/go/ql/test/experimental/CWE-287/ImproperLdapAuth.expected b/go/ql/test/experimental/CWE-287/ImproperLdapAuth.expected
index 4a16afdfde60f..e1b5b23f1ddfc 100644
--- a/go/ql/test/experimental/CWE-287/ImproperLdapAuth.expected
+++ b/go/ql/test/experimental/CWE-287/ImproperLdapAuth.expected
@@ -1,5 +1,5 @@
edges
-| ImproperLdapAuth.go:18:18:18:24 | selection of URL | ImproperLdapAuth.go:18:18:18:32 | call to Query | provenance | Src:MaD:793 MaD:854 |
+| ImproperLdapAuth.go:18:18:18:24 | selection of URL | ImproperLdapAuth.go:18:18:18:32 | call to Query | provenance | Src:MaD:802 MaD:863 |
| ImproperLdapAuth.go:18:18:18:32 | call to Query | ImproperLdapAuth.go:28:23:28:34 | bindPassword | provenance | |
| ImproperLdapAuth.go:87:18:87:19 | "" | ImproperLdapAuth.go:97:23:97:34 | bindPassword | provenance | |
nodes
diff --git a/go/ql/test/experimental/CWE-369/DivideByZero.expected b/go/ql/test/experimental/CWE-369/DivideByZero.expected
index 50d0fd6f74914..f9e0a4905cb5c 100644
--- a/go/ql/test/experimental/CWE-369/DivideByZero.expected
+++ b/go/ql/test/experimental/CWE-369/DivideByZero.expected
@@ -1,24 +1,24 @@
edges
-| DivideByZero.go:10:12:10:16 | selection of URL | DivideByZero.go:10:12:10:24 | call to Query | provenance | Src:MaD:793 MaD:854 |
+| DivideByZero.go:10:12:10:16 | selection of URL | DivideByZero.go:10:12:10:24 | call to Query | provenance | Src:MaD:802 MaD:863 |
| DivideByZero.go:10:12:10:24 | call to Query | DivideByZero.go:11:27:11:32 | param1 | provenance | |
| DivideByZero.go:11:2:11:33 | ... := ...[0] | DivideByZero.go:12:16:12:20 | value | provenance | |
| DivideByZero.go:11:27:11:32 | param1 | DivideByZero.go:11:2:11:33 | ... := ...[0] | provenance | Config |
-| DivideByZero.go:17:12:17:16 | selection of URL | DivideByZero.go:17:12:17:24 | call to Query | provenance | Src:MaD:793 MaD:854 |
+| DivideByZero.go:17:12:17:16 | selection of URL | DivideByZero.go:17:12:17:24 | call to Query | provenance | Src:MaD:802 MaD:863 |
| DivideByZero.go:17:12:17:24 | call to Query | DivideByZero.go:18:11:18:24 | type conversion | provenance | |
| DivideByZero.go:18:11:18:24 | type conversion | DivideByZero.go:19:16:19:20 | value | provenance | |
-| DivideByZero.go:24:12:24:16 | selection of URL | DivideByZero.go:24:12:24:24 | call to Query | provenance | Src:MaD:793 MaD:854 |
+| DivideByZero.go:24:12:24:16 | selection of URL | DivideByZero.go:24:12:24:24 | call to Query | provenance | Src:MaD:802 MaD:863 |
| DivideByZero.go:24:12:24:24 | call to Query | DivideByZero.go:25:31:25:36 | param1 | provenance | |
| DivideByZero.go:25:2:25:45 | ... := ...[0] | DivideByZero.go:26:16:26:20 | value | provenance | |
| DivideByZero.go:25:31:25:36 | param1 | DivideByZero.go:25:2:25:45 | ... := ...[0] | provenance | Config |
-| DivideByZero.go:31:12:31:16 | selection of URL | DivideByZero.go:31:12:31:24 | call to Query | provenance | Src:MaD:793 MaD:854 |
+| DivideByZero.go:31:12:31:16 | selection of URL | DivideByZero.go:31:12:31:24 | call to Query | provenance | Src:MaD:802 MaD:863 |
| DivideByZero.go:31:12:31:24 | call to Query | DivideByZero.go:32:33:32:38 | param1 | provenance | |
| DivideByZero.go:32:2:32:43 | ... := ...[0] | DivideByZero.go:33:16:33:20 | value | provenance | |
| DivideByZero.go:32:33:32:38 | param1 | DivideByZero.go:32:2:32:43 | ... := ...[0] | provenance | Config |
-| DivideByZero.go:38:12:38:16 | selection of URL | DivideByZero.go:38:12:38:24 | call to Query | provenance | Src:MaD:793 MaD:854 |
+| DivideByZero.go:38:12:38:16 | selection of URL | DivideByZero.go:38:12:38:24 | call to Query | provenance | Src:MaD:802 MaD:863 |
| DivideByZero.go:38:12:38:24 | call to Query | DivideByZero.go:39:32:39:37 | param1 | provenance | |
| DivideByZero.go:39:2:39:46 | ... := ...[0] | DivideByZero.go:40:16:40:20 | value | provenance | |
| DivideByZero.go:39:32:39:37 | param1 | DivideByZero.go:39:2:39:46 | ... := ...[0] | provenance | Config |
-| DivideByZero.go:54:12:54:16 | selection of URL | DivideByZero.go:54:12:54:24 | call to Query | provenance | Src:MaD:793 MaD:854 |
+| DivideByZero.go:54:12:54:16 | selection of URL | DivideByZero.go:54:12:54:24 | call to Query | provenance | Src:MaD:802 MaD:863 |
| DivideByZero.go:54:12:54:24 | call to Query | DivideByZero.go:55:11:55:24 | type conversion | provenance | |
| DivideByZero.go:55:11:55:24 | type conversion | DivideByZero.go:57:17:57:21 | value | provenance | |
nodes
diff --git a/go/ql/test/experimental/CWE-522-DecompressionBombs/DecompressionBombs.expected b/go/ql/test/experimental/CWE-522-DecompressionBombs/DecompressionBombs.expected
index 848e57fe9b8b1..324734afd6c8c 100644
--- a/go/ql/test/experimental/CWE-522-DecompressionBombs/DecompressionBombs.expected
+++ b/go/ql/test/experimental/CWE-522-DecompressionBombs/DecompressionBombs.expected
@@ -1,24 +1,24 @@
edges
-| test.go:59:16:59:44 | call to FormValue | test.go:128:20:128:27 | definition of filename | provenance | Src:MaD:781 |
-| test.go:60:15:60:26 | selection of Body | test.go:158:19:158:22 | definition of file | provenance | Src:MaD:786 |
-| test.go:61:24:61:35 | selection of Body | test.go:169:28:169:31 | definition of file | provenance | Src:MaD:786 |
-| test.go:62:13:62:24 | selection of Body | test.go:181:17:181:20 | definition of file | provenance | Src:MaD:786 |
-| test.go:64:8:64:19 | selection of Body | test.go:208:12:208:15 | definition of file | provenance | Src:MaD:786 |
-| test.go:66:8:66:19 | selection of Body | test.go:233:12:233:15 | definition of file | provenance | Src:MaD:786 |
-| test.go:68:17:68:28 | selection of Body | test.go:258:21:258:24 | definition of file | provenance | Src:MaD:786 |
-| test.go:70:13:70:24 | selection of Body | test.go:283:17:283:20 | definition of file | provenance | Src:MaD:786 |
-| test.go:72:16:72:27 | selection of Body | test.go:308:20:308:23 | definition of file | provenance | Src:MaD:786 |
-| test.go:74:7:74:18 | selection of Body | test.go:333:11:333:14 | definition of file | provenance | Src:MaD:786 |
-| test.go:76:9:76:20 | selection of Body | test.go:358:13:358:16 | definition of file | provenance | Src:MaD:786 |
-| test.go:78:18:78:29 | selection of Body | test.go:384:22:384:25 | definition of file | provenance | Src:MaD:786 |
-| test.go:80:5:80:16 | selection of Body | test.go:412:9:412:12 | definition of file | provenance | Src:MaD:786 |
-| test.go:82:7:82:18 | selection of Body | test.go:447:11:447:14 | definition of file | provenance | Src:MaD:786 |
-| test.go:84:15:84:26 | selection of Body | test.go:440:19:440:21 | definition of src | provenance | Src:MaD:786 |
-| test.go:85:16:85:27 | selection of Body | test.go:472:20:472:23 | definition of file | provenance | Src:MaD:786 |
-| test.go:87:16:87:27 | selection of Body | test.go:499:20:499:23 | definition of file | provenance | Src:MaD:786 |
-| test.go:89:17:89:28 | selection of Body | test.go:526:21:526:24 | definition of file | provenance | Src:MaD:786 |
-| test.go:91:15:91:26 | selection of Body | test.go:555:19:555:22 | definition of file | provenance | Src:MaD:786 |
-| test.go:93:5:93:16 | selection of Body | test.go:580:9:580:12 | definition of file | provenance | Src:MaD:786 |
+| test.go:59:16:59:44 | call to FormValue | test.go:128:20:128:27 | definition of filename | provenance | Src:MaD:790 |
+| test.go:60:15:60:26 | selection of Body | test.go:158:19:158:22 | definition of file | provenance | Src:MaD:795 |
+| test.go:61:24:61:35 | selection of Body | test.go:169:28:169:31 | definition of file | provenance | Src:MaD:795 |
+| test.go:62:13:62:24 | selection of Body | test.go:181:17:181:20 | definition of file | provenance | Src:MaD:795 |
+| test.go:64:8:64:19 | selection of Body | test.go:208:12:208:15 | definition of file | provenance | Src:MaD:795 |
+| test.go:66:8:66:19 | selection of Body | test.go:233:12:233:15 | definition of file | provenance | Src:MaD:795 |
+| test.go:68:17:68:28 | selection of Body | test.go:258:21:258:24 | definition of file | provenance | Src:MaD:795 |
+| test.go:70:13:70:24 | selection of Body | test.go:283:17:283:20 | definition of file | provenance | Src:MaD:795 |
+| test.go:72:16:72:27 | selection of Body | test.go:308:20:308:23 | definition of file | provenance | Src:MaD:795 |
+| test.go:74:7:74:18 | selection of Body | test.go:333:11:333:14 | definition of file | provenance | Src:MaD:795 |
+| test.go:76:9:76:20 | selection of Body | test.go:358:13:358:16 | definition of file | provenance | Src:MaD:795 |
+| test.go:78:18:78:29 | selection of Body | test.go:384:22:384:25 | definition of file | provenance | Src:MaD:795 |
+| test.go:80:5:80:16 | selection of Body | test.go:412:9:412:12 | definition of file | provenance | Src:MaD:795 |
+| test.go:82:7:82:18 | selection of Body | test.go:447:11:447:14 | definition of file | provenance | Src:MaD:795 |
+| test.go:84:15:84:26 | selection of Body | test.go:440:19:440:21 | definition of src | provenance | Src:MaD:795 |
+| test.go:85:16:85:27 | selection of Body | test.go:472:20:472:23 | definition of file | provenance | Src:MaD:795 |
+| test.go:87:16:87:27 | selection of Body | test.go:499:20:499:23 | definition of file | provenance | Src:MaD:795 |
+| test.go:89:17:89:28 | selection of Body | test.go:526:21:526:24 | definition of file | provenance | Src:MaD:795 |
+| test.go:91:15:91:26 | selection of Body | test.go:555:19:555:22 | definition of file | provenance | Src:MaD:795 |
+| test.go:93:5:93:16 | selection of Body | test.go:580:9:580:12 | definition of file | provenance | Src:MaD:795 |
| test.go:128:20:128:27 | definition of filename | test.go:130:33:130:40 | filename | provenance | |
| test.go:128:20:128:27 | definition of filename | test.go:143:51:143:58 | filename | provenance | |
| test.go:130:2:130:41 | ... := ...[0] | test.go:132:12:132:12 | f | provenance | |
@@ -31,7 +31,7 @@ edges
| test.go:145:12:145:19 | call to Open | test.go:147:37:147:38 | rc | provenance | |
| test.go:158:19:158:22 | definition of file | test.go:159:25:159:28 | file | provenance | |
| test.go:159:2:159:29 | ... := ...[0] | test.go:160:48:160:52 | file1 | provenance | |
-| test.go:159:25:159:28 | file | test.go:159:2:159:29 | ... := ...[0] | provenance | MaD:658 |
+| test.go:159:25:159:28 | file | test.go:159:2:159:29 | ... := ...[0] | provenance | MaD:667 |
| test.go:160:2:160:69 | ... := ...[0] | test.go:163:26:163:29 | file | provenance | |
| test.go:160:32:160:53 | call to NewReader | test.go:160:2:160:69 | ... := ...[0] | provenance | Config |
| test.go:160:48:160:52 | file1 | test.go:160:32:160:53 | call to NewReader | provenance | MaD:46 |
@@ -39,7 +39,7 @@ edges
| test.go:163:26:163:29 | file | test.go:163:3:163:36 | ... := ...[0] | provenance | MaD:8 |
| test.go:169:28:169:31 | definition of file | test.go:170:25:170:28 | file | provenance | |
| test.go:170:2:170:29 | ... := ...[0] | test.go:171:57:171:61 | file2 | provenance | |
-| test.go:170:25:170:28 | file | test.go:170:2:170:29 | ... := ...[0] | provenance | MaD:658 |
+| test.go:170:25:170:28 | file | test.go:170:2:170:29 | ... := ...[0] | provenance | MaD:667 |
| test.go:171:2:171:78 | ... := ...[0] | test.go:175:26:175:29 | file | provenance | |
| test.go:171:41:171:62 | call to NewReader | test.go:171:2:171:78 | ... := ...[0] | provenance | Config |
| test.go:171:57:171:61 | file2 | test.go:171:41:171:62 | call to NewReader | provenance | MaD:46 |
diff --git a/go/ql/test/experimental/CWE-74/DsnInjection.expected b/go/ql/test/experimental/CWE-74/DsnInjection.expected
index e91036cc7129c..901f9fed3682c 100644
--- a/go/ql/test/experimental/CWE-74/DsnInjection.expected
+++ b/go/ql/test/experimental/CWE-74/DsnInjection.expected
@@ -1,5 +1,5 @@
edges
-| Dsn.go:47:10:47:30 | call to FormValue | Dsn.go:49:102:49:105 | name | provenance | Src:MaD:781 |
+| Dsn.go:47:10:47:30 | call to FormValue | Dsn.go:49:102:49:105 | name | provenance | Src:MaD:790 |
| Dsn.go:49:11:49:106 | []type{args} [array] | Dsn.go:49:11:49:106 | call to Sprintf | provenance | MaD:248 |
| Dsn.go:49:11:49:106 | call to Sprintf | Dsn.go:50:29:50:33 | dbDSN | provenance | |
| Dsn.go:49:102:49:105 | name | Dsn.go:49:11:49:106 | []type{args} [array] | provenance | |
diff --git a/go/ql/test/experimental/CWE-79/HTMLTemplateEscapingPassthrough.expected b/go/ql/test/experimental/CWE-79/HTMLTemplateEscapingPassthrough.expected
index 8b05d1a1b245b..28eb20587b685 100644
--- a/go/ql/test/experimental/CWE-79/HTMLTemplateEscapingPassthrough.expected
+++ b/go/ql/test/experimental/CWE-79/HTMLTemplateEscapingPassthrough.expected
@@ -1,28 +1,28 @@
edges
| HTMLTemplateEscapingPassthrough.go:29:12:29:41 | type conversion | HTMLTemplateEscapingPassthrough.go:30:39:30:39 | a | provenance | |
-| HTMLTemplateEscapingPassthrough.go:29:26:29:40 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:29:12:29:41 | type conversion | provenance | Src:MaD:785 |
+| HTMLTemplateEscapingPassthrough.go:29:26:29:40 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:29:12:29:41 | type conversion | provenance | Src:MaD:794 |
| HTMLTemplateEscapingPassthrough.go:35:9:35:38 | type conversion | HTMLTemplateEscapingPassthrough.go:36:40:36:40 | a | provenance | |
-| HTMLTemplateEscapingPassthrough.go:35:23:35:37 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:35:9:35:38 | type conversion | provenance | Src:MaD:785 |
+| HTMLTemplateEscapingPassthrough.go:35:23:35:37 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:35:9:35:38 | type conversion | provenance | Src:MaD:794 |
| HTMLTemplateEscapingPassthrough.go:40:9:40:34 | type conversion | HTMLTemplateEscapingPassthrough.go:41:40:41:40 | a | provenance | |
-| HTMLTemplateEscapingPassthrough.go:40:19:40:33 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:40:9:40:34 | type conversion | provenance | Src:MaD:785 |
+| HTMLTemplateEscapingPassthrough.go:40:19:40:33 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:40:9:40:34 | type conversion | provenance | Src:MaD:794 |
| HTMLTemplateEscapingPassthrough.go:46:11:46:44 | type conversion | HTMLTemplateEscapingPassthrough.go:47:41:47:41 | c | provenance | |
-| HTMLTemplateEscapingPassthrough.go:46:29:46:43 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:46:11:46:44 | type conversion | provenance | Src:MaD:785 |
+| HTMLTemplateEscapingPassthrough.go:46:29:46:43 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:46:11:46:44 | type conversion | provenance | Src:MaD:794 |
| HTMLTemplateEscapingPassthrough.go:50:11:50:38 | type conversion | HTMLTemplateEscapingPassthrough.go:51:44:51:44 | d | provenance | |
-| HTMLTemplateEscapingPassthrough.go:50:23:50:37 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:50:11:50:38 | type conversion | provenance | Src:MaD:785 |
+| HTMLTemplateEscapingPassthrough.go:50:23:50:37 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:50:11:50:38 | type conversion | provenance | Src:MaD:794 |
| HTMLTemplateEscapingPassthrough.go:54:11:54:41 | type conversion | HTMLTemplateEscapingPassthrough.go:55:44:55:44 | e | provenance | |
-| HTMLTemplateEscapingPassthrough.go:54:26:54:40 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:54:11:54:41 | type conversion | provenance | Src:MaD:785 |
+| HTMLTemplateEscapingPassthrough.go:54:26:54:40 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:54:11:54:41 | type conversion | provenance | Src:MaD:794 |
| HTMLTemplateEscapingPassthrough.go:58:11:58:39 | type conversion | HTMLTemplateEscapingPassthrough.go:59:38:59:38 | b | provenance | |
-| HTMLTemplateEscapingPassthrough.go:58:24:58:38 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:58:11:58:39 | type conversion | provenance | Src:MaD:785 |
+| HTMLTemplateEscapingPassthrough.go:58:24:58:38 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:58:11:58:39 | type conversion | provenance | Src:MaD:794 |
| HTMLTemplateEscapingPassthrough.go:62:11:62:42 | type conversion | HTMLTemplateEscapingPassthrough.go:63:44:63:44 | f | provenance | |
-| HTMLTemplateEscapingPassthrough.go:62:27:62:41 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:62:11:62:42 | type conversion | provenance | Src:MaD:785 |
+| HTMLTemplateEscapingPassthrough.go:62:27:62:41 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:62:11:62:42 | type conversion | provenance | Src:MaD:794 |
| HTMLTemplateEscapingPassthrough.go:66:11:66:39 | type conversion | HTMLTemplateEscapingPassthrough.go:67:38:67:38 | g | provenance | |
-| HTMLTemplateEscapingPassthrough.go:66:24:66:38 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:66:11:66:39 | type conversion | provenance | Src:MaD:785 |
-| HTMLTemplateEscapingPassthrough.go:75:17:75:31 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:76:38:76:44 | escaped | provenance | Src:MaD:785 |
-| HTMLTemplateEscapingPassthrough.go:81:10:81:24 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:84:38:84:40 | src | provenance | Src:MaD:785 |
-| HTMLTemplateEscapingPassthrough.go:89:10:89:24 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:91:64:91:66 | src | provenance | Src:MaD:785 |
+| HTMLTemplateEscapingPassthrough.go:66:24:66:38 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:66:11:66:39 | type conversion | provenance | Src:MaD:794 |
+| HTMLTemplateEscapingPassthrough.go:75:17:75:31 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:76:38:76:44 | escaped | provenance | Src:MaD:794 |
+| HTMLTemplateEscapingPassthrough.go:81:10:81:24 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:84:38:84:40 | src | provenance | Src:MaD:794 |
+| HTMLTemplateEscapingPassthrough.go:89:10:89:24 | call to UserAgent | HTMLTemplateEscapingPassthrough.go:91:64:91:66 | src | provenance | Src:MaD:794 |
| HTMLTemplateEscapingPassthrough.go:91:16:91:77 | type conversion | HTMLTemplateEscapingPassthrough.go:92:38:92:46 | converted | provenance | |
| HTMLTemplateEscapingPassthrough.go:91:38:91:67 | call to HTMLEscapeString | HTMLTemplateEscapingPassthrough.go:91:16:91:77 | type conversion | provenance | |
-| HTMLTemplateEscapingPassthrough.go:91:64:91:66 | src | HTMLTemplateEscapingPassthrough.go:91:38:91:67 | call to HTMLEscapeString | provenance | MaD:633 |
+| HTMLTemplateEscapingPassthrough.go:91:64:91:66 | src | HTMLTemplateEscapingPassthrough.go:91:38:91:67 | call to HTMLEscapeString | provenance | MaD:642 |
nodes
| HTMLTemplateEscapingPassthrough.go:29:12:29:41 | type conversion | semmle.label | type conversion |
| HTMLTemplateEscapingPassthrough.go:29:26:29:40 | call to UserAgent | semmle.label | call to UserAgent |
diff --git a/go/ql/test/experimental/CWE-918/SSRF.expected b/go/ql/test/experimental/CWE-918/SSRF.expected
index 17779bff56962..1e8f3bcd393cf 100644
--- a/go/ql/test/experimental/CWE-918/SSRF.expected
+++ b/go/ql/test/experimental/CWE-918/SSRF.expected
@@ -1,9 +1,9 @@
edges
-| builtin.go:19:12:19:34 | call to FormValue | builtin.go:22:21:22:62 | ...+... | provenance | Src:MaD:781 |
-| builtin.go:83:21:83:31 | call to Referer | builtin.go:88:27:88:40 | untrustedInput | provenance | Src:MaD:784 |
-| builtin.go:97:21:97:31 | call to Referer | builtin.go:101:36:101:49 | untrustedInput | provenance | Src:MaD:784 |
-| builtin.go:111:21:111:31 | call to Referer | builtin.go:114:15:114:28 | untrustedInput | provenance | Src:MaD:784 |
-| builtin.go:129:21:129:31 | call to Referer | builtin.go:132:38:132:51 | untrustedInput | provenance | Src:MaD:784 |
+| builtin.go:19:12:19:34 | call to FormValue | builtin.go:22:21:22:62 | ...+... | provenance | Src:MaD:790 |
+| builtin.go:83:21:83:31 | call to Referer | builtin.go:88:27:88:40 | untrustedInput | provenance | Src:MaD:793 |
+| builtin.go:97:21:97:31 | call to Referer | builtin.go:101:36:101:49 | untrustedInput | provenance | Src:MaD:793 |
+| builtin.go:111:21:111:31 | call to Referer | builtin.go:114:15:114:28 | untrustedInput | provenance | Src:MaD:793 |
+| builtin.go:129:21:129:31 | call to Referer | builtin.go:132:38:132:51 | untrustedInput | provenance | Src:MaD:793 |
| new-tests.go:26:26:26:30 | &... | new-tests.go:31:48:31:56 | selection of word | provenance | Src:MaD:402 |
| new-tests.go:26:26:26:30 | &... | new-tests.go:32:48:32:56 | selection of safe | provenance | Src:MaD:402 |
| new-tests.go:26:26:26:30 | &... | new-tests.go:35:49:35:57 | selection of word | provenance | Src:MaD:402 |
@@ -19,7 +19,7 @@ edges
| new-tests.go:39:18:39:30 | call to Param | new-tests.go:47:11:47:46 | ...+... | provenance | Src:MaD:391 |
| new-tests.go:49:18:49:30 | call to Query | new-tests.go:50:11:50:46 | ...+... | provenance | Src:MaD:396 |
| new-tests.go:62:2:62:39 | ... := ...[0] | new-tests.go:63:17:63:23 | reqBody | provenance | |
-| new-tests.go:62:31:62:38 | selection of Body | new-tests.go:62:2:62:39 | ... := ...[0] | provenance | Src:MaD:786 MaD:651 |
+| new-tests.go:62:31:62:38 | selection of Body | new-tests.go:62:2:62:39 | ... := ...[0] | provenance | Src:MaD:795 MaD:660 |
| new-tests.go:63:17:63:23 | reqBody | new-tests.go:63:26:63:30 | &... | provenance | MaD:187 |
| new-tests.go:63:26:63:30 | &... | new-tests.go:68:48:68:56 | selection of word | provenance | |
| new-tests.go:63:26:63:30 | &... | new-tests.go:69:48:69:56 | selection of safe | provenance | |
@@ -33,13 +33,13 @@ edges
| new-tests.go:74:12:74:58 | []type{args} [array] | new-tests.go:74:12:74:58 | call to Sprintf | provenance | MaD:248 |
| new-tests.go:74:49:74:57 | selection of word | new-tests.go:74:12:74:58 | []type{args} [array] | provenance | |
| new-tests.go:74:49:74:57 | selection of word | new-tests.go:74:12:74:58 | call to Sprintf | provenance | FunctionModel |
-| new-tests.go:78:18:78:24 | selection of URL | new-tests.go:78:18:78:32 | call to Query | provenance | Src:MaD:793 MaD:854 |
-| new-tests.go:78:18:78:32 | call to Query | new-tests.go:78:18:78:46 | call to Get | provenance | MaD:861 |
+| new-tests.go:78:18:78:24 | selection of URL | new-tests.go:78:18:78:32 | call to Query | provenance | Src:MaD:802 MaD:863 |
+| new-tests.go:78:18:78:32 | call to Query | new-tests.go:78:18:78:46 | call to Get | provenance | MaD:870 |
| new-tests.go:78:18:78:46 | call to Get | new-tests.go:79:11:79:46 | ...+... | provenance | |
| new-tests.go:81:18:81:67 | call to TrimPrefix | new-tests.go:82:11:82:46 | ...+... | provenance | |
-| new-tests.go:81:37:81:43 | selection of URL | new-tests.go:81:37:81:48 | selection of Path | provenance | Src:MaD:793 |
-| new-tests.go:81:37:81:48 | selection of Path | new-tests.go:81:18:81:67 | call to TrimPrefix | provenance | MaD:977 |
-| new-tests.go:86:10:86:20 | call to Vars | new-tests.go:88:11:88:46 | ...+... | provenance | Src:MaD:445 |
+| new-tests.go:81:37:81:43 | selection of URL | new-tests.go:81:37:81:48 | selection of Path | provenance | Src:MaD:802 |
+| new-tests.go:81:37:81:48 | selection of Path | new-tests.go:81:18:81:67 | call to TrimPrefix | provenance | MaD:988 |
+| new-tests.go:86:10:86:20 | call to Vars | new-tests.go:88:11:88:46 | ...+... | provenance | Src:MaD:447 |
| new-tests.go:95:18:95:45 | call to URLParam | new-tests.go:96:11:96:46 | ...+... | provenance | Src:MaD:408 |
nodes
| builtin.go:19:12:19:34 | call to FormValue | semmle.label | call to FormValue |
diff --git a/go/ql/test/library-tests/semmle/go/dataflow/DefaultTaintSanitizer/DefaultSanitizer.expected b/go/ql/test/library-tests/semmle/go/dataflow/DefaultTaintSanitizer/DefaultSanitizer.expected
index 3d7bfa2706722..dd113996a23e6 100644
--- a/go/ql/test/library-tests/semmle/go/dataflow/DefaultTaintSanitizer/DefaultSanitizer.expected
+++ b/go/ql/test/library-tests/semmle/go/dataflow/DefaultTaintSanitizer/DefaultSanitizer.expected
@@ -1,10 +1,10 @@
edges
| Builtin.go:6:2:6:2 | definition of b | Builtin.go:8:9:8:17 | type conversion | provenance | |
-| Builtin.go:7:2:7:15 | selection of Body | Builtin.go:6:2:6:2 | definition of b | provenance | Src:MaD:786 MaD:664 |
+| Builtin.go:7:2:7:15 | selection of Body | Builtin.go:6:2:6:2 | definition of b | provenance | Src:MaD:795 MaD:673 |
| Builtin.go:12:2:12:2 | definition of b | Builtin.go:17:9:17:17 | type conversion | provenance | |
-| Builtin.go:13:2:13:15 | selection of Body | Builtin.go:12:2:12:2 | definition of b | provenance | Src:MaD:786 MaD:664 |
+| Builtin.go:13:2:13:15 | selection of Body | Builtin.go:12:2:12:2 | definition of b | provenance | Src:MaD:795 MaD:673 |
| Builtin.go:21:2:21:2 | definition of b | Builtin.go:24:10:24:18 | type conversion | provenance | |
-| Builtin.go:22:2:22:15 | selection of Body | Builtin.go:21:2:21:2 | definition of b | provenance | Src:MaD:786 MaD:664 |
+| Builtin.go:22:2:22:15 | selection of Body | Builtin.go:21:2:21:2 | definition of b | provenance | Src:MaD:795 MaD:673 |
nodes
| Builtin.go:6:2:6:2 | definition of b | semmle.label | definition of b |
| Builtin.go:7:2:7:15 | selection of Body | semmle.label | selection of Body |
diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ThreatModels/threat-models-flowtest1.expected b/go/ql/test/library-tests/semmle/go/dataflow/ThreatModels/threat-models-flowtest1.expected
index ab9512807fea7..30671016dcedf 100644
--- a/go/ql/test/library-tests/semmle/go/dataflow/ThreatModels/threat-models-flowtest1.expected
+++ b/go/ql/test/library-tests/semmle/go/dataflow/ThreatModels/threat-models-flowtest1.expected
@@ -1,6 +1,6 @@
edges
-| test.go:32:11:32:15 | selection of URL | test.go:32:11:32:23 | call to Query | provenance | Src:MaD:793 MaD:854 |
-| test.go:32:11:32:23 | call to Query | test.go:32:11:32:36 | call to Get | provenance | MaD:861 |
+| test.go:32:11:32:15 | selection of URL | test.go:32:11:32:23 | call to Query | provenance | Src:MaD:802 MaD:863 |
+| test.go:32:11:32:23 | call to Query | test.go:32:11:32:36 | call to Get | provenance | MaD:870 |
| test.go:32:11:32:36 | call to Get | test.go:34:7:34:30 | ...+... | provenance | |
nodes
| test.go:32:11:32:15 | selection of URL | semmle.label | selection of URL |
diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ThreatModels/threat-models-flowtest2.expected b/go/ql/test/library-tests/semmle/go/dataflow/ThreatModels/threat-models-flowtest2.expected
index 18bd5dbb71513..3d4edb7380848 100644
--- a/go/ql/test/library-tests/semmle/go/dataflow/ThreatModels/threat-models-flowtest2.expected
+++ b/go/ql/test/library-tests/semmle/go/dataflow/ThreatModels/threat-models-flowtest2.expected
@@ -1,7 +1,7 @@
edges
| test.go:27:11:27:63 | call to ExecuteQuery | test.go:28:7:28:11 | query | provenance | Src:MaD:1 |
-| test.go:32:11:32:15 | selection of URL | test.go:32:11:32:23 | call to Query | provenance | Src:MaD:793 MaD:854 |
-| test.go:32:11:32:23 | call to Query | test.go:32:11:32:36 | call to Get | provenance | MaD:861 |
+| test.go:32:11:32:15 | selection of URL | test.go:32:11:32:23 | call to Query | provenance | Src:MaD:802 MaD:863 |
+| test.go:32:11:32:23 | call to Query | test.go:32:11:32:36 | call to Get | provenance | MaD:870 |
| test.go:32:11:32:36 | call to Get | test.go:34:7:34:30 | ...+... | provenance | |
nodes
| test.go:27:11:27:63 | call to ExecuteQuery | semmle.label | call to ExecuteQuery |
diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ThreatModels/threat-models-flowtest3.expected b/go/ql/test/library-tests/semmle/go/dataflow/ThreatModels/threat-models-flowtest3.expected
index aa3c2226b5f66..401b39a979a5c 100644
--- a/go/ql/test/library-tests/semmle/go/dataflow/ThreatModels/threat-models-flowtest3.expected
+++ b/go/ql/test/library-tests/semmle/go/dataflow/ThreatModels/threat-models-flowtest3.expected
@@ -2,8 +2,8 @@ edges
| test.go:9:10:9:40 | call to ReadEnvironment | test.go:11:7:11:29 | ...+... | provenance | Src:MaD:2 |
| test.go:15:9:15:32 | call to GetCliArg | test.go:17:7:17:28 | ...+... | provenance | Src:MaD:4 |
| test.go:27:11:27:63 | call to ExecuteQuery | test.go:28:7:28:11 | query | provenance | Src:MaD:1 |
-| test.go:32:11:32:15 | selection of URL | test.go:32:11:32:23 | call to Query | provenance | Src:MaD:793 MaD:854 |
-| test.go:32:11:32:23 | call to Query | test.go:32:11:32:36 | call to Get | provenance | MaD:861 |
+| test.go:32:11:32:15 | selection of URL | test.go:32:11:32:23 | call to Query | provenance | Src:MaD:802 MaD:863 |
+| test.go:32:11:32:23 | call to Query | test.go:32:11:32:36 | call to Get | provenance | MaD:870 |
| test.go:32:11:32:36 | call to Get | test.go:34:7:34:30 | ...+... | provenance | |
nodes
| test.go:9:10:9:40 | call to ReadEnvironment | semmle.label | call to ReadEnvironment |
diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ThreatModels/threat-models-flowtest4.expected b/go/ql/test/library-tests/semmle/go/dataflow/ThreatModels/threat-models-flowtest4.expected
index d62f8ac21f327..c5d3e018e70ce 100644
--- a/go/ql/test/library-tests/semmle/go/dataflow/ThreatModels/threat-models-flowtest4.expected
+++ b/go/ql/test/library-tests/semmle/go/dataflow/ThreatModels/threat-models-flowtest4.expected
@@ -3,8 +3,8 @@ edges
| test.go:15:9:15:32 | call to GetCliArg | test.go:17:7:17:28 | ...+... | provenance | Src:MaD:4 |
| test.go:21:11:21:36 | call to GetCustom | test.go:23:7:23:30 | ...+... | provenance | Src:MaD:3 |
| test.go:27:11:27:63 | call to ExecuteQuery | test.go:28:7:28:11 | query | provenance | Src:MaD:1 |
-| test.go:32:11:32:15 | selection of URL | test.go:32:11:32:23 | call to Query | provenance | Src:MaD:793 MaD:854 |
-| test.go:32:11:32:23 | call to Query | test.go:32:11:32:36 | call to Get | provenance | MaD:861 |
+| test.go:32:11:32:15 | selection of URL | test.go:32:11:32:23 | call to Query | provenance | Src:MaD:802 MaD:863 |
+| test.go:32:11:32:23 | call to Query | test.go:32:11:32:36 | call to Get | provenance | MaD:870 |
| test.go:32:11:32:36 | call to Get | test.go:34:7:34:30 | ...+... | provenance | |
nodes
| test.go:9:10:9:40 | call to ReadEnvironment | semmle.label | call to ReadEnvironment |
diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ThreatModels/threat-models-flowtest5.expected b/go/ql/test/library-tests/semmle/go/dataflow/ThreatModels/threat-models-flowtest5.expected
index eb592b9ca4f59..312c91e1c4bf4 100644
--- a/go/ql/test/library-tests/semmle/go/dataflow/ThreatModels/threat-models-flowtest5.expected
+++ b/go/ql/test/library-tests/semmle/go/dataflow/ThreatModels/threat-models-flowtest5.expected
@@ -1,8 +1,8 @@
edges
| test.go:9:10:9:40 | call to ReadEnvironment | test.go:11:7:11:29 | ...+... | provenance | Src:MaD:3 |
| test.go:15:9:15:32 | call to GetCliArg | test.go:17:7:17:28 | ...+... | provenance | Src:MaD:5 |
-| test.go:32:11:32:15 | selection of URL | test.go:32:11:32:23 | call to Query | provenance | Src:MaD:793 MaD:854 |
-| test.go:32:11:32:23 | call to Query | test.go:32:11:32:36 | call to Get | provenance | MaD:861 |
+| test.go:32:11:32:15 | selection of URL | test.go:32:11:32:23 | call to Query | provenance | Src:MaD:802 MaD:863 |
+| test.go:32:11:32:23 | call to Query | test.go:32:11:32:36 | call to Get | provenance | MaD:870 |
| test.go:32:11:32:36 | call to Get | test.go:34:7:34:30 | ...+... | provenance | |
nodes
| test.go:9:10:9:40 | call to ReadEnvironment | semmle.label | call to ReadEnvironment |
diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ThreatModels/threat-models-flowtest6.expected b/go/ql/test/library-tests/semmle/go/dataflow/ThreatModels/threat-models-flowtest6.expected
index b60fb225f78c9..7e30904b70cca 100644
--- a/go/ql/test/library-tests/semmle/go/dataflow/ThreatModels/threat-models-flowtest6.expected
+++ b/go/ql/test/library-tests/semmle/go/dataflow/ThreatModels/threat-models-flowtest6.expected
@@ -1,8 +1,8 @@
edges
| test.go:15:9:15:32 | call to GetCliArg | test.go:17:7:17:28 | ...+... | provenance | Src:MaD:5 |
| test.go:27:11:27:63 | call to ExecuteQuery | test.go:28:7:28:11 | query | provenance | Src:MaD:2 |
-| test.go:32:11:32:15 | selection of URL | test.go:32:11:32:23 | call to Query | provenance | Src:MaD:793 MaD:854 |
-| test.go:32:11:32:23 | call to Query | test.go:32:11:32:36 | call to Get | provenance | MaD:861 |
+| test.go:32:11:32:15 | selection of URL | test.go:32:11:32:23 | call to Query | provenance | Src:MaD:802 MaD:863 |
+| test.go:32:11:32:23 | call to Query | test.go:32:11:32:36 | call to Get | provenance | MaD:870 |
| test.go:32:11:32:36 | call to Get | test.go:34:7:34:30 | ...+... | provenance | |
nodes
| test.go:15:9:15:32 | call to GetCliArg | semmle.label | call to GetCliArg |
diff --git a/go/ql/test/library-tests/semmle/go/frameworks/Beego/ReflectedXss.expected b/go/ql/test/library-tests/semmle/go/frameworks/Beego/ReflectedXss.expected
index 09272ea52b43d..fd6f8095ccc23 100644
--- a/go/ql/test/library-tests/semmle/go/frameworks/Beego/ReflectedXss.expected
+++ b/go/ql/test/library-tests/semmle/go/frameworks/Beego/ReflectedXss.expected
@@ -34,11 +34,11 @@ edges
| test.go:205:21:205:58 | call to Substr | test.go:205:14:205:59 | type conversion | provenance | |
| test.go:205:34:205:51 | type assertion | test.go:205:21:205:58 | call to Substr | provenance | MaD:294 |
| test.go:207:6:207:6 | definition of s | test.go:209:14:209:28 | type conversion | provenance | |
-| test.go:208:18:208:33 | selection of Form | test.go:207:6:207:6 | definition of s | provenance | Src:MaD:788 MaD:292 |
+| test.go:208:18:208:33 | selection of Form | test.go:207:6:207:6 | definition of s | provenance | Src:MaD:797 MaD:292 |
| test.go:223:2:223:34 | ... := ...[0] | test.go:225:31:225:31 | f | provenance | Src:MaD:296 |
| test.go:223:2:223:34 | ... := ...[1] | test.go:224:14:224:32 | type conversion | provenance | Src:MaD:296 |
| test.go:225:2:225:32 | ... := ...[0] | test.go:226:14:226:20 | content | provenance | |
-| test.go:225:31:225:31 | f | test.go:225:2:225:32 | ... := ...[0] | provenance | MaD:651 |
+| test.go:225:31:225:31 | f | test.go:225:2:225:32 | ... := ...[0] | provenance | MaD:660 |
| test.go:228:2:228:40 | ... := ...[0] | test.go:229:14:229:38 | type conversion | provenance | Src:MaD:297 |
| test.go:231:7:231:28 | call to GetString | test.go:232:14:232:22 | type conversion | provenance | Src:MaD:298 |
| test.go:234:8:234:35 | call to GetStrings | test.go:235:14:235:26 | type conversion | provenance | Src:MaD:299 |
diff --git a/go/ql/test/library-tests/semmle/go/frameworks/BeegoOrm/SqlInjection.expected b/go/ql/test/library-tests/semmle/go/frameworks/BeegoOrm/SqlInjection.expected
index 6702387136711..3122b2d226151 100644
--- a/go/ql/test/library-tests/semmle/go/frameworks/BeegoOrm/SqlInjection.expected
+++ b/go/ql/test/library-tests/semmle/go/frameworks/BeegoOrm/SqlInjection.expected
@@ -1,36 +1,36 @@
edges
-| test.go:10:15:10:41 | call to UserAgent | test.go:12:11:12:19 | untrusted | provenance | Src:MaD:785 |
-| test.go:10:15:10:41 | call to UserAgent | test.go:13:23:13:31 | untrusted | provenance | Src:MaD:785 |
-| test.go:10:15:10:41 | call to UserAgent | test.go:14:14:14:22 | untrusted | provenance | Src:MaD:785 |
-| test.go:10:15:10:41 | call to UserAgent | test.go:15:26:15:34 | untrusted | provenance | Src:MaD:785 |
-| test.go:10:15:10:41 | call to UserAgent | test.go:16:12:16:20 | untrusted | provenance | Src:MaD:785 |
-| test.go:10:15:10:41 | call to UserAgent | test.go:17:24:17:32 | untrusted | provenance | Src:MaD:785 |
-| test.go:10:15:10:41 | call to UserAgent | test.go:18:15:18:23 | untrusted | provenance | Src:MaD:785 |
-| test.go:10:15:10:41 | call to UserAgent | test.go:19:27:19:35 | untrusted | provenance | Src:MaD:785 |
-| test.go:24:15:24:41 | call to UserAgent | test.go:26:12:26:20 | untrusted | provenance | Src:MaD:785 |
-| test.go:24:15:24:41 | call to UserAgent | test.go:27:10:27:18 | untrusted | provenance | Src:MaD:785 |
-| test.go:24:15:24:41 | call to UserAgent | test.go:28:15:28:23 | untrusted | provenance | Src:MaD:785 |
-| test.go:24:15:24:41 | call to UserAgent | test.go:29:14:29:22 | untrusted | provenance | Src:MaD:785 |
-| test.go:24:15:24:41 | call to UserAgent | test.go:30:15:30:23 | untrusted | provenance | Src:MaD:785 |
-| test.go:24:15:24:41 | call to UserAgent | test.go:31:8:31:16 | untrusted | provenance | Src:MaD:785 |
-| test.go:24:15:24:41 | call to UserAgent | test.go:32:11:32:19 | untrusted | provenance | Src:MaD:785 |
-| test.go:24:15:24:41 | call to UserAgent | test.go:33:9:33:17 | untrusted | provenance | Src:MaD:785 |
-| test.go:24:15:24:41 | call to UserAgent | test.go:34:8:34:16 | untrusted | provenance | Src:MaD:785 |
-| test.go:24:15:24:41 | call to UserAgent | test.go:35:8:35:16 | untrusted | provenance | Src:MaD:785 |
-| test.go:24:15:24:41 | call to UserAgent | test.go:36:13:36:21 | untrusted | provenance | Src:MaD:785 |
-| test.go:24:15:24:41 | call to UserAgent | test.go:37:13:37:21 | untrusted | provenance | Src:MaD:785 |
-| test.go:24:15:24:41 | call to UserAgent | test.go:38:12:38:20 | untrusted | provenance | Src:MaD:785 |
-| test.go:24:15:24:41 | call to UserAgent | test.go:39:12:39:20 | untrusted | provenance | Src:MaD:785 |
-| test.go:24:15:24:41 | call to UserAgent | test.go:40:9:40:17 | untrusted | provenance | Src:MaD:785 |
-| test.go:24:15:24:41 | call to UserAgent | test.go:41:12:41:20 | untrusted | provenance | Src:MaD:785 |
-| test.go:24:15:24:41 | call to UserAgent | test.go:42:16:42:24 | untrusted | provenance | Src:MaD:785 |
-| test.go:24:15:24:41 | call to UserAgent | test.go:42:27:42:35 | untrusted | provenance | Src:MaD:785 |
-| test.go:24:15:24:41 | call to UserAgent | test.go:43:12:43:20 | untrusted | provenance | Src:MaD:785 |
-| test.go:24:15:24:41 | call to UserAgent | test.go:44:14:44:22 | untrusted | provenance | Src:MaD:785 |
-| test.go:24:15:24:41 | call to UserAgent | test.go:44:25:44:33 | untrusted | provenance | Src:MaD:785 |
-| test.go:48:15:48:41 | call to UserAgent | test.go:49:12:49:20 | untrusted | provenance | Src:MaD:785 |
-| test.go:54:15:54:41 | call to UserAgent | test.go:56:31:56:39 | untrusted | provenance | Src:MaD:785 |
-| test.go:60:15:60:41 | call to UserAgent | test.go:62:19:62:27 | untrusted | provenance | Src:MaD:785 |
+| test.go:10:15:10:41 | call to UserAgent | test.go:12:11:12:19 | untrusted | provenance | Src:MaD:794 |
+| test.go:10:15:10:41 | call to UserAgent | test.go:13:23:13:31 | untrusted | provenance | Src:MaD:794 |
+| test.go:10:15:10:41 | call to UserAgent | test.go:14:14:14:22 | untrusted | provenance | Src:MaD:794 |
+| test.go:10:15:10:41 | call to UserAgent | test.go:15:26:15:34 | untrusted | provenance | Src:MaD:794 |
+| test.go:10:15:10:41 | call to UserAgent | test.go:16:12:16:20 | untrusted | provenance | Src:MaD:794 |
+| test.go:10:15:10:41 | call to UserAgent | test.go:17:24:17:32 | untrusted | provenance | Src:MaD:794 |
+| test.go:10:15:10:41 | call to UserAgent | test.go:18:15:18:23 | untrusted | provenance | Src:MaD:794 |
+| test.go:10:15:10:41 | call to UserAgent | test.go:19:27:19:35 | untrusted | provenance | Src:MaD:794 |
+| test.go:24:15:24:41 | call to UserAgent | test.go:26:12:26:20 | untrusted | provenance | Src:MaD:794 |
+| test.go:24:15:24:41 | call to UserAgent | test.go:27:10:27:18 | untrusted | provenance | Src:MaD:794 |
+| test.go:24:15:24:41 | call to UserAgent | test.go:28:15:28:23 | untrusted | provenance | Src:MaD:794 |
+| test.go:24:15:24:41 | call to UserAgent | test.go:29:14:29:22 | untrusted | provenance | Src:MaD:794 |
+| test.go:24:15:24:41 | call to UserAgent | test.go:30:15:30:23 | untrusted | provenance | Src:MaD:794 |
+| test.go:24:15:24:41 | call to UserAgent | test.go:31:8:31:16 | untrusted | provenance | Src:MaD:794 |
+| test.go:24:15:24:41 | call to UserAgent | test.go:32:11:32:19 | untrusted | provenance | Src:MaD:794 |
+| test.go:24:15:24:41 | call to UserAgent | test.go:33:9:33:17 | untrusted | provenance | Src:MaD:794 |
+| test.go:24:15:24:41 | call to UserAgent | test.go:34:8:34:16 | untrusted | provenance | Src:MaD:794 |
+| test.go:24:15:24:41 | call to UserAgent | test.go:35:8:35:16 | untrusted | provenance | Src:MaD:794 |
+| test.go:24:15:24:41 | call to UserAgent | test.go:36:13:36:21 | untrusted | provenance | Src:MaD:794 |
+| test.go:24:15:24:41 | call to UserAgent | test.go:37:13:37:21 | untrusted | provenance | Src:MaD:794 |
+| test.go:24:15:24:41 | call to UserAgent | test.go:38:12:38:20 | untrusted | provenance | Src:MaD:794 |
+| test.go:24:15:24:41 | call to UserAgent | test.go:39:12:39:20 | untrusted | provenance | Src:MaD:794 |
+| test.go:24:15:24:41 | call to UserAgent | test.go:40:9:40:17 | untrusted | provenance | Src:MaD:794 |
+| test.go:24:15:24:41 | call to UserAgent | test.go:41:12:41:20 | untrusted | provenance | Src:MaD:794 |
+| test.go:24:15:24:41 | call to UserAgent | test.go:42:16:42:24 | untrusted | provenance | Src:MaD:794 |
+| test.go:24:15:24:41 | call to UserAgent | test.go:42:27:42:35 | untrusted | provenance | Src:MaD:794 |
+| test.go:24:15:24:41 | call to UserAgent | test.go:43:12:43:20 | untrusted | provenance | Src:MaD:794 |
+| test.go:24:15:24:41 | call to UserAgent | test.go:44:14:44:22 | untrusted | provenance | Src:MaD:794 |
+| test.go:24:15:24:41 | call to UserAgent | test.go:44:25:44:33 | untrusted | provenance | Src:MaD:794 |
+| test.go:48:15:48:41 | call to UserAgent | test.go:49:12:49:20 | untrusted | provenance | Src:MaD:794 |
+| test.go:54:15:54:41 | call to UserAgent | test.go:56:31:56:39 | untrusted | provenance | Src:MaD:794 |
+| test.go:60:15:60:41 | call to UserAgent | test.go:62:19:62:27 | untrusted | provenance | Src:MaD:794 |
nodes
| test.go:10:15:10:41 | call to UserAgent | semmle.label | call to UserAgent |
| test.go:12:11:12:19 | untrusted | semmle.label | untrusted |
diff --git a/go/ql/test/library-tests/semmle/go/frameworks/Chi/ReflectedXss.expected b/go/ql/test/library-tests/semmle/go/frameworks/Chi/ReflectedXss.expected
index 3896eea7e1ba4..963d271c8b680 100644
--- a/go/ql/test/library-tests/semmle/go/frameworks/Chi/ReflectedXss.expected
+++ b/go/ql/test/library-tests/semmle/go/frameworks/Chi/ReflectedXss.expected
@@ -1,5 +1,5 @@
edges
-| test.go:13:12:13:16 | selection of URL | test.go:13:12:13:21 | selection of Path | provenance | Src:MaD:793 |
+| test.go:13:12:13:16 | selection of URL | test.go:13:12:13:21 | selection of Path | provenance | Src:MaD:802 |
| test.go:13:12:13:21 | selection of Path | test.go:21:18:21:23 | hidden | provenance | |
| test.go:21:18:21:23 | hidden | test.go:21:11:21:24 | type conversion | provenance | |
| test.go:22:18:22:45 | call to URLParam | test.go:22:11:22:46 | type conversion | provenance | Src:MaD:408 |
diff --git a/go/ql/test/library-tests/semmle/go/frameworks/Echo/OpenRedirect.expected b/go/ql/test/library-tests/semmle/go/frameworks/Echo/OpenRedirect.expected
index ac6d6af509b4c..816efce0892f7 100644
--- a/go/ql/test/library-tests/semmle/go/frameworks/Echo/OpenRedirect.expected
+++ b/go/ql/test/library-tests/semmle/go/frameworks/Echo/OpenRedirect.expected
@@ -1,10 +1,10 @@
edges
-| test.go:172:11:172:32 | call to Param | test.go:173:20:173:24 | param | provenance | Src:MaD:459 |
-| test.go:178:11:178:32 | call to Param | test.go:182:24:182:28 | param | provenance | Src:MaD:459 |
+| test.go:172:11:172:32 | call to Param | test.go:173:20:173:24 | param | provenance | Src:MaD:464 |
+| test.go:178:11:178:32 | call to Param | test.go:182:24:182:28 | param | provenance | Src:MaD:464 |
| test.go:182:24:182:28 | param | test.go:182:20:182:28 | ...+... | provenance | Config |
| test.go:190:9:190:26 | star expression | test.go:190:10:190:26 | selection of URL | provenance | Config |
| test.go:190:9:190:26 | star expression | test.go:193:21:193:23 | url | provenance | |
-| test.go:190:10:190:26 | selection of URL | test.go:190:9:190:26 | star expression | provenance | Src:MaD:793 Config |
+| test.go:190:10:190:26 | selection of URL | test.go:190:9:190:26 | star expression | provenance | Src:MaD:802 Config |
| test.go:193:21:193:23 | url | test.go:193:21:193:32 | call to String | provenance | Config |
nodes
| test.go:172:11:172:32 | call to Param | semmle.label | call to Param |
diff --git a/go/ql/test/library-tests/semmle/go/frameworks/Echo/ReflectedXss.expected b/go/ql/test/library-tests/semmle/go/frameworks/Echo/ReflectedXss.expected
index d18c24e097eee..8ada23ef521b8 100644
--- a/go/ql/test/library-tests/semmle/go/frameworks/Echo/ReflectedXss.expected
+++ b/go/ql/test/library-tests/semmle/go/frameworks/Echo/ReflectedXss.expected
@@ -1,36 +1,36 @@
edges
-| test.go:15:11:15:32 | call to Param | test.go:16:16:16:20 | param | provenance | Src:MaD:459 |
-| test.go:21:11:21:27 | call to ParamValues | test.go:22:16:22:20 | param | provenance | Src:MaD:460 |
-| test.go:27:11:27:37 | call to QueryParam | test.go:28:16:28:20 | param | provenance | Src:MaD:461 |
-| test.go:33:11:33:27 | call to QueryParams | test.go:34:16:34:20 | param | provenance | Src:MaD:462 |
-| test.go:39:10:39:26 | call to QueryString | test.go:40:16:40:19 | qstr | provenance | Src:MaD:463 |
-| test.go:45:9:45:34 | call to FormValue | test.go:46:16:46:18 | val | provenance | Src:MaD:464 |
-| test.go:51:2:51:30 | ... := ...[0] | test.go:52:16:52:37 | index expression | provenance | Src:MaD:465 |
-| test.go:57:2:57:46 | ... := ...[0] | test.go:58:13:58:22 | fileHeader | provenance | Src:MaD:466 |
+| test.go:15:11:15:32 | call to Param | test.go:16:16:16:20 | param | provenance | Src:MaD:464 |
+| test.go:21:11:21:27 | call to ParamValues | test.go:22:16:22:20 | param | provenance | Src:MaD:465 |
+| test.go:27:11:27:37 | call to QueryParam | test.go:28:16:28:20 | param | provenance | Src:MaD:466 |
+| test.go:33:11:33:27 | call to QueryParams | test.go:34:16:34:20 | param | provenance | Src:MaD:467 |
+| test.go:39:10:39:26 | call to QueryString | test.go:40:16:40:19 | qstr | provenance | Src:MaD:468 |
+| test.go:45:9:45:34 | call to FormValue | test.go:46:16:46:18 | val | provenance | Src:MaD:469 |
+| test.go:51:2:51:30 | ... := ...[0] | test.go:52:16:52:37 | index expression | provenance | Src:MaD:470 |
+| test.go:57:2:57:46 | ... := ...[0] | test.go:58:13:58:22 | fileHeader | provenance | Src:MaD:471 |
| test.go:58:2:58:29 | ... := ...[0] | test.go:60:2:60:5 | file | provenance | |
-| test.go:58:13:58:22 | fileHeader | test.go:58:2:58:29 | ... := ...[0] | provenance | MaD:738 |
+| test.go:58:13:58:22 | fileHeader | test.go:58:2:58:29 | ... := ...[0] | provenance | MaD:747 |
| test.go:59:2:59:7 | definition of buffer | test.go:61:20:61:25 | buffer | provenance | |
-| test.go:60:2:60:5 | file | test.go:59:2:59:7 | definition of buffer | provenance | MaD:664 |
-| test.go:66:2:66:31 | ... := ...[0] | test.go:67:16:67:41 | index expression | provenance | Src:MaD:467 |
-| test.go:72:2:72:31 | ... := ...[0] | test.go:74:13:74:22 | fileHeader | provenance | Src:MaD:467 |
+| test.go:60:2:60:5 | file | test.go:59:2:59:7 | definition of buffer | provenance | MaD:673 |
+| test.go:66:2:66:31 | ... := ...[0] | test.go:67:16:67:41 | index expression | provenance | Src:MaD:472 |
+| test.go:72:2:72:31 | ... := ...[0] | test.go:74:13:74:22 | fileHeader | provenance | Src:MaD:472 |
| test.go:74:2:74:29 | ... := ...[0] | test.go:76:2:76:5 | file | provenance | |
-| test.go:74:13:74:22 | fileHeader | test.go:74:2:74:29 | ... := ...[0] | provenance | MaD:738 |
+| test.go:74:13:74:22 | fileHeader | test.go:74:2:74:29 | ... := ...[0] | provenance | MaD:747 |
| test.go:75:2:75:7 | definition of buffer | test.go:77:20:77:25 | buffer | provenance | |
-| test.go:76:2:76:5 | file | test.go:75:2:75:7 | definition of buffer | provenance | MaD:664 |
-| test.go:82:2:82:32 | ... := ...[0] | test.go:83:16:83:24 | selection of Value | provenance | Src:MaD:468 |
-| test.go:88:13:88:25 | call to Cookies | test.go:89:16:89:31 | selection of Value | provenance | Src:MaD:469 |
-| test.go:99:11:99:15 | &... | test.go:100:16:100:21 | selection of s | provenance | Src:MaD:458 |
+| test.go:76:2:76:5 | file | test.go:75:2:75:7 | definition of buffer | provenance | MaD:673 |
+| test.go:82:2:82:32 | ... := ...[0] | test.go:83:16:83:24 | selection of Value | provenance | Src:MaD:473 |
+| test.go:88:13:88:25 | call to Cookies | test.go:89:16:89:31 | selection of Value | provenance | Src:MaD:474 |
+| test.go:99:11:99:15 | &... | test.go:100:16:100:21 | selection of s | provenance | Src:MaD:463 |
| test.go:112:17:112:19 | definition of ctx | test.go:114:16:114:18 | ctx | provenance | |
-| test.go:113:21:113:42 | call to Param | test.go:112:17:112:19 | definition of ctx | provenance | Src:MaD:459 MaD:457 |
-| test.go:114:16:114:18 | ctx | test.go:114:16:114:33 | call to Get | provenance | MaD:456 |
+| test.go:113:21:113:42 | call to Param | test.go:112:17:112:19 | definition of ctx | provenance | Src:MaD:464 MaD:462 |
+| test.go:114:16:114:18 | ctx | test.go:114:16:114:33 | call to Get | provenance | MaD:461 |
| test.go:114:16:114:33 | call to Get | test.go:114:16:114:42 | type assertion | provenance | |
-| test.go:124:11:124:32 | call to Param | test.go:125:16:125:20 | param | provenance | Src:MaD:459 |
-| test.go:130:11:130:32 | call to Param | test.go:131:20:131:32 | type conversion | provenance | Src:MaD:459 |
-| test.go:136:11:136:32 | call to Param | test.go:137:29:137:41 | type conversion | provenance | Src:MaD:459 |
-| test.go:148:11:148:32 | call to Param | test.go:149:30:149:34 | param | provenance | Src:MaD:459 |
+| test.go:124:11:124:32 | call to Param | test.go:125:16:125:20 | param | provenance | Src:MaD:464 |
+| test.go:130:11:130:32 | call to Param | test.go:131:20:131:32 | type conversion | provenance | Src:MaD:464 |
+| test.go:136:11:136:32 | call to Param | test.go:137:29:137:41 | type conversion | provenance | Src:MaD:464 |
+| test.go:148:11:148:32 | call to Param | test.go:149:30:149:34 | param | provenance | Src:MaD:464 |
| test.go:149:12:149:35 | call to NewReader | test.go:150:31:150:36 | reader | provenance | |
-| test.go:149:30:149:34 | param | test.go:149:12:149:35 | call to NewReader | provenance | MaD:955 |
-| test.go:164:11:164:32 | call to Param | test.go:165:23:165:35 | type conversion | provenance | Src:MaD:459 |
+| test.go:149:30:149:34 | param | test.go:149:12:149:35 | call to NewReader | provenance | MaD:966 |
+| test.go:164:11:164:32 | call to Param | test.go:165:23:165:35 | type conversion | provenance | Src:MaD:464 |
nodes
| test.go:15:11:15:32 | call to Param | semmle.label | call to Param |
| test.go:16:16:16:20 | param | semmle.label | param |
diff --git a/go/ql/test/library-tests/semmle/go/frameworks/Echo/TaintedPath.expected b/go/ql/test/library-tests/semmle/go/frameworks/Echo/TaintedPath.expected
index 4985c7091fc2c..31ee545b275cc 100644
--- a/go/ql/test/library-tests/semmle/go/frameworks/Echo/TaintedPath.expected
+++ b/go/ql/test/library-tests/semmle/go/frameworks/Echo/TaintedPath.expected
@@ -1,6 +1,6 @@
edges
-| test.go:221:15:221:38 | call to QueryParam | test.go:222:17:222:24 | filepath | provenance | Src:MaD:461 |
-| test.go:225:15:225:38 | call to QueryParam | test.go:226:23:226:30 | filepath | provenance | Src:MaD:461 |
+| test.go:221:15:221:38 | call to QueryParam | test.go:222:17:222:24 | filepath | provenance | Src:MaD:466 |
+| test.go:225:15:225:38 | call to QueryParam | test.go:226:23:226:30 | filepath | provenance | Src:MaD:466 |
nodes
| test.go:221:15:221:38 | call to QueryParam | semmle.label | call to QueryParam |
| test.go:222:17:222:24 | filepath | semmle.label | filepath |
diff --git a/go/ql/test/library-tests/semmle/go/frameworks/Encoding/jsoniter.expected b/go/ql/test/library-tests/semmle/go/frameworks/Encoding/jsoniter.expected
index 7714ebdc504c1..39c52eb45303d 100644
--- a/go/ql/test/library-tests/semmle/go/frameworks/Encoding/jsoniter.expected
+++ b/go/ql/test/library-tests/semmle/go/frameworks/Encoding/jsoniter.expected
@@ -4,13 +4,13 @@ edges
| jsoniter.go:23:20:23:38 | call to getUntrustedBytes | jsoniter.go:31:21:31:34 | untrustedInput | provenance | |
| jsoniter.go:24:21:24:40 | call to getUntrustedString | jsoniter.go:35:27:35:41 | untrustedString | provenance | |
| jsoniter.go:24:21:24:40 | call to getUntrustedString | jsoniter.go:39:31:39:45 | untrustedString | provenance | |
-| jsoniter.go:27:17:27:30 | untrustedInput | jsoniter.go:27:33:27:37 | &... | provenance | MaD:448 |
+| jsoniter.go:27:17:27:30 | untrustedInput | jsoniter.go:27:33:27:37 | &... | provenance | MaD:453 |
| jsoniter.go:27:33:27:37 | &... | jsoniter.go:28:15:28:24 | selection of field | provenance | |
-| jsoniter.go:31:21:31:34 | untrustedInput | jsoniter.go:31:37:31:42 | &... | provenance | MaD:446 |
+| jsoniter.go:31:21:31:34 | untrustedInput | jsoniter.go:31:37:31:42 | &... | provenance | MaD:451 |
| jsoniter.go:31:37:31:42 | &... | jsoniter.go:32:15:32:25 | selection of field | provenance | |
-| jsoniter.go:35:27:35:41 | untrustedString | jsoniter.go:35:44:35:49 | &... | provenance | MaD:449 |
+| jsoniter.go:35:27:35:41 | untrustedString | jsoniter.go:35:44:35:49 | &... | provenance | MaD:454 |
| jsoniter.go:35:44:35:49 | &... | jsoniter.go:36:15:36:25 | selection of field | provenance | |
-| jsoniter.go:39:31:39:45 | untrustedString | jsoniter.go:39:48:39:53 | &... | provenance | MaD:447 |
+| jsoniter.go:39:31:39:45 | untrustedString | jsoniter.go:39:48:39:53 | &... | provenance | MaD:452 |
| jsoniter.go:39:48:39:53 | &... | jsoniter.go:40:15:40:25 | selection of field | provenance | |
nodes
| jsoniter.go:23:20:23:38 | call to getUntrustedBytes | semmle.label | call to getUntrustedBytes |
diff --git a/go/ql/test/library-tests/semmle/go/frameworks/Revel/OpenRedirect.expected b/go/ql/test/library-tests/semmle/go/frameworks/Revel/OpenRedirect.expected
index 0b475b751e5ce..bc8d19ba666dd 100644
--- a/go/ql/test/library-tests/semmle/go/frameworks/Revel/OpenRedirect.expected
+++ b/go/ql/test/library-tests/semmle/go/frameworks/Revel/OpenRedirect.expected
@@ -1,8 +1,8 @@
edges
| EndToEnd.go:94:20:94:27 | implicit dereference | EndToEnd.go:94:20:94:27 | selection of Params | provenance | Config |
| EndToEnd.go:94:20:94:27 | implicit dereference | EndToEnd.go:94:20:94:32 | selection of Form | provenance | Config |
-| EndToEnd.go:94:20:94:27 | selection of Params | EndToEnd.go:94:20:94:27 | implicit dereference | provenance | Src:MaD:477 Config |
-| EndToEnd.go:94:20:94:27 | selection of Params | EndToEnd.go:94:20:94:32 | selection of Form | provenance | Src:MaD:477 Config |
+| EndToEnd.go:94:20:94:27 | selection of Params | EndToEnd.go:94:20:94:27 | implicit dereference | provenance | Src:MaD:482 Config |
+| EndToEnd.go:94:20:94:27 | selection of Params | EndToEnd.go:94:20:94:32 | selection of Form | provenance | Src:MaD:482 Config |
| EndToEnd.go:94:20:94:32 | selection of Form | EndToEnd.go:94:20:94:49 | call to Get | provenance | Config |
nodes
| EndToEnd.go:94:20:94:27 | implicit dereference | semmle.label | implicit dereference |
diff --git a/go/ql/test/library-tests/semmle/go/frameworks/Revel/ReflectedXss.expected b/go/ql/test/library-tests/semmle/go/frameworks/Revel/ReflectedXss.expected
index 7d99bcd75e8f6..3d58541bee200 100644
--- a/go/ql/test/library-tests/semmle/go/frameworks/Revel/ReflectedXss.expected
+++ b/go/ql/test/library-tests/semmle/go/frameworks/Revel/ReflectedXss.expected
@@ -1,13 +1,13 @@
edges
| EndToEnd.go:35:2:35:4 | definition of buf | EndToEnd.go:37:24:37:26 | buf | provenance | |
-| EndToEnd.go:36:18:36:25 | selection of Params | EndToEnd.go:36:18:36:30 | selection of Form | provenance | Src:MaD:477 |
-| EndToEnd.go:36:18:36:30 | selection of Form | EndToEnd.go:36:18:36:47 | call to Get | provenance | MaD:861 |
-| EndToEnd.go:36:18:36:47 | call to Get | EndToEnd.go:35:2:35:4 | definition of buf | provenance | MaD:667 |
-| EndToEnd.go:69:22:69:29 | selection of Params | EndToEnd.go:69:22:69:34 | selection of Form | provenance | Src:MaD:477 |
-| EndToEnd.go:69:22:69:34 | selection of Form | EndToEnd.go:69:22:69:51 | call to Get | provenance | MaD:861 |
-| Revel.go:70:22:70:29 | selection of Params | Revel.go:70:22:70:35 | selection of Query | provenance | Src:MaD:477 |
-| examples/booking/app/init.go:36:44:36:48 | selection of URL | examples/booking/app/init.go:36:44:36:53 | selection of Path | provenance | Src:MaD:793 |
-| examples/booking/app/init.go:40:49:40:53 | selection of URL | examples/booking/app/init.go:40:49:40:58 | selection of Path | provenance | Src:MaD:793 |
+| EndToEnd.go:36:18:36:25 | selection of Params | EndToEnd.go:36:18:36:30 | selection of Form | provenance | Src:MaD:482 |
+| EndToEnd.go:36:18:36:30 | selection of Form | EndToEnd.go:36:18:36:47 | call to Get | provenance | MaD:870 |
+| EndToEnd.go:36:18:36:47 | call to Get | EndToEnd.go:35:2:35:4 | definition of buf | provenance | MaD:676 |
+| EndToEnd.go:69:22:69:29 | selection of Params | EndToEnd.go:69:22:69:34 | selection of Form | provenance | Src:MaD:482 |
+| EndToEnd.go:69:22:69:34 | selection of Form | EndToEnd.go:69:22:69:51 | call to Get | provenance | MaD:870 |
+| Revel.go:70:22:70:29 | selection of Params | Revel.go:70:22:70:35 | selection of Query | provenance | Src:MaD:482 |
+| examples/booking/app/init.go:36:44:36:48 | selection of URL | examples/booking/app/init.go:36:44:36:53 | selection of Path | provenance | Src:MaD:802 |
+| examples/booking/app/init.go:40:49:40:53 | selection of URL | examples/booking/app/init.go:40:49:40:58 | selection of Path | provenance | Src:MaD:802 |
nodes
| EndToEnd.go:35:2:35:4 | definition of buf | semmle.label | definition of buf |
| EndToEnd.go:36:18:36:25 | selection of Params | semmle.label | selection of Params |
diff --git a/go/ql/test/library-tests/semmle/go/frameworks/Revel/TaintedPath.expected b/go/ql/test/library-tests/semmle/go/frameworks/Revel/TaintedPath.expected
index 48d5657b50846..d5ca939601553 100644
--- a/go/ql/test/library-tests/semmle/go/frameworks/Revel/TaintedPath.expected
+++ b/go/ql/test/library-tests/semmle/go/frameworks/Revel/TaintedPath.expected
@@ -1,8 +1,8 @@
edges
-| EndToEnd.go:58:18:58:25 | selection of Params | EndToEnd.go:58:18:58:30 | selection of Form | provenance | Src:MaD:477 |
-| EndToEnd.go:58:18:58:30 | selection of Form | EndToEnd.go:58:18:58:47 | call to Get | provenance | MaD:861 |
-| EndToEnd.go:64:26:64:33 | selection of Params | EndToEnd.go:64:26:64:38 | selection of Form | provenance | Src:MaD:477 |
-| EndToEnd.go:64:26:64:38 | selection of Form | EndToEnd.go:64:26:64:55 | call to Get | provenance | MaD:861 |
+| EndToEnd.go:58:18:58:25 | selection of Params | EndToEnd.go:58:18:58:30 | selection of Form | provenance | Src:MaD:482 |
+| EndToEnd.go:58:18:58:30 | selection of Form | EndToEnd.go:58:18:58:47 | call to Get | provenance | MaD:870 |
+| EndToEnd.go:64:26:64:33 | selection of Params | EndToEnd.go:64:26:64:38 | selection of Form | provenance | Src:MaD:482 |
+| EndToEnd.go:64:26:64:38 | selection of Form | EndToEnd.go:64:26:64:55 | call to Get | provenance | MaD:870 |
nodes
| EndToEnd.go:58:18:58:25 | selection of Params | semmle.label | selection of Params |
| EndToEnd.go:58:18:58:30 | selection of Form | semmle.label | selection of Form |
diff --git a/go/ql/test/library-tests/semmle/go/frameworks/Twirp/RequestForgery.expected b/go/ql/test/library-tests/semmle/go/frameworks/Twirp/RequestForgery.expected
index 1fe7b8c72364f..4b0749e3224ba 100644
--- a/go/ql/test/library-tests/semmle/go/frameworks/Twirp/RequestForgery.expected
+++ b/go/ql/test/library-tests/semmle/go/frameworks/Twirp/RequestForgery.expected
@@ -6,9 +6,9 @@ edges
| rpc/notes/service.twirp.go:493:2:493:2 | capture variable reqContent | rpc/notes/service.twirp.go:495:35:495:44 | reqContent | provenance | |
| rpc/notes/service.twirp.go:495:35:495:44 | reqContent | server/main.go:19:56:19:61 | definition of params | provenance | |
| rpc/notes/service.twirp.go:538:2:538:33 | ... := ...[0] | rpc/notes/service.twirp.go:544:27:544:29 | buf | provenance | |
-| rpc/notes/service.twirp.go:538:25:538:32 | selection of Body | rpc/notes/service.twirp.go:538:2:538:33 | ... := ...[0] | provenance | Src:MaD:786 MaD:658 |
+| rpc/notes/service.twirp.go:538:25:538:32 | selection of Body | rpc/notes/service.twirp.go:538:2:538:33 | ... := ...[0] | provenance | Src:MaD:795 MaD:667 |
| rpc/notes/service.twirp.go:543:2:543:11 | definition of reqContent | rpc/notes/service.twirp.go:574:2:574:2 | capture variable reqContent | provenance | |
-| rpc/notes/service.twirp.go:544:27:544:29 | buf | rpc/notes/service.twirp.go:543:2:543:11 | definition of reqContent | provenance | MaD:602 |
+| rpc/notes/service.twirp.go:544:27:544:29 | buf | rpc/notes/service.twirp.go:543:2:543:11 | definition of reqContent | provenance | MaD:611 |
| rpc/notes/service.twirp.go:554:6:554:13 | definition of typedReq | rpc/notes/service.twirp.go:558:44:558:51 | typedReq | provenance | |
| rpc/notes/service.twirp.go:558:44:558:51 | typedReq | server/main.go:19:56:19:61 | definition of params | provenance | |
| rpc/notes/service.twirp.go:574:2:574:2 | capture variable reqContent | rpc/notes/service.twirp.go:576:35:576:44 | reqContent | provenance | |
diff --git a/go/ql/test/library-tests/semmle/go/frameworks/XNetHtml/ReflectedXss.expected b/go/ql/test/library-tests/semmle/go/frameworks/XNetHtml/ReflectedXss.expected
index 9c38dc406ea60..c74109cd3a0e8 100644
--- a/go/ql/test/library-tests/semmle/go/frameworks/XNetHtml/ReflectedXss.expected
+++ b/go/ql/test/library-tests/semmle/go/frameworks/XNetHtml/ReflectedXss.expected
@@ -1,40 +1,40 @@
edges
-| test.go:12:12:12:22 | selection of URL | test.go:12:12:12:30 | call to Query | provenance | Src:MaD:793 MaD:854 |
-| test.go:12:12:12:30 | call to Query | test.go:12:12:12:44 | call to Get | provenance | MaD:861 |
+| test.go:12:12:12:22 | selection of URL | test.go:12:12:12:30 | call to Query | provenance | Src:MaD:802 MaD:863 |
+| test.go:12:12:12:30 | call to Query | test.go:12:12:12:44 | call to Get | provenance | MaD:870 |
| test.go:12:12:12:44 | call to Get | test.go:15:42:15:47 | param1 | provenance | |
| test.go:15:22:15:48 | call to UnescapeString | test.go:15:15:15:49 | type conversion | provenance | |
-| test.go:15:42:15:47 | param1 | test.go:15:22:15:48 | call to UnescapeString | provenance | MaD:588 |
+| test.go:15:42:15:47 | param1 | test.go:15:22:15:48 | call to UnescapeString | provenance | MaD:595 |
| test.go:17:2:17:36 | ... := ...[0] | test.go:18:15:18:31 | type conversion | provenance | |
| test.go:17:2:17:36 | ... := ...[0] | test.go:29:22:29:25 | node | provenance | |
-| test.go:17:24:17:35 | selection of Body | test.go:17:2:17:36 | ... := ...[0] | provenance | Src:MaD:786 MaD:583 |
+| test.go:17:24:17:35 | selection of Body | test.go:17:2:17:36 | ... := ...[0] | provenance | Src:MaD:795 MaD:590 |
| test.go:20:2:20:48 | ... := ...[0] | test.go:21:15:21:32 | type conversion | provenance | |
-| test.go:20:36:20:47 | selection of Body | test.go:20:2:20:48 | ... := ...[0] | provenance | Src:MaD:786 MaD:586 |
+| test.go:20:36:20:47 | selection of Body | test.go:20:2:20:48 | ... := ...[0] | provenance | Src:MaD:795 MaD:593 |
| test.go:23:2:23:50 | ... := ...[0] | test.go:24:15:24:35 | type conversion | provenance | |
-| test.go:23:33:23:44 | selection of Body | test.go:23:2:23:50 | ... := ...[0] | provenance | Src:MaD:786 MaD:584 |
+| test.go:23:33:23:44 | selection of Body | test.go:23:2:23:50 | ... := ...[0] | provenance | Src:MaD:795 MaD:591 |
| test.go:26:2:26:62 | ... := ...[0] | test.go:27:15:27:36 | type conversion | provenance | |
-| test.go:26:45:26:56 | selection of Body | test.go:26:2:26:62 | ... := ...[0] | provenance | Src:MaD:786 MaD:585 |
+| test.go:26:45:26:56 | selection of Body | test.go:26:2:26:62 | ... := ...[0] | provenance | Src:MaD:795 MaD:592 |
| test.go:31:15:31:45 | call to NewTokenizer | test.go:32:15:32:23 | tokenizer | provenance | |
| test.go:31:15:31:45 | call to NewTokenizer | test.go:33:15:33:23 | tokenizer | provenance | |
| test.go:31:15:31:45 | call to NewTokenizer | test.go:34:17:34:25 | tokenizer | provenance | |
| test.go:31:15:31:45 | call to NewTokenizer | test.go:36:15:36:23 | tokenizer | provenance | |
| test.go:31:15:31:45 | call to NewTokenizer | test.go:37:22:37:30 | tokenizer | provenance | |
-| test.go:31:33:31:44 | selection of Body | test.go:31:15:31:45 | call to NewTokenizer | provenance | Src:MaD:786 MaD:581 |
-| test.go:32:15:32:23 | tokenizer | test.go:32:15:32:34 | call to Buffered | provenance | MaD:591 |
-| test.go:33:15:33:23 | tokenizer | test.go:33:15:33:29 | call to Raw | provenance | MaD:592 |
+| test.go:31:33:31:44 | selection of Body | test.go:31:15:31:45 | call to NewTokenizer | provenance | Src:MaD:795 MaD:588 |
+| test.go:32:15:32:23 | tokenizer | test.go:32:15:32:34 | call to Buffered | provenance | MaD:598 |
+| test.go:33:15:33:23 | tokenizer | test.go:33:15:33:29 | call to Raw | provenance | MaD:599 |
| test.go:34:2:34:35 | ... := ...[1] | test.go:35:15:35:19 | value | provenance | |
-| test.go:34:17:34:25 | tokenizer | test.go:34:2:34:35 | ... := ...[1] | provenance | MaD:593 |
-| test.go:36:15:36:23 | tokenizer | test.go:36:15:36:30 | call to Text | provenance | MaD:594 |
-| test.go:37:22:37:30 | tokenizer | test.go:37:22:37:38 | call to Token | provenance | MaD:595 |
+| test.go:34:17:34:25 | tokenizer | test.go:34:2:34:35 | ... := ...[1] | provenance | MaD:600 |
+| test.go:36:15:36:23 | tokenizer | test.go:36:15:36:30 | call to Text | provenance | MaD:601 |
+| test.go:37:22:37:30 | tokenizer | test.go:37:22:37:38 | call to Token | provenance | MaD:602 |
| test.go:37:22:37:38 | call to Token | test.go:37:15:37:44 | type conversion | provenance | |
| test.go:39:23:39:77 | call to NewTokenizerFragment | test.go:40:15:40:31 | tokenizerFragment | provenance | |
-| test.go:39:49:39:60 | selection of Body | test.go:39:23:39:77 | call to NewTokenizerFragment | provenance | Src:MaD:786 MaD:582 |
-| test.go:40:15:40:31 | tokenizerFragment | test.go:40:15:40:42 | call to Buffered | provenance | MaD:591 |
+| test.go:39:49:39:60 | selection of Body | test.go:39:23:39:77 | call to NewTokenizerFragment | provenance | Src:MaD:795 MaD:589 |
+| test.go:40:15:40:31 | tokenizerFragment | test.go:40:15:40:42 | call to Buffered | provenance | MaD:598 |
| test.go:42:6:42:14 | definition of cleanNode | test.go:45:22:45:31 | &... | provenance | |
| test.go:42:6:42:14 | definition of cleanNode | test.go:45:22:45:31 | &... | provenance | |
| test.go:42:6:42:14 | definition of cleanNode | test.go:45:23:45:31 | cleanNode | provenance | |
| test.go:43:2:43:43 | ... := ...[0] | test.go:44:24:44:34 | taintedNode | provenance | |
-| test.go:43:31:43:42 | selection of Body | test.go:43:2:43:43 | ... := ...[0] | provenance | Src:MaD:786 MaD:583 |
-| test.go:44:24:44:34 | taintedNode | test.go:42:6:42:14 | definition of cleanNode | provenance | MaD:589 |
+| test.go:43:31:43:42 | selection of Body | test.go:43:2:43:43 | ... := ...[0] | provenance | Src:MaD:795 MaD:590 |
+| test.go:44:24:44:34 | taintedNode | test.go:42:6:42:14 | definition of cleanNode | provenance | MaD:596 |
| test.go:45:22:45:31 | &... | test.go:45:22:45:31 | &... | provenance | |
| test.go:45:22:45:31 | &... | test.go:45:22:45:31 | &... | provenance | |
| test.go:45:22:45:31 | &... | test.go:45:23:45:31 | cleanNode | provenance | |
@@ -46,8 +46,8 @@ edges
| test.go:47:6:47:15 | definition of cleanNode2 | test.go:50:22:50:32 | &... | provenance | |
| test.go:47:6:47:15 | definition of cleanNode2 | test.go:50:23:50:32 | cleanNode2 | provenance | |
| test.go:48:2:48:44 | ... := ...[0] | test.go:49:26:49:37 | taintedNode2 | provenance | |
-| test.go:48:32:48:43 | selection of Body | test.go:48:2:48:44 | ... := ...[0] | provenance | Src:MaD:786 MaD:583 |
-| test.go:49:26:49:37 | taintedNode2 | test.go:47:6:47:15 | definition of cleanNode2 | provenance | MaD:590 |
+| test.go:48:32:48:43 | selection of Body | test.go:48:2:48:44 | ... := ...[0] | provenance | Src:MaD:795 MaD:590 |
+| test.go:49:26:49:37 | taintedNode2 | test.go:47:6:47:15 | definition of cleanNode2 | provenance | MaD:597 |
| test.go:50:22:50:32 | &... | test.go:50:22:50:32 | &... | provenance | |
| test.go:50:22:50:32 | &... | test.go:50:22:50:32 | &... | provenance | |
| test.go:50:22:50:32 | &... | test.go:50:23:50:32 | cleanNode2 | provenance | |
diff --git a/go/ql/test/library-tests/semmle/go/frameworks/XNetHtml/SqlInjection.expected b/go/ql/test/library-tests/semmle/go/frameworks/XNetHtml/SqlInjection.expected
index a2ada58cd218b..d68255c95813f 100644
--- a/go/ql/test/library-tests/semmle/go/frameworks/XNetHtml/SqlInjection.expected
+++ b/go/ql/test/library-tests/semmle/go/frameworks/XNetHtml/SqlInjection.expected
@@ -1,6 +1,6 @@
edges
-| test.go:56:2:56:42 | ... := ...[0] | test.go:57:29:57:40 | selection of Value | provenance | Src:MaD:778 |
-| test.go:57:29:57:40 | selection of Value | test.go:57:11:57:41 | call to EscapeString | provenance | MaD:580 |
+| test.go:56:2:56:42 | ... := ...[0] | test.go:57:29:57:40 | selection of Value | provenance | Src:MaD:787 |
+| test.go:57:29:57:40 | selection of Value | test.go:57:11:57:41 | call to EscapeString | provenance | MaD:587 |
nodes
| test.go:56:2:56:42 | ... := ...[0] | semmle.label | ... := ...[0] |
| test.go:57:11:57:41 | call to EscapeString | semmle.label | call to EscapeString |
diff --git a/go/ql/test/query-tests/Security/CWE-022/ZipSlip.expected b/go/ql/test/query-tests/Security/CWE-022/ZipSlip.expected
index 7b7c103a70931..8ecda9edce7dd 100644
--- a/go/ql/test/query-tests/Security/CWE-022/ZipSlip.expected
+++ b/go/ql/test/query-tests/Security/CWE-022/ZipSlip.expected
@@ -7,9 +7,9 @@ edges
| UnsafeUnzipSymlinkGood.go:76:70:76:80 | selection of Name | UnsafeUnzipSymlinkGood.go:52:24:52:32 | definition of candidate | provenance | |
| ZipSlip.go:11:2:15:2 | range statement[1] | ZipSlip.go:12:24:12:29 | selection of Name | provenance | |
| ZipSlip.go:12:3:12:30 | ... := ...[0] | ZipSlip.go:14:20:14:20 | p | provenance | |
-| ZipSlip.go:12:24:12:29 | selection of Name | ZipSlip.go:12:3:12:30 | ... := ...[0] | provenance | MaD:866 |
+| ZipSlip.go:12:24:12:29 | selection of Name | ZipSlip.go:12:3:12:30 | ... := ...[0] | provenance | MaD:877 |
| tarslip.go:15:2:15:30 | ... := ...[0] | tarslip.go:16:23:16:33 | selection of Name | provenance | |
-| tarslip.go:16:23:16:33 | selection of Name | tarslip.go:16:14:16:34 | call to Dir | provenance | MaD:881 |
+| tarslip.go:16:23:16:33 | selection of Name | tarslip.go:16:14:16:34 | call to Dir | provenance | MaD:892 |
| tst.go:23:2:43:2 | range statement[1] | tst.go:29:20:29:23 | path | provenance | |
nodes
| UnsafeUnzipSymlinkGood.go:52:24:52:32 | definition of candidate | semmle.label | definition of candidate |
diff --git a/go/ql/test/query-tests/Security/CWE-078/CommandInjection.expected b/go/ql/test/query-tests/Security/CWE-078/CommandInjection.expected
index 01139ee6e31a0..0071cfbdddd77 100644
--- a/go/ql/test/query-tests/Security/CWE-078/CommandInjection.expected
+++ b/go/ql/test/query-tests/Security/CWE-078/CommandInjection.expected
@@ -1,27 +1,27 @@
edges
-| ArgumentInjection.go:9:10:9:16 | selection of URL | ArgumentInjection.go:9:10:9:24 | call to Query | provenance | Src:MaD:793 MaD:854 |
+| ArgumentInjection.go:9:10:9:16 | selection of URL | ArgumentInjection.go:9:10:9:24 | call to Query | provenance | Src:MaD:802 MaD:863 |
| ArgumentInjection.go:9:10:9:24 | call to Query | ArgumentInjection.go:10:31:10:34 | path | provenance | |
-| CommandInjection2.go:13:15:13:21 | selection of URL | CommandInjection2.go:13:15:13:29 | call to Query | provenance | Src:MaD:793 MaD:854 |
+| CommandInjection2.go:13:15:13:21 | selection of URL | CommandInjection2.go:13:15:13:29 | call to Query | provenance | Src:MaD:802 MaD:863 |
| CommandInjection2.go:13:15:13:29 | call to Query | CommandInjection2.go:15:67:15:75 | imageName | provenance | |
| CommandInjection2.go:15:34:15:88 | []type{args} [array] | CommandInjection2.go:15:34:15:88 | call to Sprintf | provenance | MaD:248 |
| CommandInjection2.go:15:67:15:75 | imageName | CommandInjection2.go:15:34:15:88 | []type{args} [array] | provenance | |
| CommandInjection2.go:15:67:15:75 | imageName | CommandInjection2.go:15:34:15:88 | call to Sprintf | provenance | FunctionModel |
-| CommandInjection2.go:41:15:41:21 | selection of URL | CommandInjection2.go:41:15:41:29 | call to Query | provenance | Src:MaD:793 MaD:854 |
+| CommandInjection2.go:41:15:41:21 | selection of URL | CommandInjection2.go:41:15:41:29 | call to Query | provenance | Src:MaD:802 MaD:863 |
| CommandInjection2.go:41:15:41:29 | call to Query | CommandInjection2.go:44:67:44:75 | imageName | provenance | |
| CommandInjection2.go:44:34:44:88 | []type{args} [array] | CommandInjection2.go:44:34:44:88 | call to Sprintf | provenance | MaD:248 |
| CommandInjection2.go:44:67:44:75 | imageName | CommandInjection2.go:44:34:44:88 | []type{args} [array] | provenance | |
| CommandInjection2.go:44:67:44:75 | imageName | CommandInjection2.go:44:34:44:88 | call to Sprintf | provenance | FunctionModel |
-| CommandInjection.go:9:13:9:19 | selection of URL | CommandInjection.go:9:13:9:27 | call to Query | provenance | Src:MaD:793 MaD:854 |
+| CommandInjection.go:9:13:9:19 | selection of URL | CommandInjection.go:9:13:9:27 | call to Query | provenance | Src:MaD:802 MaD:863 |
| CommandInjection.go:9:13:9:27 | call to Query | CommandInjection.go:10:22:10:28 | cmdName | provenance | |
-| GitSubcommands.go:11:13:11:19 | selection of URL | GitSubcommands.go:11:13:11:27 | call to Query | provenance | Src:MaD:793 MaD:854 |
+| GitSubcommands.go:11:13:11:19 | selection of URL | GitSubcommands.go:11:13:11:27 | call to Query | provenance | Src:MaD:802 MaD:863 |
| GitSubcommands.go:11:13:11:27 | call to Query | GitSubcommands.go:13:31:13:37 | tainted | provenance | |
| GitSubcommands.go:11:13:11:27 | call to Query | GitSubcommands.go:14:31:14:37 | tainted | provenance | |
| GitSubcommands.go:11:13:11:27 | call to Query | GitSubcommands.go:15:30:15:36 | tainted | provenance | |
| GitSubcommands.go:11:13:11:27 | call to Query | GitSubcommands.go:16:35:16:41 | tainted | provenance | |
| GitSubcommands.go:11:13:11:27 | call to Query | GitSubcommands.go:17:36:17:42 | tainted | provenance | |
-| GitSubcommands.go:33:13:33:19 | selection of URL | GitSubcommands.go:33:13:33:27 | call to Query | provenance | Src:MaD:793 MaD:854 |
+| GitSubcommands.go:33:13:33:19 | selection of URL | GitSubcommands.go:33:13:33:27 | call to Query | provenance | Src:MaD:802 MaD:863 |
| GitSubcommands.go:33:13:33:27 | call to Query | GitSubcommands.go:38:32:38:38 | tainted | provenance | |
-| SanitizingDoubleDash.go:9:13:9:19 | selection of URL | SanitizingDoubleDash.go:9:13:9:27 | call to Query | provenance | Src:MaD:793 MaD:854 |
+| SanitizingDoubleDash.go:9:13:9:19 | selection of URL | SanitizingDoubleDash.go:9:13:9:27 | call to Query | provenance | Src:MaD:802 MaD:863 |
| SanitizingDoubleDash.go:9:13:9:27 | call to Query | SanitizingDoubleDash.go:13:25:13:31 | tainted | provenance | |
| SanitizingDoubleDash.go:9:13:9:27 | call to Query | SanitizingDoubleDash.go:14:23:14:33 | slice expression | provenance | |
| SanitizingDoubleDash.go:9:13:9:27 | call to Query | SanitizingDoubleDash.go:39:31:39:37 | tainted | provenance | |
@@ -56,7 +56,7 @@ edges
| SanitizingDoubleDash.go:69:21:69:28 | arrayLit | SanitizingDoubleDash.go:69:14:69:35 | call to append | provenance | MaD:28 |
| SanitizingDoubleDash.go:69:21:69:28 | arrayLit [array] | SanitizingDoubleDash.go:69:14:69:35 | call to append | provenance | MaD:29 |
| SanitizingDoubleDash.go:69:21:69:28 | arrayLit [array] | SanitizingDoubleDash.go:69:14:69:35 | call to append [array] | provenance | MaD:29 |
-| SanitizingDoubleDash.go:92:13:92:19 | selection of URL | SanitizingDoubleDash.go:92:13:92:27 | call to Query | provenance | Src:MaD:793 MaD:854 |
+| SanitizingDoubleDash.go:92:13:92:19 | selection of URL | SanitizingDoubleDash.go:92:13:92:27 | call to Query | provenance | Src:MaD:802 MaD:863 |
| SanitizingDoubleDash.go:92:13:92:27 | call to Query | SanitizingDoubleDash.go:95:25:95:31 | tainted | provenance | |
| SanitizingDoubleDash.go:92:13:92:27 | call to Query | SanitizingDoubleDash.go:96:24:96:34 | slice expression | provenance | |
| SanitizingDoubleDash.go:92:13:92:27 | call to Query | SanitizingDoubleDash.go:100:31:100:37 | tainted | provenance | |
diff --git a/go/ql/test/query-tests/Security/CWE-079/ReflectedXss.expected b/go/ql/test/query-tests/Security/CWE-079/ReflectedXss.expected
index 192709186ae18..a8e50184fb052 100644
--- a/go/ql/test/query-tests/Security/CWE-079/ReflectedXss.expected
+++ b/go/ql/test/query-tests/Security/CWE-079/ReflectedXss.expected
@@ -1,18 +1,18 @@
edges
-| ReflectedXss.go:11:15:11:20 | selection of Form | ReflectedXss.go:11:15:11:36 | call to Get | provenance | Src:MaD:788 MaD:861 |
+| ReflectedXss.go:11:15:11:20 | selection of Form | ReflectedXss.go:11:15:11:36 | call to Get | provenance | Src:MaD:797 MaD:870 |
| ReflectedXss.go:11:15:11:36 | call to Get | ReflectedXss.go:14:44:14:51 | username | provenance | |
-| contenttype.go:11:11:11:16 | selection of Form | contenttype.go:11:11:11:28 | call to Get | provenance | Src:MaD:788 MaD:861 |
+| contenttype.go:11:11:11:16 | selection of Form | contenttype.go:11:11:11:28 | call to Get | provenance | Src:MaD:797 MaD:870 |
| contenttype.go:11:11:11:28 | call to Get | contenttype.go:17:11:17:22 | type conversion | provenance | |
-| contenttype.go:49:11:49:16 | selection of Form | contenttype.go:49:11:49:28 | call to Get | provenance | Src:MaD:788 MaD:861 |
+| contenttype.go:49:11:49:16 | selection of Form | contenttype.go:49:11:49:28 | call to Get | provenance | Src:MaD:797 MaD:870 |
| contenttype.go:49:11:49:28 | call to Get | contenttype.go:53:34:53:37 | data | provenance | |
-| contenttype.go:63:10:63:28 | call to FormValue | contenttype.go:64:52:64:55 | data | provenance | Src:MaD:781 |
-| contenttype.go:73:10:73:28 | call to FormValue | contenttype.go:79:11:79:14 | data | provenance | Src:MaD:781 |
-| contenttype.go:88:10:88:28 | call to FormValue | contenttype.go:91:4:91:7 | data | provenance | Src:MaD:781 |
-| contenttype.go:113:10:113:28 | call to FormValue | contenttype.go:114:50:114:53 | data | provenance | Src:MaD:781 |
-| reflectedxsstest.go:31:2:31:44 | ... := ...[0] | reflectedxsstest.go:32:34:32:37 | file | provenance | Src:MaD:780 |
-| reflectedxsstest.go:31:2:31:44 | ... := ...[1] | reflectedxsstest.go:34:46:34:60 | selection of Filename | provenance | Src:MaD:780 |
+| contenttype.go:63:10:63:28 | call to FormValue | contenttype.go:64:52:64:55 | data | provenance | Src:MaD:790 |
+| contenttype.go:73:10:73:28 | call to FormValue | contenttype.go:79:11:79:14 | data | provenance | Src:MaD:790 |
+| contenttype.go:88:10:88:28 | call to FormValue | contenttype.go:91:4:91:7 | data | provenance | Src:MaD:790 |
+| contenttype.go:113:10:113:28 | call to FormValue | contenttype.go:114:50:114:53 | data | provenance | Src:MaD:790 |
+| reflectedxsstest.go:31:2:31:44 | ... := ...[0] | reflectedxsstest.go:32:34:32:37 | file | provenance | Src:MaD:789 |
+| reflectedxsstest.go:31:2:31:44 | ... := ...[1] | reflectedxsstest.go:34:46:34:60 | selection of Filename | provenance | Src:MaD:789 |
| reflectedxsstest.go:32:2:32:38 | ... := ...[0] | reflectedxsstest.go:33:49:33:55 | content | provenance | |
-| reflectedxsstest.go:32:34:32:37 | file | reflectedxsstest.go:32:2:32:38 | ... := ...[0] | provenance | MaD:651 |
+| reflectedxsstest.go:32:34:32:37 | file | reflectedxsstest.go:32:2:32:38 | ... := ...[0] | provenance | MaD:660 |
| reflectedxsstest.go:33:17:33:56 | []type{args} [array] | reflectedxsstest.go:33:17:33:56 | call to Sprintf | provenance | MaD:248 |
| reflectedxsstest.go:33:17:33:56 | call to Sprintf | reflectedxsstest.go:33:10:33:57 | type conversion | provenance | |
| reflectedxsstest.go:33:49:33:55 | content | reflectedxsstest.go:33:17:33:56 | []type{args} [array] | provenance | |
@@ -21,32 +21,32 @@ edges
| reflectedxsstest.go:34:17:34:61 | call to Sprintf | reflectedxsstest.go:34:10:34:62 | type conversion | provenance | |
| reflectedxsstest.go:34:46:34:60 | selection of Filename | reflectedxsstest.go:34:17:34:61 | []type{args} [array] | provenance | |
| reflectedxsstest.go:34:46:34:60 | selection of Filename | reflectedxsstest.go:34:17:34:61 | call to Sprintf | provenance | FunctionModel |
-| reflectedxsstest.go:38:2:38:35 | ... := ...[0] | reflectedxsstest.go:39:16:39:21 | reader | provenance | Src:MaD:782 |
+| reflectedxsstest.go:38:2:38:35 | ... := ...[0] | reflectedxsstest.go:39:16:39:21 | reader | provenance | Src:MaD:791 |
| reflectedxsstest.go:39:2:39:32 | ... := ...[0] | reflectedxsstest.go:40:14:40:17 | part | provenance | |
| reflectedxsstest.go:39:2:39:32 | ... := ...[0] | reflectedxsstest.go:42:2:42:5 | part | provenance | |
-| reflectedxsstest.go:39:16:39:21 | reader | reflectedxsstest.go:39:2:39:32 | ... := ...[0] | provenance | MaD:741 |
-| reflectedxsstest.go:40:14:40:17 | part | reflectedxsstest.go:40:14:40:28 | call to FileName | provenance | MaD:739 |
+| reflectedxsstest.go:39:16:39:21 | reader | reflectedxsstest.go:39:2:39:32 | ... := ...[0] | provenance | MaD:750 |
+| reflectedxsstest.go:40:14:40:17 | part | reflectedxsstest.go:40:14:40:28 | call to FileName | provenance | MaD:748 |
| reflectedxsstest.go:40:14:40:28 | call to FileName | reflectedxsstest.go:44:46:44:53 | partName | provenance | |
| reflectedxsstest.go:41:2:41:10 | definition of byteSlice | reflectedxsstest.go:45:10:45:18 | byteSlice | provenance | |
-| reflectedxsstest.go:42:2:42:5 | part | reflectedxsstest.go:41:2:41:10 | definition of byteSlice | provenance | MaD:664 |
+| reflectedxsstest.go:42:2:42:5 | part | reflectedxsstest.go:41:2:41:10 | definition of byteSlice | provenance | MaD:673 |
| reflectedxsstest.go:44:17:44:54 | []type{args} [array] | reflectedxsstest.go:44:17:44:54 | call to Sprintf | provenance | MaD:248 |
| reflectedxsstest.go:44:17:44:54 | call to Sprintf | reflectedxsstest.go:44:10:44:55 | type conversion | provenance | |
| reflectedxsstest.go:44:46:44:53 | partName | reflectedxsstest.go:44:17:44:54 | []type{args} [array] | provenance | |
| reflectedxsstest.go:44:46:44:53 | partName | reflectedxsstest.go:44:17:44:54 | call to Sprintf | provenance | FunctionModel |
-| reflectedxsstest.go:51:14:51:18 | selection of URL | reflectedxsstest.go:51:14:51:26 | call to Query | provenance | Src:MaD:793 MaD:854 |
+| reflectedxsstest.go:51:14:51:18 | selection of URL | reflectedxsstest.go:51:14:51:26 | call to Query | provenance | Src:MaD:802 MaD:863 |
| reflectedxsstest.go:51:14:51:26 | call to Query | reflectedxsstest.go:54:11:54:21 | type conversion | provenance | |
-| tst.go:14:15:14:20 | selection of Form | tst.go:14:15:14:36 | call to Get | provenance | Src:MaD:788 MaD:861 |
+| tst.go:14:15:14:20 | selection of Form | tst.go:14:15:14:36 | call to Get | provenance | Src:MaD:797 MaD:870 |
| tst.go:14:15:14:36 | call to Get | tst.go:18:32:18:32 | a | provenance | |
| tst.go:18:19:18:38 | call to Join | tst.go:18:12:18:39 | type conversion | provenance | |
-| tst.go:18:32:18:32 | a | tst.go:18:19:18:38 | call to Join | provenance | MaD:953 |
-| tst.go:48:14:48:19 | selection of Form | tst.go:48:14:48:34 | call to Get | provenance | Src:MaD:788 MaD:861 |
+| tst.go:18:32:18:32 | a | tst.go:18:19:18:38 | call to Join | provenance | MaD:964 |
+| tst.go:48:14:48:19 | selection of Form | tst.go:48:14:48:34 | call to Get | provenance | Src:MaD:797 MaD:870 |
| tst.go:48:14:48:34 | call to Get | tst.go:53:12:53:26 | type conversion | provenance | |
-| websocketXss.go:30:7:30:10 | definition of xnet | websocketXss.go:32:24:32:27 | xnet | provenance | |
-| websocketXss.go:34:3:34:7 | definition of xnet2 | websocketXss.go:36:24:36:28 | xnet2 | provenance | |
-| websocketXss.go:40:3:40:40 | ... := ...[1] | websocketXss.go:41:24:41:29 | nhooyr | provenance | |
-| websocketXss.go:46:7:46:16 | definition of gorillaMsg | websocketXss.go:48:24:48:33 | gorillaMsg | provenance | |
-| websocketXss.go:50:3:50:10 | definition of gorilla2 | websocketXss.go:52:24:52:31 | gorilla2 | provenance | |
-| websocketXss.go:54:3:54:38 | ... := ...[1] | websocketXss.go:55:24:55:31 | gorilla3 | provenance | |
+| websocketXss.go:30:7:30:10 | definition of xnet | websocketXss.go:32:24:32:27 | xnet | provenance | Src:MaD:604 |
+| websocketXss.go:34:3:34:7 | definition of xnet2 | websocketXss.go:36:24:36:28 | xnet2 | provenance | Src:MaD:603 |
+| websocketXss.go:40:3:40:40 | ... := ...[1] | websocketXss.go:41:24:41:29 | nhooyr | provenance | Src:MaD:871 |
+| websocketXss.go:46:7:46:16 | definition of gorillaMsg | websocketXss.go:48:24:48:33 | gorillaMsg | provenance | Src:MaD:448 |
+| websocketXss.go:50:3:50:10 | definition of gorilla2 | websocketXss.go:52:24:52:31 | gorilla2 | provenance | Src:MaD:449 |
+| websocketXss.go:54:3:54:38 | ... := ...[1] | websocketXss.go:55:24:55:31 | gorilla3 | provenance | Src:MaD:450 |
nodes
| ReflectedXss.go:11:15:11:20 | selection of Form | semmle.label | selection of Form |
| ReflectedXss.go:11:15:11:36 | call to Get | semmle.label | call to Get |
diff --git a/go/ql/test/query-tests/Security/CWE-089/SqlInjection.expected b/go/ql/test/query-tests/Security/CWE-089/SqlInjection.expected
index 7b4782e9d83d9..1b57d8a4ab658 100644
--- a/go/ql/test/query-tests/Security/CWE-089/SqlInjection.expected
+++ b/go/ql/test/query-tests/Security/CWE-089/SqlInjection.expected
@@ -1,12 +1,12 @@
edges
| SqlInjection.go:10:7:11:30 | []type{args} [array] | SqlInjection.go:10:7:11:30 | call to Sprintf | provenance | MaD:248 |
| SqlInjection.go:10:7:11:30 | call to Sprintf | SqlInjection.go:12:11:12:11 | q | provenance | |
-| SqlInjection.go:11:3:11:9 | selection of URL | SqlInjection.go:11:3:11:17 | call to Query | provenance | Src:MaD:793 MaD:854 |
+| SqlInjection.go:11:3:11:9 | selection of URL | SqlInjection.go:11:3:11:17 | call to Query | provenance | Src:MaD:802 MaD:863 |
| SqlInjection.go:11:3:11:17 | call to Query | SqlInjection.go:11:3:11:29 | index expression | provenance | |
| SqlInjection.go:11:3:11:29 | index expression | SqlInjection.go:10:7:11:30 | []type{args} [array] | provenance | |
| SqlInjection.go:11:3:11:29 | index expression | SqlInjection.go:10:7:11:30 | call to Sprintf | provenance | FunctionModel |
| issue48.go:17:2:17:33 | ... := ...[0] | issue48.go:18:17:18:17 | b | provenance | |
-| issue48.go:17:25:17:32 | selection of Body | issue48.go:17:2:17:33 | ... := ...[0] | provenance | Src:MaD:786 MaD:651 |
+| issue48.go:17:25:17:32 | selection of Body | issue48.go:17:2:17:33 | ... := ...[0] | provenance | Src:MaD:795 MaD:660 |
| issue48.go:18:17:18:17 | b | issue48.go:18:20:18:39 | &... | provenance | MaD:187 |
| issue48.go:18:20:18:39 | &... | issue48.go:21:3:21:33 | index expression | provenance | |
| issue48.go:20:8:21:34 | []type{args} [array] | issue48.go:20:8:21:34 | call to Sprintf | provenance | MaD:248 |
@@ -14,7 +14,7 @@ edges
| issue48.go:21:3:21:33 | index expression | issue48.go:20:8:21:34 | []type{args} [array] | provenance | |
| issue48.go:21:3:21:33 | index expression | issue48.go:20:8:21:34 | call to Sprintf | provenance | FunctionModel |
| issue48.go:27:2:27:34 | ... := ...[0] | issue48.go:28:17:28:18 | b2 | provenance | |
-| issue48.go:27:26:27:33 | selection of Body | issue48.go:27:2:27:34 | ... := ...[0] | provenance | Src:MaD:786 MaD:651 |
+| issue48.go:27:26:27:33 | selection of Body | issue48.go:27:2:27:34 | ... := ...[0] | provenance | Src:MaD:795 MaD:660 |
| issue48.go:28:17:28:18 | b2 | issue48.go:28:21:28:41 | &... | provenance | MaD:187 |
| issue48.go:28:21:28:41 | &... | issue48.go:31:3:31:31 | selection of Category | provenance | |
| issue48.go:30:8:31:32 | []type{args} [array] | issue48.go:30:8:31:32 | call to Sprintf | provenance | MaD:248 |
@@ -22,26 +22,26 @@ edges
| issue48.go:31:3:31:31 | selection of Category | issue48.go:30:8:31:32 | []type{args} [array] | provenance | |
| issue48.go:31:3:31:31 | selection of Category | issue48.go:30:8:31:32 | call to Sprintf | provenance | FunctionModel |
| issue48.go:37:17:37:50 | type conversion | issue48.go:37:53:37:73 | &... | provenance | MaD:187 |
-| issue48.go:37:24:37:30 | selection of URL | issue48.go:37:24:37:38 | call to Query | provenance | Src:MaD:793 MaD:854 |
+| issue48.go:37:24:37:30 | selection of URL | issue48.go:37:24:37:38 | call to Query | provenance | Src:MaD:802 MaD:863 |
| issue48.go:37:24:37:38 | call to Query | issue48.go:37:17:37:50 | type conversion | provenance | |
| issue48.go:37:53:37:73 | &... | issue48.go:40:3:40:31 | selection of Category | provenance | |
| issue48.go:39:8:40:32 | []type{args} [array] | issue48.go:39:8:40:32 | call to Sprintf | provenance | MaD:248 |
| issue48.go:39:8:40:32 | call to Sprintf | issue48.go:41:11:41:12 | q5 | provenance | |
| issue48.go:40:3:40:31 | selection of Category | issue48.go:39:8:40:32 | []type{args} [array] | provenance | |
| issue48.go:40:3:40:31 | selection of Category | issue48.go:39:8:40:32 | call to Sprintf | provenance | FunctionModel |
-| main.go:11:11:11:16 | selection of Form | main.go:11:11:11:28 | index expression | provenance | Src:MaD:788 |
+| main.go:11:11:11:16 | selection of Form | main.go:11:11:11:28 | index expression | provenance | Src:MaD:797 |
| main.go:15:11:15:84 | []type{args} [array] | main.go:15:11:15:84 | call to Sprintf | provenance | MaD:248 |
-| main.go:15:63:15:67 | selection of URL | main.go:15:63:15:75 | call to Query | provenance | Src:MaD:793 MaD:854 |
+| main.go:15:63:15:67 | selection of URL | main.go:15:63:15:75 | call to Query | provenance | Src:MaD:802 MaD:863 |
| main.go:15:63:15:75 | call to Query | main.go:15:63:15:83 | index expression | provenance | |
| main.go:15:63:15:83 | index expression | main.go:15:11:15:84 | []type{args} [array] | provenance | |
| main.go:15:63:15:83 | index expression | main.go:15:11:15:84 | call to Sprintf | provenance | FunctionModel |
| main.go:16:11:16:85 | []type{args} [array] | main.go:16:11:16:85 | call to Sprintf | provenance | MaD:248 |
-| main.go:16:63:16:70 | selection of Header | main.go:16:63:16:84 | call to Get | provenance | Src:MaD:791 MaD:766 |
+| main.go:16:63:16:70 | selection of Header | main.go:16:63:16:84 | call to Get | provenance | Src:MaD:800 MaD:775 |
| main.go:16:63:16:84 | call to Get | main.go:16:11:16:85 | []type{args} [array] | provenance | |
| main.go:16:63:16:84 | call to Get | main.go:16:11:16:85 | call to Sprintf | provenance | FunctionModel |
| main.go:28:17:31:2 | &... [pointer, Category] | main.go:34:3:34:13 | RequestData [pointer, Category] | provenance | |
| main.go:28:18:31:2 | struct literal [Category] | main.go:28:17:31:2 | &... [pointer, Category] | provenance | |
-| main.go:30:13:30:19 | selection of URL | main.go:30:13:30:27 | call to Query | provenance | Src:MaD:793 MaD:854 |
+| main.go:30:13:30:19 | selection of URL | main.go:30:13:30:27 | call to Query | provenance | Src:MaD:802 MaD:863 |
| main.go:30:13:30:27 | call to Query | main.go:30:13:30:39 | index expression | provenance | |
| main.go:30:13:30:39 | index expression | main.go:28:18:31:2 | struct literal [Category] | provenance | |
| main.go:33:7:34:23 | []type{args} [array] | main.go:33:7:34:23 | call to Sprintf | provenance | MaD:248 |
@@ -54,7 +54,7 @@ edges
| main.go:39:2:39:12 | definition of RequestData [pointer, Category] | main.go:43:3:43:13 | RequestData [pointer, Category] | provenance | |
| main.go:40:2:40:12 | RequestData [pointer, Category] | main.go:40:2:40:12 | implicit dereference [Category] | provenance | |
| main.go:40:2:40:12 | implicit dereference [Category] | main.go:39:2:39:12 | definition of RequestData [pointer, Category] | provenance | |
-| main.go:40:25:40:31 | selection of URL | main.go:40:25:40:39 | call to Query | provenance | Src:MaD:793 MaD:854 |
+| main.go:40:25:40:31 | selection of URL | main.go:40:25:40:39 | call to Query | provenance | Src:MaD:802 MaD:863 |
| main.go:40:25:40:39 | call to Query | main.go:40:25:40:51 | index expression | provenance | |
| main.go:40:25:40:51 | index expression | main.go:40:2:40:12 | implicit dereference [Category] | provenance | |
| main.go:42:7:43:23 | []type{args} [array] | main.go:42:7:43:23 | call to Sprintf | provenance | MaD:248 |
@@ -67,7 +67,7 @@ edges
| main.go:48:2:48:12 | definition of RequestData [pointer, Category] | main.go:52:3:52:13 | RequestData [pointer, Category] | provenance | |
| main.go:49:3:49:14 | star expression [Category] | main.go:48:2:48:12 | definition of RequestData [pointer, Category] | provenance | |
| main.go:49:4:49:14 | RequestData [pointer, Category] | main.go:49:3:49:14 | star expression [Category] | provenance | |
-| main.go:49:28:49:34 | selection of URL | main.go:49:28:49:42 | call to Query | provenance | Src:MaD:793 MaD:854 |
+| main.go:49:28:49:34 | selection of URL | main.go:49:28:49:42 | call to Query | provenance | Src:MaD:802 MaD:863 |
| main.go:49:28:49:42 | call to Query | main.go:49:28:49:54 | index expression | provenance | |
| main.go:49:28:49:54 | index expression | main.go:49:3:49:14 | star expression [Category] | provenance | |
| main.go:51:7:52:23 | []type{args} [array] | main.go:51:7:52:23 | call to Sprintf | provenance | MaD:248 |
@@ -80,7 +80,7 @@ edges
| main.go:57:2:57:12 | definition of RequestData [pointer, Category] | main.go:61:5:61:15 | RequestData [pointer, Category] | provenance | |
| main.go:58:3:58:14 | star expression [Category] | main.go:57:2:57:12 | definition of RequestData [pointer, Category] | provenance | |
| main.go:58:4:58:14 | RequestData [pointer, Category] | main.go:58:3:58:14 | star expression [Category] | provenance | |
-| main.go:58:28:58:34 | selection of URL | main.go:58:28:58:42 | call to Query | provenance | Src:MaD:793 MaD:854 |
+| main.go:58:28:58:34 | selection of URL | main.go:58:28:58:42 | call to Query | provenance | Src:MaD:802 MaD:863 |
| main.go:58:28:58:42 | call to Query | main.go:58:28:58:54 | index expression | provenance | |
| main.go:58:28:58:54 | index expression | main.go:58:3:58:14 | star expression [Category] | provenance | |
| main.go:60:7:61:26 | []type{args} [array] | main.go:60:7:61:26 | call to Sprintf | provenance | MaD:248 |
@@ -89,7 +89,7 @@ edges
| main.go:61:3:61:25 | selection of Category | main.go:60:7:61:26 | call to Sprintf | provenance | FunctionModel |
| main.go:61:4:61:15 | star expression [Category] | main.go:61:3:61:25 | selection of Category | provenance | |
| main.go:61:5:61:15 | RequestData [pointer, Category] | main.go:61:4:61:15 | star expression [Category] | provenance | |
-| mongoDB.go:40:20:40:30 | call to Referer | mongoDB.go:42:28:42:41 | untrustedInput | provenance | Src:MaD:784 |
+| mongoDB.go:40:20:40:30 | call to Referer | mongoDB.go:42:28:42:41 | untrustedInput | provenance | Src:MaD:793 |
| mongoDB.go:42:19:42:42 | struct literal | mongoDB.go:50:34:50:39 | filter | provenance | |
| mongoDB.go:42:19:42:42 | struct literal | mongoDB.go:61:27:61:32 | filter | provenance | |
| mongoDB.go:42:19:42:42 | struct literal | mongoDB.go:63:23:63:28 | filter | provenance | |
diff --git a/go/ql/test/query-tests/Security/CWE-089/StringBreak.expected b/go/ql/test/query-tests/Security/CWE-089/StringBreak.expected
index 4ae5e467ddf88..923fa5a71d6ae 100644
--- a/go/ql/test/query-tests/Security/CWE-089/StringBreak.expected
+++ b/go/ql/test/query-tests/Security/CWE-089/StringBreak.expected
@@ -2,10 +2,10 @@ edges
| StringBreak.go:10:2:10:40 | ... := ...[0] | StringBreak.go:14:47:14:57 | versionJSON | provenance | |
| StringBreakMismatched.go:12:2:12:40 | ... := ...[0] | StringBreakMismatched.go:13:29:13:47 | type conversion | provenance | |
| StringBreakMismatched.go:13:13:13:62 | call to Replace | StringBreakMismatched.go:17:26:17:32 | escaped | provenance | |
-| StringBreakMismatched.go:13:29:13:47 | type conversion | StringBreakMismatched.go:13:13:13:62 | call to Replace | provenance | MaD:957 |
+| StringBreakMismatched.go:13:29:13:47 | type conversion | StringBreakMismatched.go:13:13:13:62 | call to Replace | provenance | MaD:968 |
| StringBreakMismatched.go:24:2:24:40 | ... := ...[0] | StringBreakMismatched.go:25:29:25:47 | type conversion | provenance | |
| StringBreakMismatched.go:25:13:25:61 | call to Replace | StringBreakMismatched.go:29:27:29:33 | escaped | provenance | |
-| StringBreakMismatched.go:25:29:25:47 | type conversion | StringBreakMismatched.go:25:13:25:61 | call to Replace | provenance | MaD:957 |
+| StringBreakMismatched.go:25:29:25:47 | type conversion | StringBreakMismatched.go:25:13:25:61 | call to Replace | provenance | MaD:968 |
nodes
| StringBreak.go:10:2:10:40 | ... := ...[0] | semmle.label | ... := ...[0] |
| StringBreak.go:14:47:14:57 | versionJSON | semmle.label | versionJSON |
diff --git a/go/ql/test/query-tests/Security/CWE-312/CleartextLogging.expected b/go/ql/test/query-tests/Security/CWE-312/CleartextLogging.expected
index e89946bbc4dc2..1f7fa8d7eca80 100644
--- a/go/ql/test/query-tests/Security/CWE-312/CleartextLogging.expected
+++ b/go/ql/test/query-tests/Security/CWE-312/CleartextLogging.expected
@@ -1,9 +1,9 @@
edges
| klog.go:20:3:25:3 | range statement[1] | klog.go:21:27:21:33 | headers | provenance | |
-| klog.go:20:30:20:37 | selection of Header | klog.go:20:3:25:3 | range statement[1] | provenance | Src:MaD:791 Config |
+| klog.go:20:30:20:37 | selection of Header | klog.go:20:3:25:3 | range statement[1] | provenance | Src:MaD:800 Config |
| klog.go:21:4:24:4 | range statement[1] | klog.go:22:15:22:20 | header | provenance | |
| klog.go:21:27:21:33 | headers | klog.go:21:4:24:4 | range statement[1] | provenance | Config |
-| klog.go:28:13:28:20 | selection of Header | klog.go:28:13:28:41 | call to Get | provenance | Src:MaD:791 Config |
+| klog.go:28:13:28:20 | selection of Header | klog.go:28:13:28:41 | call to Get | provenance | Src:MaD:800 Config |
| overrides.go:9:9:9:16 | password | overrides.go:13:14:13:23 | call to String | provenance | |
| passwords.go:8:12:8:12 | definition of x | passwords.go:9:14:9:14 | x | provenance | |
| passwords.go:30:8:30:15 | password | passwords.go:8:12:8:12 | definition of x | provenance | |
diff --git a/go/ql/test/query-tests/Security/CWE-338/InsecureRandomness/InsecureRandomness.expected b/go/ql/test/query-tests/Security/CWE-338/InsecureRandomness/InsecureRandomness.expected
index bc62530ad7e07..27d27a1f4cf5f 100644
--- a/go/ql/test/query-tests/Security/CWE-338/InsecureRandomness/InsecureRandomness.expected
+++ b/go/ql/test/query-tests/Security/CWE-338/InsecureRandomness/InsecureRandomness.expected
@@ -9,7 +9,7 @@ edges
| sample.go:33:2:33:6 | definition of nonce | sample.go:37:25:37:29 | nonce | provenance | |
| sample.go:33:2:33:6 | definition of nonce | sample.go:37:32:37:36 | nonce | provenance | |
| sample.go:34:12:34:40 | call to New | sample.go:35:14:35:19 | random | provenance | |
-| sample.go:35:14:35:19 | random | sample.go:33:2:33:6 | definition of nonce | provenance | MaD:660 |
+| sample.go:35:14:35:19 | random | sample.go:33:2:33:6 | definition of nonce | provenance | MaD:669 |
| sample.go:55:17:55:42 | call to Intn | sample.go:56:29:56:38 | randNumber | provenance | |
| sample.go:56:11:56:40 | type conversion | sample.go:58:32:58:43 | type conversion | provenance | |
| sample.go:56:18:56:39 | index expression | sample.go:56:11:56:40 | type conversion | provenance | |
diff --git a/go/ql/test/query-tests/Security/CWE-347/MissingJwtSignatureCheck.expected b/go/ql/test/query-tests/Security/CWE-347/MissingJwtSignatureCheck.expected
index f965acb08c06b..32c78cc4e9db1 100644
--- a/go/ql/test/query-tests/Security/CWE-347/MissingJwtSignatureCheck.expected
+++ b/go/ql/test/query-tests/Security/CWE-347/MissingJwtSignatureCheck.expected
@@ -1,16 +1,16 @@
edges
-| go-jose.v3.go:25:16:25:20 | selection of URL | go-jose.v3.go:25:16:25:28 | call to Query | provenance | Src:MaD:793 MaD:854 |
-| go-jose.v3.go:25:16:25:28 | call to Query | go-jose.v3.go:25:16:25:47 | call to Get | provenance | MaD:861 |
+| go-jose.v3.go:25:16:25:20 | selection of URL | go-jose.v3.go:25:16:25:28 | call to Query | provenance | Src:MaD:802 MaD:863 |
+| go-jose.v3.go:25:16:25:28 | call to Query | go-jose.v3.go:25:16:25:47 | call to Get | provenance | MaD:870 |
| go-jose.v3.go:25:16:25:47 | call to Get | go-jose.v3.go:26:15:26:25 | signedToken | provenance | |
| go-jose.v3.go:26:15:26:25 | signedToken | go-jose.v3.go:29:19:29:29 | definition of signedToken | provenance | |
| go-jose.v3.go:29:19:29:29 | definition of signedToken | go-jose.v3.go:31:37:31:47 | signedToken | provenance | |
| go-jose.v3.go:31:2:31:48 | ... := ...[0] | go-jose.v3.go:33:12:33:23 | DecodedToken | provenance | Sink:MaD:415 |
| go-jose.v3.go:31:37:31:47 | signedToken | go-jose.v3.go:31:2:31:48 | ... := ...[0] | provenance | MaD:417 |
-| golang-jwt-v5.go:28:16:28:20 | selection of URL | golang-jwt-v5.go:28:16:28:28 | call to Query | provenance | Src:MaD:793 MaD:854 |
-| golang-jwt-v5.go:28:16:28:28 | call to Query | golang-jwt-v5.go:28:16:28:47 | call to Get | provenance | MaD:861 |
+| golang-jwt-v5.go:28:16:28:20 | selection of URL | golang-jwt-v5.go:28:16:28:28 | call to Query | provenance | Src:MaD:802 MaD:863 |
+| golang-jwt-v5.go:28:16:28:28 | call to Query | golang-jwt-v5.go:28:16:28:47 | call to Get | provenance | MaD:870 |
| golang-jwt-v5.go:28:16:28:47 | call to Get | golang-jwt-v5.go:29:25:29:35 | signedToken | provenance | |
| golang-jwt-v5.go:29:25:29:35 | signedToken | golang-jwt-v5.go:32:29:32:39 | definition of signedToken | provenance | |
-| golang-jwt-v5.go:32:29:32:39 | definition of signedToken | golang-jwt-v5.go:34:58:34:68 | signedToken | provenance | Sink:MaD:429 |
+| golang-jwt-v5.go:32:29:32:39 | definition of signedToken | golang-jwt-v5.go:34:58:34:68 | signedToken | provenance | Sink:MaD:431 |
nodes
| go-jose.v3.go:25:16:25:20 | selection of URL | semmle.label | selection of URL |
| go-jose.v3.go:25:16:25:28 | call to Query | semmle.label | call to Query |
diff --git a/go/ql/test/query-tests/Security/CWE-601/BadRedirectCheck/BadRedirectCheck.expected b/go/ql/test/query-tests/Security/CWE-601/BadRedirectCheck/BadRedirectCheck.expected
index 9dcdd9c081b82..aea61f57f6b2a 100644
--- a/go/ql/test/query-tests/Security/CWE-601/BadRedirectCheck/BadRedirectCheck.expected
+++ b/go/ql/test/query-tests/Security/CWE-601/BadRedirectCheck/BadRedirectCheck.expected
@@ -12,8 +12,8 @@ edges
| main.go:68:17:68:24 | argument corresponding to redirect | main.go:73:20:73:27 | redirect | provenance | |
| main.go:68:17:68:24 | definition of redirect | main.go:73:20:73:27 | redirect | provenance | |
| main.go:73:9:73:28 | call to Clean | main.go:77:25:77:39 | call to getTarget1 | provenance | |
-| main.go:73:20:73:27 | redirect | main.go:73:9:73:28 | call to Clean | provenance | MaD:880 |
-| main.go:73:20:73:27 | redirect | main.go:73:9:73:28 | call to Clean | provenance | MaD:880 |
+| main.go:73:20:73:27 | redirect | main.go:73:9:73:28 | call to Clean | provenance | MaD:891 |
+| main.go:73:20:73:27 | redirect | main.go:73:9:73:28 | call to Clean | provenance | MaD:891 |
| main.go:76:19:76:21 | argument corresponding to url | main.go:77:36:77:38 | url | provenance | |
| main.go:77:36:77:38 | url | main.go:68:17:68:24 | definition of redirect | provenance | |
| main.go:77:36:77:38 | url | main.go:77:25:77:39 | call to getTarget1 | provenance | |
diff --git a/go/ql/test/query-tests/Security/CWE-601/OpenUrlRedirect/OpenUrlRedirect.expected b/go/ql/test/query-tests/Security/CWE-601/OpenUrlRedirect/OpenUrlRedirect.expected
index 928489005d8ab..3d0e867ca97e2 100644
--- a/go/ql/test/query-tests/Security/CWE-601/OpenUrlRedirect/OpenUrlRedirect.expected
+++ b/go/ql/test/query-tests/Security/CWE-601/OpenUrlRedirect/OpenUrlRedirect.expected
@@ -1,19 +1,19 @@
edges
-| OpenUrlRedirect.go:10:23:10:28 | selection of Form | OpenUrlRedirect.go:10:23:10:42 | call to Get | provenance | Src:MaD:788 Config |
-| stdlib.go:13:13:13:18 | selection of Form | stdlib.go:13:13:13:32 | call to Get | provenance | Src:MaD:788 Config |
+| OpenUrlRedirect.go:10:23:10:28 | selection of Form | OpenUrlRedirect.go:10:23:10:42 | call to Get | provenance | Src:MaD:797 Config |
+| stdlib.go:13:13:13:18 | selection of Form | stdlib.go:13:13:13:32 | call to Get | provenance | Src:MaD:797 Config |
| stdlib.go:13:13:13:32 | call to Get | stdlib.go:15:30:15:35 | target | provenance | |
-| stdlib.go:22:13:22:18 | selection of Form | stdlib.go:22:13:22:32 | call to Get | provenance | Src:MaD:788 Config |
+| stdlib.go:22:13:22:18 | selection of Form | stdlib.go:22:13:22:32 | call to Get | provenance | Src:MaD:797 Config |
| stdlib.go:22:13:22:32 | call to Get | stdlib.go:24:30:24:35 | target | provenance | |
-| stdlib.go:31:13:31:18 | selection of Form | stdlib.go:31:13:31:32 | call to Get | provenance | Src:MaD:788 Config |
+| stdlib.go:31:13:31:18 | selection of Form | stdlib.go:31:13:31:32 | call to Get | provenance | Src:MaD:797 Config |
| stdlib.go:31:13:31:32 | call to Get | stdlib.go:35:34:35:39 | target | provenance | |
| stdlib.go:35:34:35:39 | target | stdlib.go:35:30:35:39 | ...+... | provenance | Config |
-| stdlib.go:44:13:44:18 | selection of Form | stdlib.go:44:13:44:32 | call to Get | provenance | Src:MaD:788 Config |
+| stdlib.go:44:13:44:18 | selection of Form | stdlib.go:44:13:44:32 | call to Get | provenance | Src:MaD:797 Config |
| stdlib.go:44:13:44:32 | call to Get | stdlib.go:46:23:46:28 | target | provenance | |
-| stdlib.go:64:13:64:18 | selection of Form | stdlib.go:64:13:64:32 | call to Get | provenance | Src:MaD:788 Config |
+| stdlib.go:64:13:64:18 | selection of Form | stdlib.go:64:13:64:32 | call to Get | provenance | Src:MaD:797 Config |
| stdlib.go:64:13:64:32 | call to Get | stdlib.go:67:23:67:28 | target | provenance | |
| stdlib.go:67:23:67:28 | target | stdlib.go:67:23:67:37 | ...+... | provenance | Config |
| stdlib.go:67:23:67:37 | ...+... | stdlib.go:67:23:67:40 | ...+... | provenance | Config |
-| stdlib.go:89:13:89:18 | selection of Form | stdlib.go:89:13:89:32 | call to Get | provenance | Src:MaD:788 Config |
+| stdlib.go:89:13:89:18 | selection of Form | stdlib.go:89:13:89:32 | call to Get | provenance | Src:MaD:797 Config |
| stdlib.go:89:13:89:32 | call to Get | stdlib.go:90:3:90:8 | target | provenance | |
| stdlib.go:90:3:90:8 | target | stdlib.go:90:3:90:25 | ... += ... | provenance | Config |
| stdlib.go:90:3:90:25 | ... += ... | stdlib.go:92:23:92:28 | target | provenance | |
@@ -28,26 +28,26 @@ edges
| stdlib.go:112:4:112:4 | r [pointer, URL] | stdlib.go:112:4:112:4 | implicit dereference [URL] | provenance | |
| stdlib.go:112:4:112:8 | implicit dereference | stdlib.go:112:4:112:8 | selection of URL | provenance | Config |
| stdlib.go:112:4:112:8 | implicit dereference | stdlib.go:112:4:112:8 | selection of URL [pointer] | provenance | |
-| stdlib.go:112:4:112:8 | selection of URL | stdlib.go:112:4:112:4 | implicit dereference [URL] | provenance | Src:MaD:793 |
-| stdlib.go:112:4:112:8 | selection of URL | stdlib.go:112:4:112:8 | implicit dereference | provenance | Src:MaD:793 Config |
+| stdlib.go:112:4:112:8 | selection of URL | stdlib.go:112:4:112:4 | implicit dereference [URL] | provenance | Src:MaD:802 |
+| stdlib.go:112:4:112:8 | selection of URL | stdlib.go:112:4:112:8 | implicit dereference | provenance | Src:MaD:802 Config |
| stdlib.go:112:4:112:8 | selection of URL [pointer] | stdlib.go:112:4:112:4 | implicit dereference [URL, pointer] | provenance | |
| stdlib.go:112:4:112:8 | selection of URL [pointer] | stdlib.go:112:4:112:8 | implicit dereference | provenance | |
| stdlib.go:113:24:113:24 | implicit dereference [URL] | stdlib.go:113:24:113:28 | selection of URL | provenance | |
| stdlib.go:113:24:113:24 | r [pointer, URL] | stdlib.go:113:24:113:24 | implicit dereference [URL] | provenance | |
-| stdlib.go:113:24:113:28 | selection of URL | stdlib.go:113:24:113:37 | call to String | provenance | Src:MaD:793 Config |
-| stdlib.go:146:13:146:18 | selection of Form | stdlib.go:146:13:146:32 | call to Get | provenance | Src:MaD:788 Config |
+| stdlib.go:113:24:113:28 | selection of URL | stdlib.go:113:24:113:37 | call to String | provenance | Src:MaD:802 Config |
+| stdlib.go:146:13:146:18 | selection of Form | stdlib.go:146:13:146:32 | call to Get | provenance | Src:MaD:797 Config |
| stdlib.go:146:13:146:32 | call to Get | stdlib.go:152:23:152:28 | target | provenance | |
| stdlib.go:159:10:159:15 | star expression | stdlib.go:159:11:159:15 | selection of URL | provenance | Config |
| stdlib.go:159:10:159:15 | star expression | stdlib.go:162:24:162:26 | url | provenance | |
-| stdlib.go:159:11:159:15 | selection of URL | stdlib.go:159:10:159:15 | star expression | provenance | Src:MaD:793 Config |
+| stdlib.go:159:11:159:15 | selection of URL | stdlib.go:159:10:159:15 | star expression | provenance | Src:MaD:802 Config |
| stdlib.go:162:24:162:26 | url | stdlib.go:162:24:162:35 | call to String | provenance | Config |
-| stdlib.go:173:35:173:39 | selection of URL | stdlib.go:173:35:173:52 | call to RequestURI | provenance | Src:MaD:793 Config |
+| stdlib.go:173:35:173:39 | selection of URL | stdlib.go:173:35:173:52 | call to RequestURI | provenance | Src:MaD:802 Config |
| stdlib.go:173:35:173:52 | call to RequestURI | stdlib.go:173:24:173:52 | ...+... | provenance | Config |
-| stdlib.go:182:13:182:33 | call to FormValue | stdlib.go:184:23:184:28 | target | provenance | Src:MaD:781 |
+| stdlib.go:182:13:182:33 | call to FormValue | stdlib.go:184:23:184:28 | target | provenance | Src:MaD:790 |
| stdlib.go:190:3:190:8 | definition of target | stdlib.go:192:23:192:28 | target | provenance | |
| stdlib.go:190:3:190:8 | definition of target | stdlib.go:194:23:194:28 | target | provenance | |
| stdlib.go:190:3:190:57 | ... := ...[0] | stdlib.go:190:3:190:8 | definition of target | provenance | |
-| stdlib.go:190:36:190:56 | call to FormValue | stdlib.go:190:3:190:57 | ... := ...[0] | provenance | Src:MaD:781 Config |
+| stdlib.go:190:36:190:56 | call to FormValue | stdlib.go:190:3:190:57 | ... := ...[0] | provenance | Src:MaD:790 Config |
| stdlib.go:192:23:192:28 | implicit dereference | stdlib.go:190:3:190:8 | definition of target | provenance | Config |
| stdlib.go:192:23:192:28 | implicit dereference | stdlib.go:192:23:192:33 | selection of Path | provenance | Config |
| stdlib.go:192:23:192:28 | target | stdlib.go:192:23:192:28 | implicit dereference | provenance | Config |
diff --git a/go/ql/test/query-tests/Security/CWE-640/EmailInjection.expected b/go/ql/test/query-tests/Security/CWE-640/EmailInjection.expected
index 165b65c5ac797..07c431401623d 100644
--- a/go/ql/test/query-tests/Security/CWE-640/EmailInjection.expected
+++ b/go/ql/test/query-tests/Security/CWE-640/EmailInjection.expected
@@ -1,23 +1,23 @@
edges
-| EmailBad.go:9:10:9:17 | selection of Header | EmailBad.go:9:10:9:29 | call to Get | provenance | Src:MaD:791 MaD:766 |
+| EmailBad.go:9:10:9:17 | selection of Header | EmailBad.go:9:10:9:29 | call to Get | provenance | Src:MaD:800 MaD:775 |
| EmailBad.go:9:10:9:29 | call to Get | EmailBad.go:12:56:12:67 | type conversion | provenance | |
-| main.go:29:21:29:31 | call to Referer | main.go:31:57:31:78 | type conversion | provenance | Src:MaD:784 |
-| main.go:37:21:37:31 | call to Referer | main.go:41:25:41:38 | untrustedInput | provenance | Src:MaD:784 |
-| main.go:41:25:41:38 | untrustedInput | main.go:40:3:40:7 | definition of write | provenance | MaD:663 |
-| main.go:46:21:46:31 | call to Referer | main.go:52:46:52:59 | untrustedInput | provenance | Src:MaD:784 |
-| main.go:46:21:46:31 | call to Referer | main.go:53:52:53:65 | untrustedInput | provenance | Src:MaD:784 |
-| main.go:58:21:58:31 | call to Referer | main.go:60:47:60:60 | untrustedInput | provenance | Src:MaD:784 |
+| main.go:29:21:29:31 | call to Referer | main.go:31:57:31:78 | type conversion | provenance | Src:MaD:793 |
+| main.go:37:21:37:31 | call to Referer | main.go:41:25:41:38 | untrustedInput | provenance | Src:MaD:793 |
+| main.go:41:25:41:38 | untrustedInput | main.go:40:3:40:7 | definition of write | provenance | MaD:672 |
+| main.go:46:21:46:31 | call to Referer | main.go:52:46:52:59 | untrustedInput | provenance | Src:MaD:793 |
+| main.go:46:21:46:31 | call to Referer | main.go:53:52:53:65 | untrustedInput | provenance | Src:MaD:793 |
+| main.go:58:21:58:31 | call to Referer | main.go:60:47:60:60 | untrustedInput | provenance | Src:MaD:793 |
| main.go:60:14:60:61 | call to NewContent | main.go:63:16:63:22 | content | provenance | |
-| main.go:60:47:60:60 | untrustedInput | main.go:60:14:60:61 | call to NewContent | provenance | MaD:508 |
-| main.go:68:21:68:31 | call to Referer | main.go:74:47:74:60 | untrustedInput | provenance | Src:MaD:784 |
+| main.go:60:47:60:60 | untrustedInput | main.go:60:14:60:61 | call to NewContent | provenance | MaD:515 |
+| main.go:68:21:68:31 | call to Referer | main.go:74:47:74:60 | untrustedInput | provenance | Src:MaD:793 |
| main.go:74:14:74:61 | call to NewContent | main.go:76:50:76:56 | content | provenance | |
| main.go:74:14:74:61 | call to NewContent | main.go:76:59:76:65 | content | provenance | |
| main.go:74:14:74:61 | call to NewContent | main.go:77:16:77:22 | content | provenance | |
-| main.go:74:47:74:60 | untrustedInput | main.go:74:14:74:61 | call to NewContent | provenance | MaD:508 |
-| main.go:82:21:82:31 | call to Referer | main.go:89:37:89:50 | untrustedInput | provenance | Src:MaD:784 |
-| main.go:82:21:82:31 | call to Referer | main.go:91:48:91:61 | untrustedInput | provenance | Src:MaD:784 |
+| main.go:74:47:74:60 | untrustedInput | main.go:74:14:74:61 | call to NewContent | provenance | MaD:515 |
+| main.go:82:21:82:31 | call to Referer | main.go:89:37:89:50 | untrustedInput | provenance | Src:MaD:793 |
+| main.go:82:21:82:31 | call to Referer | main.go:91:48:91:61 | untrustedInput | provenance | Src:MaD:793 |
| main.go:91:15:91:62 | call to NewContent | main.go:93:16:93:23 | content2 | provenance | |
-| main.go:91:48:91:61 | untrustedInput | main.go:91:15:91:62 | call to NewContent | provenance | MaD:508 |
+| main.go:91:48:91:61 | untrustedInput | main.go:91:15:91:62 | call to NewContent | provenance | MaD:515 |
nodes
| EmailBad.go:9:10:9:17 | selection of Header | semmle.label | selection of Header |
| EmailBad.go:9:10:9:29 | call to Get | semmle.label | call to Get |
diff --git a/go/ql/test/query-tests/Security/CWE-643/XPathInjection.expected b/go/ql/test/query-tests/Security/CWE-643/XPathInjection.expected
index 1f5687339be7d..47739bb945b9e 100644
--- a/go/ql/test/query-tests/Security/CWE-643/XPathInjection.expected
+++ b/go/ql/test/query-tests/Security/CWE-643/XPathInjection.expected
@@ -1,16 +1,16 @@
edges
-| XPathInjection.go:13:14:13:19 | selection of Form | XPathInjection.go:13:14:13:35 | call to Get | provenance | Src:MaD:788 MaD:861 |
+| XPathInjection.go:13:14:13:19 | selection of Form | XPathInjection.go:13:14:13:35 | call to Get | provenance | Src:MaD:797 MaD:870 |
| XPathInjection.go:13:14:13:35 | call to Get | XPathInjection.go:16:29:16:91 | ...+... | provenance | |
-| tst.go:34:14:34:19 | selection of Form | tst.go:34:14:34:35 | call to Get | provenance | Src:MaD:788 MaD:861 |
+| tst.go:34:14:34:19 | selection of Form | tst.go:34:14:34:35 | call to Get | provenance | Src:MaD:797 MaD:870 |
| tst.go:34:14:34:35 | call to Get | tst.go:37:23:37:85 | ...+... | provenance | |
| tst.go:34:14:34:35 | call to Get | tst.go:40:24:40:86 | ...+... | provenance | |
| tst.go:34:14:34:35 | call to Get | tst.go:43:24:43:82 | ...+... | provenance | |
-| tst.go:48:14:48:19 | selection of Form | tst.go:48:14:48:35 | call to Get | provenance | Src:MaD:788 MaD:861 |
+| tst.go:48:14:48:19 | selection of Form | tst.go:48:14:48:35 | call to Get | provenance | Src:MaD:797 MaD:870 |
| tst.go:48:14:48:35 | call to Get | tst.go:51:26:51:84 | ...+... | provenance | |
| tst.go:48:14:48:35 | call to Get | tst.go:54:29:54:87 | ...+... | provenance | |
| tst.go:48:14:48:35 | call to Get | tst.go:57:33:57:91 | ...+... | provenance | |
| tst.go:48:14:48:35 | call to Get | tst.go:60:30:60:88 | ...+... | provenance | |
-| tst.go:65:14:65:19 | selection of Form | tst.go:65:14:65:35 | call to Get | provenance | Src:MaD:788 MaD:861 |
+| tst.go:65:14:65:19 | selection of Form | tst.go:65:14:65:35 | call to Get | provenance | Src:MaD:797 MaD:870 |
| tst.go:65:14:65:35 | call to Get | tst.go:68:25:68:83 | ...+... | provenance | |
| tst.go:65:14:65:35 | call to Get | tst.go:71:28:71:86 | ...+... | provenance | |
| tst.go:65:14:65:35 | call to Get | tst.go:74:25:74:83 | ...+... | provenance | |
@@ -19,38 +19,38 @@ edges
| tst.go:65:14:65:35 | call to Get | tst.go:83:29:83:87 | ...+... | provenance | |
| tst.go:65:14:65:35 | call to Get | tst.go:86:23:86:85 | ...+... | provenance | |
| tst.go:65:14:65:35 | call to Get | tst.go:89:22:89:84 | ...+... | provenance | |
-| tst.go:94:14:94:19 | selection of Form | tst.go:94:14:94:35 | call to Get | provenance | Src:MaD:788 MaD:861 |
+| tst.go:94:14:94:19 | selection of Form | tst.go:94:14:94:35 | call to Get | provenance | Src:MaD:797 MaD:870 |
| tst.go:94:14:94:35 | call to Get | tst.go:97:26:97:84 | ...+... | provenance | |
| tst.go:94:14:94:35 | call to Get | tst.go:100:29:100:87 | ...+... | provenance | |
| tst.go:94:14:94:35 | call to Get | tst.go:103:33:103:91 | ...+... | provenance | |
| tst.go:94:14:94:35 | call to Get | tst.go:106:30:106:88 | ...+... | provenance | |
-| tst.go:111:14:111:19 | selection of Form | tst.go:111:14:111:35 | call to Get | provenance | Src:MaD:788 MaD:861 |
+| tst.go:111:14:111:19 | selection of Form | tst.go:111:14:111:35 | call to Get | provenance | Src:MaD:797 MaD:870 |
| tst.go:111:14:111:35 | call to Get | tst.go:114:25:114:87 | ...+... | provenance | |
| tst.go:111:14:111:35 | call to Get | tst.go:117:26:117:88 | ...+... | provenance | |
-| tst.go:122:14:122:19 | selection of Form | tst.go:122:14:122:35 | call to Get | provenance | Src:MaD:788 MaD:861 |
+| tst.go:122:14:122:19 | selection of Form | tst.go:122:14:122:35 | call to Get | provenance | Src:MaD:797 MaD:870 |
| tst.go:122:14:122:35 | call to Get | tst.go:126:23:126:126 | ...+... | provenance | |
| tst.go:122:14:122:35 | call to Get | tst.go:129:24:129:127 | ...+... | provenance | |
| tst.go:122:14:122:35 | call to Get | tst.go:132:27:132:122 | ...+... | provenance | |
-| tst.go:123:14:123:19 | selection of Form | tst.go:123:14:123:35 | call to Get | provenance | Src:MaD:788 MaD:861 |
+| tst.go:123:14:123:19 | selection of Form | tst.go:123:14:123:35 | call to Get | provenance | Src:MaD:797 MaD:870 |
| tst.go:123:14:123:35 | call to Get | tst.go:126:23:126:126 | ...+... | provenance | |
| tst.go:123:14:123:35 | call to Get | tst.go:129:24:129:127 | ...+... | provenance | |
| tst.go:123:14:123:35 | call to Get | tst.go:132:27:132:122 | ...+... | provenance | |
-| tst.go:140:14:140:19 | selection of Form | tst.go:140:14:140:35 | call to Get | provenance | Src:MaD:788 MaD:861 |
+| tst.go:140:14:140:19 | selection of Form | tst.go:140:14:140:35 | call to Get | provenance | Src:MaD:797 MaD:870 |
| tst.go:140:14:140:35 | call to Get | tst.go:143:27:143:89 | ...+... | provenance | |
| tst.go:140:14:140:35 | call to Get | tst.go:146:28:146:90 | ...+... | provenance | |
-| tst.go:151:14:151:19 | selection of Form | tst.go:151:14:151:35 | call to Get | provenance | Src:MaD:788 MaD:861 |
+| tst.go:151:14:151:19 | selection of Form | tst.go:151:14:151:35 | call to Get | provenance | Src:MaD:797 MaD:870 |
| tst.go:151:14:151:35 | call to Get | tst.go:155:33:155:136 | ...+... | provenance | |
| tst.go:151:14:151:35 | call to Get | tst.go:158:18:158:121 | ...+... | provenance | |
| tst.go:151:14:151:35 | call to Get | tst.go:164:31:164:126 | ...+... | provenance | |
| tst.go:151:14:151:35 | call to Get | tst.go:173:21:173:116 | ...+... | provenance | |
| tst.go:151:14:151:35 | call to Get | tst.go:182:27:182:122 | ...+... | provenance | |
-| tst.go:152:14:152:19 | selection of Form | tst.go:152:14:152:35 | call to Get | provenance | Src:MaD:788 MaD:861 |
+| tst.go:152:14:152:19 | selection of Form | tst.go:152:14:152:35 | call to Get | provenance | Src:MaD:797 MaD:870 |
| tst.go:152:14:152:35 | call to Get | tst.go:155:33:155:136 | ...+... | provenance | |
| tst.go:152:14:152:35 | call to Get | tst.go:158:18:158:121 | ...+... | provenance | |
| tst.go:152:14:152:35 | call to Get | tst.go:164:31:164:126 | ...+... | provenance | |
| tst.go:152:14:152:35 | call to Get | tst.go:173:21:173:116 | ...+... | provenance | |
| tst.go:152:14:152:35 | call to Get | tst.go:182:27:182:122 | ...+... | provenance | |
-| tst.go:193:14:193:19 | selection of Form | tst.go:193:14:193:35 | call to Get | provenance | Src:MaD:788 MaD:861 |
+| tst.go:193:14:193:19 | selection of Form | tst.go:193:14:193:35 | call to Get | provenance | Src:MaD:797 MaD:870 |
| tst.go:193:14:193:35 | call to Get | tst.go:198:23:198:85 | ...+... | provenance | |
nodes
| XPathInjection.go:13:14:13:19 | selection of Form | semmle.label | selection of Form |
diff --git a/go/ql/test/query-tests/Security/CWE-918/RequestForgery.expected b/go/ql/test/query-tests/Security/CWE-918/RequestForgery.expected
index 4e64101e82d7a..f575ad436dcf1 100644
--- a/go/ql/test/query-tests/Security/CWE-918/RequestForgery.expected
+++ b/go/ql/test/query-tests/Security/CWE-918/RequestForgery.expected
@@ -1,12 +1,12 @@
edges
-| RequestForgery.go:8:12:8:34 | call to FormValue | RequestForgery.go:11:24:11:65 | ...+... | provenance | Src:MaD:781 |
-| tst.go:10:13:10:35 | call to FormValue | tst.go:14:11:14:17 | tainted | provenance | Src:MaD:781 |
-| tst.go:10:13:10:35 | call to FormValue | tst.go:18:12:18:18 | tainted | provenance | Src:MaD:781 |
-| tst.go:10:13:10:35 | call to FormValue | tst.go:21:34:21:40 | tainted | provenance | Src:MaD:781 |
-| tst.go:10:13:10:35 | call to FormValue | tst.go:24:66:24:72 | tainted | provenance | Src:MaD:781 |
-| tst.go:10:13:10:35 | call to FormValue | tst.go:27:11:27:29 | ...+... | provenance | Src:MaD:781 |
-| tst.go:10:13:10:35 | call to FormValue | tst.go:29:11:29:40 | ...+... | provenance | Src:MaD:781 |
-| tst.go:10:13:10:35 | call to FormValue | tst.go:36:11:36:17 | tainted | provenance | Src:MaD:781 |
+| RequestForgery.go:8:12:8:34 | call to FormValue | RequestForgery.go:11:24:11:65 | ...+... | provenance | Src:MaD:790 |
+| tst.go:10:13:10:35 | call to FormValue | tst.go:14:11:14:17 | tainted | provenance | Src:MaD:790 |
+| tst.go:10:13:10:35 | call to FormValue | tst.go:18:12:18:18 | tainted | provenance | Src:MaD:790 |
+| tst.go:10:13:10:35 | call to FormValue | tst.go:21:34:21:40 | tainted | provenance | Src:MaD:790 |
+| tst.go:10:13:10:35 | call to FormValue | tst.go:24:66:24:72 | tainted | provenance | Src:MaD:790 |
+| tst.go:10:13:10:35 | call to FormValue | tst.go:27:11:27:29 | ...+... | provenance | Src:MaD:790 |
+| tst.go:10:13:10:35 | call to FormValue | tst.go:29:11:29:40 | ...+... | provenance | Src:MaD:790 |
+| tst.go:10:13:10:35 | call to FormValue | tst.go:36:11:36:17 | tainted | provenance | Src:MaD:790 |
| tst.go:35:2:35:2 | definition of u [pointer] | tst.go:36:2:36:2 | u [pointer] | provenance | |
| tst.go:36:2:36:2 | implicit dereference | tst.go:35:2:35:2 | definition of u [pointer] | provenance | |
| tst.go:36:2:36:2 | implicit dereference | tst.go:36:2:36:2 | u | provenance | |
@@ -18,15 +18,15 @@ edges
| tst.go:36:11:36:17 | tainted | tst.go:36:2:36:2 | u | provenance | Config |
| tst.go:36:11:36:17 | tainted | tst.go:37:11:37:11 | u | provenance | Config |
| tst.go:37:11:37:11 | u | tst.go:37:11:37:20 | call to String | provenance | MaD:238 |
-| websocket.go:60:21:60:31 | call to Referer | websocket.go:65:27:65:40 | untrustedInput | provenance | Src:MaD:784 |
-| websocket.go:74:21:74:31 | call to Referer | websocket.go:78:36:78:49 | untrustedInput | provenance | Src:MaD:784 |
-| websocket.go:88:21:88:31 | call to Referer | websocket.go:91:31:91:44 | untrustedInput | provenance | Src:MaD:784 |
-| websocket.go:107:21:107:31 | call to Referer | websocket.go:110:15:110:28 | untrustedInput | provenance | Src:MaD:784 |
-| websocket.go:126:21:126:31 | call to Referer | websocket.go:129:38:129:51 | untrustedInput | provenance | Src:MaD:784 |
-| websocket.go:154:21:154:31 | call to Referer | websocket.go:155:31:155:44 | untrustedInput | provenance | Src:MaD:784 |
-| websocket.go:160:21:160:31 | call to Referer | websocket.go:162:31:162:44 | untrustedInput | provenance | Src:MaD:784 |
-| websocket.go:195:21:195:31 | call to Referer | websocket.go:197:18:197:31 | untrustedInput | provenance | Src:MaD:784 |
-| websocket.go:202:21:202:31 | call to Referer | websocket.go:204:11:204:24 | untrustedInput | provenance | Src:MaD:784 |
+| websocket.go:60:21:60:31 | call to Referer | websocket.go:65:27:65:40 | untrustedInput | provenance | Src:MaD:793 |
+| websocket.go:74:21:74:31 | call to Referer | websocket.go:78:36:78:49 | untrustedInput | provenance | Src:MaD:793 |
+| websocket.go:88:21:88:31 | call to Referer | websocket.go:91:31:91:44 | untrustedInput | provenance | Src:MaD:793 |
+| websocket.go:107:21:107:31 | call to Referer | websocket.go:110:15:110:28 | untrustedInput | provenance | Src:MaD:793 |
+| websocket.go:126:21:126:31 | call to Referer | websocket.go:129:38:129:51 | untrustedInput | provenance | Src:MaD:793 |
+| websocket.go:154:21:154:31 | call to Referer | websocket.go:155:31:155:44 | untrustedInput | provenance | Src:MaD:793 |
+| websocket.go:160:21:160:31 | call to Referer | websocket.go:162:31:162:44 | untrustedInput | provenance | Src:MaD:793 |
+| websocket.go:195:21:195:31 | call to Referer | websocket.go:197:18:197:31 | untrustedInput | provenance | Src:MaD:793 |
+| websocket.go:202:21:202:31 | call to Referer | websocket.go:204:11:204:24 | untrustedInput | provenance | Src:MaD:793 |
nodes
| RequestForgery.go:8:12:8:34 | call to FormValue | semmle.label | call to FormValue |
| RequestForgery.go:11:24:11:65 | ...+... | semmle.label | ...+... |
From 94078e851ca471ebed2eef5de0526a67038b10b0 Mon Sep 17 00:00:00 2001
From: Anders Schack-Mulligen
Date: Thu, 18 Jul 2024 11:28:48 +0200
Subject: [PATCH 042/140] Shared: Add support for provenance pretty-printing as
a qltest postprocess step.
---
.../test/TestUtilities/PrettyPrintModels.ql | 18 +++++
.../security/CWE-078/ExecTainted.expected | 28 ++++----
.../security/CWE-078/ExecTainted.qlref | 3 +-
.../security/CWE-311/CWE-319/HttpsUrls.ql | 14 ----
.../security/CWE-311/CWE-319/HttpsUrls.qlref | 2 +
.../dataflow/test/ProvenancePathGraph.qll | 66 ++++++++++++++++---
6 files changed, 95 insertions(+), 36 deletions(-)
create mode 100644 java/ql/test/TestUtilities/PrettyPrintModels.ql
delete mode 100644 java/ql/test/query-tests/security/CWE-311/CWE-319/HttpsUrls.ql
create mode 100644 java/ql/test/query-tests/security/CWE-311/CWE-319/HttpsUrls.qlref
diff --git a/java/ql/test/TestUtilities/PrettyPrintModels.ql b/java/ql/test/TestUtilities/PrettyPrintModels.ql
new file mode 100644
index 0000000000000..79442c4439516
--- /dev/null
+++ b/java/ql/test/TestUtilities/PrettyPrintModels.ql
@@ -0,0 +1,18 @@
+/**
+ * @kind test-postprocess
+ */
+
+import codeql.dataflow.test.ProvenancePathGraph
+import semmle.code.java.dataflow.ExternalFlow
+
+external predicate queryResults(string relation, int row, int column, string data);
+
+external predicate queryRelations(string relation);
+
+query predicate resultRelations(string relation) { queryRelations(relation) }
+
+module Res = TranslateProvenanceResults;
+
+from string relation, int row, int column, string data
+where Res::results(relation, row, column, data)
+select relation, row, column, data
diff --git a/java/ql/test/query-tests/security/CWE-078/ExecTainted.expected b/java/ql/test/query-tests/security/CWE-078/ExecTainted.expected
index 6e71e15445406..8cff41743e99f 100644
--- a/java/ql/test/query-tests/security/CWE-078/ExecTainted.expected
+++ b/java/ql/test/query-tests/security/CWE-078/ExecTainted.expected
@@ -1,23 +1,33 @@
+#select
+| Test.java:7:44:7:69 | ... + ... | Test.java:57:27:57:39 | args : String[] | Test.java:7:25:7:70 | new ..[] { .. } | This command line depends on a $@. | Test.java:57:27:57:39 | args | user-provided value |
+| Test.java:10:29:10:74 | new String[] | Test.java:57:27:57:39 | args : String[] | Test.java:10:29:10:74 | new String[] | This command line depends on a $@. | Test.java:57:27:57:39 | args | user-provided value |
+| Test.java:18:29:18:31 | cmd | Test.java:57:27:57:39 | args : String[] | Test.java:18:29:18:31 | cmd | This command line depends on a $@. | Test.java:57:27:57:39 | args | user-provided value |
+| Test.java:24:29:24:32 | cmd1 | Test.java:57:27:57:39 | args : String[] | Test.java:24:29:24:32 | cmd1 | This command line depends on a $@. | Test.java:57:27:57:39 | args | user-provided value |
+| Test.java:29:44:29:64 | ... + ... | Test.java:57:27:57:39 | args : String[] | Test.java:29:25:29:65 | new ..[] { .. } | This command line depends on a $@. | Test.java:57:27:57:39 | args | user-provided value |
edges
| Test.java:6:35:6:44 | arg : String | Test.java:7:44:7:69 | ... + ... : String | provenance | |
| Test.java:6:35:6:44 | arg : String | Test.java:10:61:10:73 | ... + ... : String | provenance | |
| Test.java:6:35:6:44 | arg : String | Test.java:16:13:16:25 | ... + ... : String | provenance | |
| Test.java:6:35:6:44 | arg : String | Test.java:22:15:22:27 | ... + ... : String | provenance | |
-| Test.java:7:25:7:70 | new ..[] { .. } : String[] [[]] : String | Test.java:7:25:7:70 | new ..[] { .. } | provenance | Sink:MaD:42682 |
+| Test.java:7:25:7:70 | new ..[] { .. } : String[] [[]] : String | Test.java:7:25:7:70 | new ..[] { .. } | provenance | Sink:MaD:2 |
| Test.java:7:44:7:69 | ... + ... : String | Test.java:7:25:7:70 | new ..[] { .. } : String[] [[]] : String | provenance | |
-| Test.java:10:29:10:74 | {...} : String[] [[]] : String | Test.java:10:29:10:74 | new String[] | provenance | Sink:MaD:42682 |
+| Test.java:10:29:10:74 | {...} : String[] [[]] : String | Test.java:10:29:10:74 | new String[] | provenance | Sink:MaD:2 |
| Test.java:10:61:10:73 | ... + ... : String | Test.java:10:29:10:74 | {...} : String[] [[]] : String | provenance | |
-| Test.java:16:5:16:7 | cmd [post update] : ArrayList [] : String | Test.java:18:29:18:31 | cmd | provenance | Sink:MaD:42681 |
-| Test.java:16:13:16:25 | ... + ... : String | Test.java:16:5:16:7 | cmd [post update] : ArrayList [] : String | provenance | MaD:43744 |
-| Test.java:22:5:22:8 | cmd1 [post update] : String[] [[]] : String | Test.java:24:29:24:32 | cmd1 | provenance | Sink:MaD:42682 |
+| Test.java:16:5:16:7 | cmd [post update] : ArrayList [] : String | Test.java:18:29:18:31 | cmd | provenance | Sink:MaD:1 |
+| Test.java:16:13:16:25 | ... + ... : String | Test.java:16:5:16:7 | cmd [post update] : ArrayList [] : String | provenance | MaD:3 |
+| Test.java:22:5:22:8 | cmd1 [post update] : String[] [[]] : String | Test.java:24:29:24:32 | cmd1 | provenance | Sink:MaD:2 |
| Test.java:22:15:22:27 | ... + ... : String | Test.java:22:5:22:8 | cmd1 [post update] : String[] [[]] : String | provenance | |
| Test.java:28:38:28:47 | arg : String | Test.java:29:44:29:64 | ... + ... : String | provenance | |
-| Test.java:29:25:29:65 | new ..[] { .. } : String[] [[]] : String | Test.java:29:25:29:65 | new ..[] { .. } | provenance | Sink:MaD:42682 |
+| Test.java:29:25:29:65 | new ..[] { .. } : String[] [[]] : String | Test.java:29:25:29:65 | new ..[] { .. } | provenance | Sink:MaD:2 |
| Test.java:29:44:29:64 | ... + ... : String | Test.java:29:25:29:65 | new ..[] { .. } : String[] [[]] : String | provenance | |
| Test.java:57:27:57:39 | args : String[] | Test.java:60:20:60:22 | arg : String | provenance | |
| Test.java:57:27:57:39 | args : String[] | Test.java:61:23:61:25 | arg : String | provenance | |
| Test.java:60:20:60:22 | arg : String | Test.java:6:35:6:44 | arg : String | provenance | |
| Test.java:61:23:61:25 | arg : String | Test.java:28:38:28:47 | arg : String | provenance | |
+models
+| 1 | Sink: java.lang; ProcessBuilder; false; ProcessBuilder; (List); ; Argument[0]; command-injection; ai-manual |
+| 2 | Sink: java.lang; ProcessBuilder; false; ProcessBuilder; (String[]); ; Argument[0]; command-injection; ai-manual |
+| 3 | Summary: java.util; Collection; true; add; ; ; Argument[0]; Argument[this].Element; value; manual |
nodes
| Test.java:6:35:6:44 | arg : String | semmle.label | arg : String |
| Test.java:7:25:7:70 | new ..[] { .. } | semmle.label | new ..[] { .. } |
@@ -40,9 +50,3 @@ nodes
| Test.java:60:20:60:22 | arg : String | semmle.label | arg : String |
| Test.java:61:23:61:25 | arg : String | semmle.label | arg : String |
subpaths
-#select
-| Test.java:7:44:7:69 | ... + ... | Test.java:57:27:57:39 | args : String[] | Test.java:7:25:7:70 | new ..[] { .. } | This command line depends on a $@. | Test.java:57:27:57:39 | args | user-provided value |
-| Test.java:10:29:10:74 | new String[] | Test.java:57:27:57:39 | args : String[] | Test.java:10:29:10:74 | new String[] | This command line depends on a $@. | Test.java:57:27:57:39 | args | user-provided value |
-| Test.java:18:29:18:31 | cmd | Test.java:57:27:57:39 | args : String[] | Test.java:18:29:18:31 | cmd | This command line depends on a $@. | Test.java:57:27:57:39 | args | user-provided value |
-| Test.java:24:29:24:32 | cmd1 | Test.java:57:27:57:39 | args : String[] | Test.java:24:29:24:32 | cmd1 | This command line depends on a $@. | Test.java:57:27:57:39 | args | user-provided value |
-| Test.java:29:44:29:64 | ... + ... | Test.java:57:27:57:39 | args : String[] | Test.java:29:25:29:65 | new ..[] { .. } | This command line depends on a $@. | Test.java:57:27:57:39 | args | user-provided value |
diff --git a/java/ql/test/query-tests/security/CWE-078/ExecTainted.qlref b/java/ql/test/query-tests/security/CWE-078/ExecTainted.qlref
index 1de765a2fdf1f..2ab35baf1bdfc 100644
--- a/java/ql/test/query-tests/security/CWE-078/ExecTainted.qlref
+++ b/java/ql/test/query-tests/security/CWE-078/ExecTainted.qlref
@@ -1 +1,2 @@
-Security/CWE/CWE-078/ExecTainted.ql
+query: Security/CWE/CWE-078/ExecTainted.ql
+postprocess: TestUtilities/PrettyPrintModels.ql
diff --git a/java/ql/test/query-tests/security/CWE-311/CWE-319/HttpsUrls.ql b/java/ql/test/query-tests/security/CWE-311/CWE-319/HttpsUrls.ql
deleted file mode 100644
index 1175b67693961..0000000000000
--- a/java/ql/test/query-tests/security/CWE-311/CWE-319/HttpsUrls.ql
+++ /dev/null
@@ -1,14 +0,0 @@
-/**
- * @kind path-problem
- */
-
-import java
-import semmle.code.java.security.HttpsUrlsQuery
-import codeql.dataflow.test.ProvenancePathGraph
-import semmle.code.java.dataflow.ExternalFlow
-import ShowProvenance
-
-from HttpStringToUrlOpenMethodFlow::PathNode source, HttpStringToUrlOpenMethodFlow::PathNode sink
-where HttpStringToUrlOpenMethodFlow::flowPath(source, sink)
-select sink.getNode(), source, sink, "URL may have been constructed with HTTP protocol, using $@.",
- source.getNode(), "this HTTP URL"
diff --git a/java/ql/test/query-tests/security/CWE-311/CWE-319/HttpsUrls.qlref b/java/ql/test/query-tests/security/CWE-311/CWE-319/HttpsUrls.qlref
new file mode 100644
index 0000000000000..b05c8153ebe6e
--- /dev/null
+++ b/java/ql/test/query-tests/security/CWE-311/CWE-319/HttpsUrls.qlref
@@ -0,0 +1,2 @@
+query: Security/CWE/CWE-319/HttpsUrls.ql
+postprocess: TestUtilities/PrettyPrintModels.ql
diff --git a/shared/dataflow/codeql/dataflow/test/ProvenancePathGraph.qll b/shared/dataflow/codeql/dataflow/test/ProvenancePathGraph.qll
index 0b606dc98dcb1..8a5bdb15be55f 100644
--- a/shared/dataflow/codeql/dataflow/test/ProvenancePathGraph.qll
+++ b/shared/dataflow/codeql/dataflow/test/ProvenancePathGraph.qll
@@ -9,6 +9,8 @@ module;
signature predicate interpretModelForTestSig(QlBuiltins::ExtensionId madId, string model);
+signature predicate queryResultsSig(string relation, int row, int column, string data);
+
signature class PathNodeSig {
string toString();
}
@@ -28,14 +30,14 @@ signature module PathGraphSig {
predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out);
}
-/** Transforms a `PathGraph` by printing the provenance information. */
-module ShowProvenance<
- interpretModelForTestSig/2 interpretModelForTest, PathNodeSig PathNode,
- PathGraphSig PathGraph>
+private signature predicate provenanceSig(string model);
+
+private module TranslateModels<
+ interpretModelForTestSig/2 interpretModelForTest, provenanceSig/1 provenance>
{
private predicate madIds(string madId) {
exists(string model |
- PathGraph::edges(_, _, _, model) and
+ provenance(model) and
model.regexpFind("(?<=MaD:)[0-9]*", _, _) = madId
)
}
@@ -44,14 +46,15 @@ module ShowProvenance<
madId = rank[r](string madId0 | madIds(madId0) | madId0 order by madId0.toInt())
}
- query predicate models(int r, string model) {
+ /** Lists the renumbered and pretty-printed models used in the edges relation. */
+ predicate models(int r, string model) {
exists(QlBuiltins::ExtensionId madId |
rankedMadIds(madId.toString(), r) and interpretModelForTest(madId, model)
)
}
private predicate translateModelsPart(string model1, string model2, int i) {
- PathGraph::edges(_, _, _, model1) and
+ provenance(model1) and
exists(string s | model1.splitAt("MaD:", i) = s |
model2 = s and i = 0
or
@@ -65,17 +68,29 @@ module ShowProvenance<
)
}
- private predicate translateModels(string model1, string model2) {
+ predicate translateModels(string model1, string model2) {
exists(int i |
translateModelsPart(model1, model2, i) and
not translateModelsPart(model1, _, i + 1)
)
}
+}
+
+/** Transforms a `PathGraph` by printing the provenance information. */
+module ShowProvenance<
+ interpretModelForTestSig/2 interpretModelForTest, PathNodeSig PathNode,
+ PathGraphSig PathGraph>
+{
+ private predicate provenance(string model) { PathGraph::edges(_, _, _, model) }
+
+ private module Models = TranslateModels;
+
+ query predicate models(int r, string model) { Models::models(r, model) }
query predicate edges(PathNode a, PathNode b, string key, string val) {
exists(string model |
PathGraph::edges(a, b, key, model) and
- translateModels(model, val)
+ Models::translateModels(model, val)
)
}
@@ -83,3 +98,36 @@ module ShowProvenance<
query predicate subpaths = PathGraph::subpaths/4;
}
+
+/** Transforms a `PathGraph` by printing the provenance information. */
+module TranslateProvenanceResults<
+ interpretModelForTestSig/2 interpretModelForTest, queryResultsSig/4 queryResults>
+{
+ private int provenanceColumn() { result = 5 }
+
+ private predicate provenance(string model) { queryResults("edges", _, provenanceColumn(), model) }
+
+ private module Models = TranslateModels;
+
+ predicate results(string relation, int row, int column, string data) {
+ queryResults(relation, row, column, data) and
+ (relation != "edges" or column != provenanceColumn())
+ or
+ exists(string model |
+ relation = "edges" and
+ column = provenanceColumn() and
+ queryResults(relation, row, column, model) and
+ Models::translateModels(model, data)
+ )
+ or
+ exists(int r, string model |
+ Models::models(r, model) and
+ relation = "models" and
+ row = r
+ |
+ column = 0 and data = r.toString()
+ or
+ column = 1 and data = model
+ )
+ }
+}
From 3badd61a56d00a31804209b27b295d1b0707a021 Mon Sep 17 00:00:00 2001
From: Cornelius Riemenschneider
Date: Thu, 18 Jul 2024 16:36:11 +0200
Subject: [PATCH 043/140] Integration tests: port to pytest.
Requires an internal PR.
---
.../internal-error/diagnostics.expected | 27 +++++++++----------
.../diagnostics/internal-error/test.py | 9 ++-----
.../diagnostics/syntax-error/test.py | 9 ++-----
.../all-platforms/no-types/test.py | 6 +++--
.../all-platforms/qlpack.yml | 4 ---
javascript/ql/integration-tests/legacy | 1 -
6 files changed, 21 insertions(+), 35 deletions(-)
delete mode 100644 javascript/ql/integration-tests/all-platforms/qlpack.yml
delete mode 100644 javascript/ql/integration-tests/legacy
diff --git a/javascript/ql/integration-tests/all-platforms/diagnostics/internal-error/diagnostics.expected b/javascript/ql/integration-tests/all-platforms/diagnostics/internal-error/diagnostics.expected
index 72108d0ebb540..54ac43a4ad745 100644
--- a/javascript/ql/integration-tests/all-platforms/diagnostics/internal-error/diagnostics.expected
+++ b/javascript/ql/integration-tests/all-platforms/diagnostics/internal-error/diagnostics.expected
@@ -1,15 +1,14 @@
{
- "timestamp": "2023-03-23T12:04:41.317+00:00",
- "source": {
- "id": "js/internal-error",
- "name": "Internal error",
- "extractorName": "javascript"
- },
- "markdownMessage": "Internal error: com.semmle.util.exception.CatastrophicError: The TypeScript parser wrapper crashed with exit code 1",
- "severity": "unknown",
- "visibility": {
- "cliSummaryTable": true,
- "statusPage": false,
- "telemetry": true
- }
-}
\ No newline at end of file
+ "markdownMessage": "Internal error: com.semmle.util.exception.CatastrophicError: The TypeScript parser wrapper crashed with exit code 1",
+ "severity": "unknown",
+ "source": {
+ "extractorName": "javascript",
+ "id": "js/internal-error",
+ "name": "Internal error"
+ },
+ "visibility": {
+ "cliSummaryTable": true,
+ "statusPage": false,
+ "telemetry": true
+ }
+}
diff --git a/javascript/ql/integration-tests/all-platforms/diagnostics/internal-error/test.py b/javascript/ql/integration-tests/all-platforms/diagnostics/internal-error/test.py
index 3f6c33bf31c1d..25a95e763ee81 100644
--- a/javascript/ql/integration-tests/all-platforms/diagnostics/internal-error/test.py
+++ b/javascript/ql/integration-tests/all-platforms/diagnostics/internal-error/test.py
@@ -1,7 +1,2 @@
-import os
-from create_database_utils import *
-from diagnostics_test_utils import *
-
-run_codeql_database_create([], lang="javascript", runFunction = runUnsuccessfully, db = None)
-
-check_diagnostics()
+def test(codeql, javascript):
+ codeql.database.create(_assert_failure=True)
diff --git a/javascript/ql/integration-tests/all-platforms/diagnostics/syntax-error/test.py b/javascript/ql/integration-tests/all-platforms/diagnostics/syntax-error/test.py
index 886c058d8f5a6..382607f69a73a 100644
--- a/javascript/ql/integration-tests/all-platforms/diagnostics/syntax-error/test.py
+++ b/javascript/ql/integration-tests/all-platforms/diagnostics/syntax-error/test.py
@@ -1,7 +1,2 @@
-import os
-from create_database_utils import *
-from diagnostics_test_utils import *
-
-run_codeql_database_create([], lang="javascript", runFunction = runSuccessfully, db = None)
-
-check_diagnostics()
+def test(codeql, javascript):
+ codeql.database.create()
diff --git a/javascript/ql/integration-tests/all-platforms/no-types/test.py b/javascript/ql/integration-tests/all-platforms/no-types/test.py
index 12ea27fbc0ccc..a9c8a17a4a3fa 100755
--- a/javascript/ql/integration-tests/all-platforms/no-types/test.py
+++ b/javascript/ql/integration-tests/all-platforms/no-types/test.py
@@ -1,3 +1,5 @@
-from create_database_utils import *
+# from create_database_utils import *
-run_codeql_database_create([], lang="javascript", extra_args=["-Oskip_types=true"])
+# run_codeql_database_create([], lang="javascript", extra_args=["-Oskip_types=true"])
+def test(codeql, javascript):
+ codeql.database.create(extractor_option="skip_types=true")
diff --git a/javascript/ql/integration-tests/all-platforms/qlpack.yml b/javascript/ql/integration-tests/all-platforms/qlpack.yml
deleted file mode 100644
index 9f076584585a9..0000000000000
--- a/javascript/ql/integration-tests/all-platforms/qlpack.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-dependencies:
- codeql/javascript-all: '*'
- codeql/javascript-queries: '*'
-warnOnImplicitThis: true
diff --git a/javascript/ql/integration-tests/legacy b/javascript/ql/integration-tests/legacy
deleted file mode 100644
index 52478f0a7ef58..0000000000000
--- a/javascript/ql/integration-tests/legacy
+++ /dev/null
@@ -1 +0,0 @@
-These tests are still run with the legacy test runner
From 3bd330423de0db6351a5c5c47430d7cc715e6d55 Mon Sep 17 00:00:00 2001
From: Ed Minnix
Date: Tue, 16 Jul 2024 14:40:40 -0400
Subject: [PATCH 044/140] Add some models for the `org.lastaflute.web` library
Methods annotated `@Execute` are handlers for URLs. Therefore, the
parameters of the methods annotated with the
`org.lastaflute.web.Execute` annotation are likely either URL parameters
or forms.
---
...rg.lastaflute.web.ruts.multipart.model.yml | 9 ++++++++
.../semmle/code/java/dataflow/FlowSources.qll | 1 +
.../code/java/frameworks/Lastaflute.qll | 22 +++++++++++++++++++
3 files changed, 32 insertions(+)
create mode 100644 java/ql/lib/ext/org.lastaflute.web.ruts.multipart.model.yml
create mode 100644 java/ql/lib/semmle/code/java/frameworks/Lastaflute.qll
diff --git a/java/ql/lib/ext/org.lastaflute.web.ruts.multipart.model.yml b/java/ql/lib/ext/org.lastaflute.web.ruts.multipart.model.yml
new file mode 100644
index 0000000000000..994f4c36a55f3
--- /dev/null
+++ b/java/ql/lib/ext/org.lastaflute.web.ruts.multipart.model.yml
@@ -0,0 +1,9 @@
+extensions:
+ - addsTo:
+ pack: codeql/java-all
+ extensible: summaryModel
+ data:
+ - ["org.lastaflute.web.ruts.multipart", "MultipartFormFile", True, "getContentType", "()", "", "Argument[this]", "ReturnValue", "taint", "manual"]
+ - ["org.lastaflute.web.ruts.multipart", "MultipartFormFile", True, "getFileData", "()", "", "Argument[this]", "ReturnValue", "taint", "manual"]
+ - ["org.lastaflute.web.ruts.multipart", "MultipartFormFile", True, "getFileName", "()", "", "Argument[this]", "ReturnValue", "taint", "manual"]
+ - ["org.lastaflute.web.ruts.multipart", "MultipartFormFile", True, "getInputStream", "()", "", "Argument[this]", "ReturnValue", "taint", "manual"]
\ No newline at end of file
diff --git a/java/ql/lib/semmle/code/java/dataflow/FlowSources.qll b/java/ql/lib/semmle/code/java/dataflow/FlowSources.qll
index f2b2f8c20086b..6f9bd30647f2b 100644
--- a/java/ql/lib/semmle/code/java/dataflow/FlowSources.qll
+++ b/java/ql/lib/semmle/code/java/dataflow/FlowSources.qll
@@ -20,6 +20,7 @@ import semmle.code.java.frameworks.android.Android
import semmle.code.java.frameworks.android.ExternalStorage
import semmle.code.java.frameworks.android.OnActivityResultSource
import semmle.code.java.frameworks.android.Intent
+private import semmle.code.java.frameworks.Lastaflute
import semmle.code.java.frameworks.play.Play
import semmle.code.java.frameworks.spring.SpringWeb
import semmle.code.java.frameworks.spring.SpringController
diff --git a/java/ql/lib/semmle/code/java/frameworks/Lastaflute.qll b/java/ql/lib/semmle/code/java/frameworks/Lastaflute.qll
new file mode 100644
index 0000000000000..822243cdc6ebe
--- /dev/null
+++ b/java/ql/lib/semmle/code/java/frameworks/Lastaflute.qll
@@ -0,0 +1,22 @@
+import java
+import semmle.code.java.dataflow.FlowSources
+
+/**
+ * The `org.lastaflute.web.Execute` annotation.
+ */
+class LastafluteExecuteAnnotation extends Annotation {
+ LastafluteExecuteAnnotation() { this.getType().hasQualifiedName("org.lastaflute.web", "Execute") }
+}
+
+/**
+ * The parameter of a method defining a URL handler using the Lastaflute framework.
+ */
+class LastafluteHandlerParameterSource extends RemoteFlowSource {
+ LastafluteHandlerParameterSource() {
+ exists(Parameter p | p.getCallable().getAnAnnotation() instanceof LastafluteExecuteAnnotation |
+ p = this.asParameter()
+ )
+ }
+
+ override string getSourceType() { result = "Lastaflute handler parameter" }
+}
From 62944ee473641cec521bdbec0c1286cb422a3faa Mon Sep 17 00:00:00 2001
From: Ed Minnix
Date: Tue, 16 Jul 2024 15:52:51 -0400
Subject: [PATCH 045/140] Add tests for lastaflute framework
---
.../frameworks/lastaflute/Test.java | 27 +++++++++++++++++++
.../frameworks/lastaflute/options | 1 +
.../frameworks/lastaflute/test.expected | 0
.../frameworks/lastaflute/test.ql | 11 ++++++++
.../org/lastaflute/web/Execute.java | 5 ++++
.../web/ruts/multipart/MultipartFormFile.java | 14 ++++++++++
6 files changed, 58 insertions(+)
create mode 100644 java/ql/test/library-tests/frameworks/lastaflute/Test.java
create mode 100644 java/ql/test/library-tests/frameworks/lastaflute/options
create mode 100644 java/ql/test/library-tests/frameworks/lastaflute/test.expected
create mode 100644 java/ql/test/library-tests/frameworks/lastaflute/test.ql
create mode 100644 java/ql/test/stubs/lastaflute/org/lastaflute/web/Execute.java
create mode 100644 java/ql/test/stubs/lastaflute/org/lastaflute/web/ruts/multipart/MultipartFormFile.java
diff --git a/java/ql/test/library-tests/frameworks/lastaflute/Test.java b/java/ql/test/library-tests/frameworks/lastaflute/Test.java
new file mode 100644
index 0000000000000..a10f4ebbdaaa6
--- /dev/null
+++ b/java/ql/test/library-tests/frameworks/lastaflute/Test.java
@@ -0,0 +1,27 @@
+import java.io.IOException;
+
+import org.lastaflute.web.Execute;
+import org.lastaflute.web.ruts.multipart.MultipartFormFile;
+
+public class Test {
+
+ void sink(Object o) {
+ }
+
+ public class TestForm {
+ public MultipartFormFile file;
+ }
+
+ @Execute
+ public String index(TestForm form) throws IOException {
+ MultipartFormFile file = form.file;
+
+ sink(file.getFileData()); // $hasTaintFlow
+ sink(file.getInputStream()); // $hasTaintFlow
+
+ return "index.jsp";
+ }
+
+}
+
+
diff --git a/java/ql/test/library-tests/frameworks/lastaflute/options b/java/ql/test/library-tests/frameworks/lastaflute/options
new file mode 100644
index 0000000000000..439b07f08ed2d
--- /dev/null
+++ b/java/ql/test/library-tests/frameworks/lastaflute/options
@@ -0,0 +1 @@
+//semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/lastaflute
\ No newline at end of file
diff --git a/java/ql/test/library-tests/frameworks/lastaflute/test.expected b/java/ql/test/library-tests/frameworks/lastaflute/test.expected
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git a/java/ql/test/library-tests/frameworks/lastaflute/test.ql b/java/ql/test/library-tests/frameworks/lastaflute/test.ql
new file mode 100644
index 0000000000000..a62fdf67dfcf6
--- /dev/null
+++ b/java/ql/test/library-tests/frameworks/lastaflute/test.ql
@@ -0,0 +1,11 @@
+import java
+import semmle.code.java.dataflow.FlowSources
+import TestUtilities.InlineFlowTest
+
+module Config implements DataFlow::ConfigSig {
+ predicate isSource(DataFlow::Node n) { n instanceof RemoteFlowSource }
+
+ predicate isSink(DataFlow::Node n) { DefaultFlowConfig::isSink(n) }
+}
+
+import TaintFlowTest
diff --git a/java/ql/test/stubs/lastaflute/org/lastaflute/web/Execute.java b/java/ql/test/stubs/lastaflute/org/lastaflute/web/Execute.java
new file mode 100644
index 0000000000000..3765a03e15e9f
--- /dev/null
+++ b/java/ql/test/stubs/lastaflute/org/lastaflute/web/Execute.java
@@ -0,0 +1,5 @@
+package org.lastaflute.web;
+
+public @interface Execute {
+
+}
diff --git a/java/ql/test/stubs/lastaflute/org/lastaflute/web/ruts/multipart/MultipartFormFile.java b/java/ql/test/stubs/lastaflute/org/lastaflute/web/ruts/multipart/MultipartFormFile.java
new file mode 100644
index 0000000000000..af4626df670af
--- /dev/null
+++ b/java/ql/test/stubs/lastaflute/org/lastaflute/web/ruts/multipart/MultipartFormFile.java
@@ -0,0 +1,14 @@
+package org.lastaflute.web.ruts.multipart;
+
+import java.io.InputStream;
+import java.io.IOException;
+
+public interface MultipartFormFile {
+ byte[] getFileData() throws IOException;
+
+ InputStream getInputStream() throws IOException;
+
+ String getFileName();
+
+ String getContentType();
+}
From 4fa45bb81ceb7557aef72ad8d2aadcb6ee6fc46c Mon Sep 17 00:00:00 2001
From: Ed Minnix
Date: Tue, 16 Jul 2024 16:25:14 -0400
Subject: [PATCH 046/140] Change note
---
.../2024-07-16-add-models-for-the-lastaflute-framework.md | 4 ++++
1 file changed, 4 insertions(+)
create mode 100644 java/ql/lib/change-notes/2024-07-16-add-models-for-the-lastaflute-framework.md
diff --git a/java/ql/lib/change-notes/2024-07-16-add-models-for-the-lastaflute-framework.md b/java/ql/lib/change-notes/2024-07-16-add-models-for-the-lastaflute-framework.md
new file mode 100644
index 0000000000000..b5f924cdb6767
--- /dev/null
+++ b/java/ql/lib/change-notes/2024-07-16-add-models-for-the-lastaflute-framework.md
@@ -0,0 +1,4 @@
+---
+category: minorAnalysis
+---
+* Adds models for request handlers using the `org.lastaflute.web` web framework.
From 971355144872f5ba0f55f699d25135fca4a0cedf Mon Sep 17 00:00:00 2001
From: Ed Minnix
Date: Tue, 16 Jul 2024 16:37:49 -0400
Subject: [PATCH 047/140] Missing QLDoc
---
java/ql/lib/semmle/code/java/frameworks/Lastaflute.qll | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/java/ql/lib/semmle/code/java/frameworks/Lastaflute.qll b/java/ql/lib/semmle/code/java/frameworks/Lastaflute.qll
index 822243cdc6ebe..76b7a5546df68 100644
--- a/java/ql/lib/semmle/code/java/frameworks/Lastaflute.qll
+++ b/java/ql/lib/semmle/code/java/frameworks/Lastaflute.qll
@@ -1,3 +1,7 @@
+/**
+ * Provides classes and predicates for working with the Lastaflute web framework.
+ */
+
import java
import semmle.code.java.dataflow.FlowSources
From 0990a370c761337f7280b81b404a801962703fce Mon Sep 17 00:00:00 2001
From: Ed Minnix
Date: Thu, 18 Jul 2024 17:39:51 -0400
Subject: [PATCH 048/140] Convert QL classes for Lastaflute to MaD
---
java/ql/lib/ext/org.lastaflute.web.model.yml | 6 +++++
.../semmle/code/java/dataflow/FlowSources.qll | 1 -
.../code/java/frameworks/Lastaflute.qll | 26 -------------------
3 files changed, 6 insertions(+), 27 deletions(-)
create mode 100644 java/ql/lib/ext/org.lastaflute.web.model.yml
delete mode 100644 java/ql/lib/semmle/code/java/frameworks/Lastaflute.qll
diff --git a/java/ql/lib/ext/org.lastaflute.web.model.yml b/java/ql/lib/ext/org.lastaflute.web.model.yml
new file mode 100644
index 0000000000000..cecb87bcfbdba
--- /dev/null
+++ b/java/ql/lib/ext/org.lastaflute.web.model.yml
@@ -0,0 +1,6 @@
+extensions:
+ - addsTo:
+ pack: codeql/java-all
+ extensible: sourceModel
+ data:
+ - ["org.lastaflute.web", "Execute", False, "", "", "Annotated", "Parameter", "remote", "manual"]
\ No newline at end of file
diff --git a/java/ql/lib/semmle/code/java/dataflow/FlowSources.qll b/java/ql/lib/semmle/code/java/dataflow/FlowSources.qll
index 6f9bd30647f2b..f2b2f8c20086b 100644
--- a/java/ql/lib/semmle/code/java/dataflow/FlowSources.qll
+++ b/java/ql/lib/semmle/code/java/dataflow/FlowSources.qll
@@ -20,7 +20,6 @@ import semmle.code.java.frameworks.android.Android
import semmle.code.java.frameworks.android.ExternalStorage
import semmle.code.java.frameworks.android.OnActivityResultSource
import semmle.code.java.frameworks.android.Intent
-private import semmle.code.java.frameworks.Lastaflute
import semmle.code.java.frameworks.play.Play
import semmle.code.java.frameworks.spring.SpringWeb
import semmle.code.java.frameworks.spring.SpringController
diff --git a/java/ql/lib/semmle/code/java/frameworks/Lastaflute.qll b/java/ql/lib/semmle/code/java/frameworks/Lastaflute.qll
deleted file mode 100644
index 76b7a5546df68..0000000000000
--- a/java/ql/lib/semmle/code/java/frameworks/Lastaflute.qll
+++ /dev/null
@@ -1,26 +0,0 @@
-/**
- * Provides classes and predicates for working with the Lastaflute web framework.
- */
-
-import java
-import semmle.code.java.dataflow.FlowSources
-
-/**
- * The `org.lastaflute.web.Execute` annotation.
- */
-class LastafluteExecuteAnnotation extends Annotation {
- LastafluteExecuteAnnotation() { this.getType().hasQualifiedName("org.lastaflute.web", "Execute") }
-}
-
-/**
- * The parameter of a method defining a URL handler using the Lastaflute framework.
- */
-class LastafluteHandlerParameterSource extends RemoteFlowSource {
- LastafluteHandlerParameterSource() {
- exists(Parameter p | p.getCallable().getAnAnnotation() instanceof LastafluteExecuteAnnotation |
- p = this.asParameter()
- )
- }
-
- override string getSourceType() { result = "Lastaflute handler parameter" }
-}
From ad4bca99751b8ff6d44ea9e86e920906794acc66 Mon Sep 17 00:00:00 2001
From: Ed Minnix
Date: Thu, 18 Jul 2024 18:18:24 -0400
Subject: [PATCH 049/140] Fix provenance in tests
---
.../CWE-601/SpringUrlRedirect.expected | 12 +++----
.../security/CWE-090/LdapInjection.expected | 36 +++++++++----------
2 files changed, 24 insertions(+), 24 deletions(-)
diff --git a/java/ql/test/experimental/query-tests/security/CWE-601/SpringUrlRedirect.expected b/java/ql/test/experimental/query-tests/security/CWE-601/SpringUrlRedirect.expected
index 9b1f0897b5656..b17be2a3db256 100644
--- a/java/ql/test/experimental/query-tests/security/CWE-601/SpringUrlRedirect.expected
+++ b/java/ql/test/experimental/query-tests/security/CWE-601/SpringUrlRedirect.expected
@@ -19,18 +19,18 @@ edges
| SpringUrlRedirect.java:104:39:104:56 | redirectUrl : String | SpringUrlRedirect.java:106:37:106:47 | redirectUrl : String | provenance | |
| SpringUrlRedirect.java:106:9:106:19 | httpHeaders [post update] : HttpHeaders | SpringUrlRedirect.java:108:68:108:78 | httpHeaders | provenance | |
| SpringUrlRedirect.java:106:9:106:19 | httpHeaders [post update] : HttpHeaders [, ] : String | SpringUrlRedirect.java:108:68:108:78 | httpHeaders | provenance | |
-| SpringUrlRedirect.java:106:37:106:47 | redirectUrl : String | SpringUrlRedirect.java:106:9:106:19 | httpHeaders [post update] : HttpHeaders | provenance | MaD:49240 |
-| SpringUrlRedirect.java:106:37:106:47 | redirectUrl : String | SpringUrlRedirect.java:106:9:106:19 | httpHeaders [post update] : HttpHeaders [, ] : String | provenance | MaD:49481 |
+| SpringUrlRedirect.java:106:37:106:47 | redirectUrl : String | SpringUrlRedirect.java:106:9:106:19 | httpHeaders [post update] : HttpHeaders | provenance | MaD:49245 |
+| SpringUrlRedirect.java:106:37:106:47 | redirectUrl : String | SpringUrlRedirect.java:106:9:106:19 | httpHeaders [post update] : HttpHeaders [, ] : String | provenance | MaD:49486 |
| SpringUrlRedirect.java:112:39:112:56 | redirectUrl : String | SpringUrlRedirect.java:114:37:114:47 | redirectUrl : String | provenance | |
| SpringUrlRedirect.java:114:9:114:19 | httpHeaders [post update] : HttpHeaders | SpringUrlRedirect.java:116:37:116:47 | httpHeaders | provenance | |
| SpringUrlRedirect.java:114:9:114:19 | httpHeaders [post update] : HttpHeaders [, ] : String | SpringUrlRedirect.java:116:37:116:47 | httpHeaders | provenance | |
-| SpringUrlRedirect.java:114:37:114:47 | redirectUrl : String | SpringUrlRedirect.java:114:9:114:19 | httpHeaders [post update] : HttpHeaders | provenance | MaD:49240 |
-| SpringUrlRedirect.java:114:37:114:47 | redirectUrl : String | SpringUrlRedirect.java:114:9:114:19 | httpHeaders [post update] : HttpHeaders [, ] : String | provenance | MaD:49481 |
+| SpringUrlRedirect.java:114:37:114:47 | redirectUrl : String | SpringUrlRedirect.java:114:9:114:19 | httpHeaders [post update] : HttpHeaders | provenance | MaD:49245 |
+| SpringUrlRedirect.java:114:37:114:47 | redirectUrl : String | SpringUrlRedirect.java:114:9:114:19 | httpHeaders [post update] : HttpHeaders [, ] : String | provenance | MaD:49486 |
| SpringUrlRedirect.java:120:33:120:50 | redirectUrl : String | SpringUrlRedirect.java:122:37:122:47 | redirectUrl : String | provenance | |
| SpringUrlRedirect.java:122:9:122:19 | httpHeaders [post update] : HttpHeaders | SpringUrlRedirect.java:124:49:124:59 | httpHeaders | provenance | |
| SpringUrlRedirect.java:122:9:122:19 | httpHeaders [post update] : HttpHeaders [, ] : String | SpringUrlRedirect.java:124:49:124:59 | httpHeaders | provenance | |
-| SpringUrlRedirect.java:122:37:122:47 | redirectUrl : String | SpringUrlRedirect.java:122:9:122:19 | httpHeaders [post update] : HttpHeaders | provenance | MaD:49240 |
-| SpringUrlRedirect.java:122:37:122:47 | redirectUrl : String | SpringUrlRedirect.java:122:9:122:19 | httpHeaders [post update] : HttpHeaders [, ] : String | provenance | MaD:49481 |
+| SpringUrlRedirect.java:122:37:122:47 | redirectUrl : String | SpringUrlRedirect.java:122:9:122:19 | httpHeaders [post update] : HttpHeaders | provenance | MaD:49245 |
+| SpringUrlRedirect.java:122:37:122:47 | redirectUrl : String | SpringUrlRedirect.java:122:9:122:19 | httpHeaders [post update] : HttpHeaders [, ] : String | provenance | MaD:49486 |
| SpringUrlRedirect.java:128:33:128:50 | redirectUrl : String | SpringUrlRedirect.java:130:44:130:54 | redirectUrl : String | provenance | |
| SpringUrlRedirect.java:130:9:130:19 | httpHeaders : HttpHeaders | SpringUrlRedirect.java:132:49:132:59 | httpHeaders | provenance | |
| SpringUrlRedirect.java:130:33:130:55 | create(...) : URI | SpringUrlRedirect.java:130:9:130:19 | httpHeaders : HttpHeaders | provenance | Config |
diff --git a/java/ql/test/query-tests/security/CWE-090/LdapInjection.expected b/java/ql/test/query-tests/security/CWE-090/LdapInjection.expected
index 5bc7b07286c76..0e603bfc7caab 100644
--- a/java/ql/test/query-tests/security/CWE-090/LdapInjection.expected
+++ b/java/ql/test/query-tests/security/CWE-090/LdapInjection.expected
@@ -90,50 +90,50 @@ edges
| LdapInjection.java:196:32:196:78 | uBadSearchRequestSetFilter : String | LdapInjection.java:199:17:199:42 | uBadSearchRequestSetFilter : String | provenance | |
| LdapInjection.java:199:5:199:5 | s : SearchRequest | LdapInjection.java:200:14:200:14 | s | provenance | Sink:MaD:1933 |
| LdapInjection.java:199:17:199:42 | uBadSearchRequestSetFilter : String | LdapInjection.java:199:5:199:5 | s : SearchRequest | provenance | Config |
-| LdapInjection.java:229:30:229:54 | sBad : String | LdapInjection.java:230:36:230:55 | ... + ... | provenance | Sink:MaD:49370 |
-| LdapInjection.java:229:57:229:83 | sBadDN : String | LdapInjection.java:230:14:230:33 | ... + ... | provenance | Sink:MaD:49370 |
-| LdapInjection.java:234:30:234:54 | sBad : String | LdapInjection.java:235:88:235:107 | ... + ... | provenance | Sink:MaD:49360 |
+| LdapInjection.java:229:30:229:54 | sBad : String | LdapInjection.java:230:36:230:55 | ... + ... | provenance | Sink:MaD:49375 |
+| LdapInjection.java:229:57:229:83 | sBadDN : String | LdapInjection.java:230:14:230:33 | ... + ... | provenance | Sink:MaD:49375 |
+| LdapInjection.java:234:30:234:54 | sBad : String | LdapInjection.java:235:88:235:107 | ... + ... | provenance | Sink:MaD:49365 |
| LdapInjection.java:234:57:234:92 | sBadDNLNBuilder : String | LdapInjection.java:235:48:235:76 | ... + ... : String | provenance | |
-| LdapInjection.java:235:20:235:77 | newInstance(...) : LdapNameBuilder | LdapInjection.java:235:20:235:85 | build(...) | provenance | Config Sink:MaD:49360 |
+| LdapInjection.java:235:20:235:77 | newInstance(...) : LdapNameBuilder | LdapInjection.java:235:20:235:85 | build(...) | provenance | Config Sink:MaD:49365 |
| LdapInjection.java:235:48:235:76 | ... + ... : String | LdapInjection.java:235:20:235:77 | newInstance(...) : LdapNameBuilder | provenance | Config |
-| LdapInjection.java:239:30:239:54 | sBad : String | LdapInjection.java:240:100:240:119 | ... + ... | provenance | Sink:MaD:49372 |
+| LdapInjection.java:239:30:239:54 | sBad : String | LdapInjection.java:240:100:240:119 | ... + ... | provenance | Sink:MaD:49377 |
| LdapInjection.java:239:57:239:95 | sBadDNLNBuilderAdd : String | LdapInjection.java:240:57:240:88 | ... + ... : String | provenance | |
-| LdapInjection.java:240:23:240:89 | add(...) : LdapNameBuilder | LdapInjection.java:240:23:240:97 | build(...) | provenance | Config Sink:MaD:49357 |
-| LdapInjection.java:240:23:240:89 | add(...) : LdapNameBuilder | LdapInjection.java:240:23:240:97 | build(...) | provenance | Config Sink:MaD:49372 |
+| LdapInjection.java:240:23:240:89 | add(...) : LdapNameBuilder | LdapInjection.java:240:23:240:97 | build(...) | provenance | Config Sink:MaD:49362 |
+| LdapInjection.java:240:23:240:89 | add(...) : LdapNameBuilder | LdapInjection.java:240:23:240:97 | build(...) | provenance | Config Sink:MaD:49377 |
| LdapInjection.java:240:57:240:88 | ... + ... : String | LdapInjection.java:240:23:240:89 | add(...) : LdapNameBuilder | provenance | Config |
| LdapInjection.java:244:30:244:63 | sBadLdapQuery : String | LdapInjection.java:245:47:245:75 | ... + ... : String | provenance | |
-| LdapInjection.java:245:47:245:75 | ... + ... : String | LdapInjection.java:245:15:245:76 | filter(...) | provenance | Config Sink:MaD:49369 |
+| LdapInjection.java:245:47:245:75 | ... + ... : String | LdapInjection.java:245:15:245:76 | filter(...) | provenance | Config Sink:MaD:49374 |
| LdapInjection.java:249:30:249:60 | sBadFilter : String | LdapInjection.java:250:86:250:111 | ... + ... : String | provenance | |
| LdapInjection.java:249:63:249:98 | sBadDNLdapUtils : String | LdapInjection.java:250:34:250:62 | ... + ... : String | provenance | |
-| LdapInjection.java:250:34:250:62 | ... + ... : String | LdapInjection.java:250:12:250:63 | newLdapName(...) | provenance | Config Sink:MaD:49368 |
-| LdapInjection.java:250:86:250:111 | ... + ... : String | LdapInjection.java:250:66:250:112 | new HardcodedFilter(...) | provenance | Config Sink:MaD:49368 |
+| LdapInjection.java:250:34:250:62 | ... + ... : String | LdapInjection.java:250:12:250:63 | newLdapName(...) | provenance | Config Sink:MaD:49373 |
+| LdapInjection.java:250:86:250:111 | ... + ... : String | LdapInjection.java:250:66:250:112 | new HardcodedFilter(...) | provenance | Config Sink:MaD:49373 |
| LdapInjection.java:254:30:254:63 | sBadLdapQuery : String | LdapInjection.java:255:56:255:84 | ... + ... : String | provenance | |
-| LdapInjection.java:255:56:255:84 | ... + ... : String | LdapInjection.java:255:24:255:85 | filter(...) | provenance | Config Sink:MaD:49371 |
+| LdapInjection.java:255:56:255:84 | ... + ... : String | LdapInjection.java:255:24:255:85 | filter(...) | provenance | Config Sink:MaD:49376 |
| LdapInjection.java:259:30:259:64 | sBadLdapQuery2 : String | LdapInjection.java:260:51:260:80 | ... + ... : String | provenance | |
-| LdapInjection.java:260:19:260:81 | filter(...) : LdapQuery | LdapInjection.java:261:24:261:24 | q | provenance | Sink:MaD:49371 |
+| LdapInjection.java:260:19:260:81 | filter(...) : LdapQuery | LdapInjection.java:261:24:261:24 | q | provenance | Sink:MaD:49376 |
| LdapInjection.java:260:51:260:80 | ... + ... : String | LdapInjection.java:260:19:260:81 | filter(...) : LdapQuery | provenance | Config |
| LdapInjection.java:265:30:265:73 | sBadLdapQueryWithFilter : String | LdapInjection.java:266:76:266:114 | ... + ... : String | provenance | |
-| LdapInjection.java:266:56:266:115 | new HardcodedFilter(...) : HardcodedFilter | LdapInjection.java:266:24:266:116 | filter(...) | provenance | Config Sink:MaD:49371 |
+| LdapInjection.java:266:56:266:115 | new HardcodedFilter(...) : HardcodedFilter | LdapInjection.java:266:24:266:116 | filter(...) | provenance | Config Sink:MaD:49376 |
| LdapInjection.java:266:76:266:114 | ... + ... : String | LdapInjection.java:266:56:266:115 | new HardcodedFilter(...) : HardcodedFilter | provenance | Config |
| LdapInjection.java:270:30:270:74 | sBadLdapQueryWithFilter2 : String | LdapInjection.java:271:68:271:107 | ... + ... : String | provenance | |
| LdapInjection.java:271:48:271:108 | new HardcodedFilter(...) : HardcodedFilter | LdapInjection.java:272:56:272:56 | f : HardcodedFilter | provenance | |
| LdapInjection.java:271:68:271:107 | ... + ... : String | LdapInjection.java:271:48:271:108 | new HardcodedFilter(...) : HardcodedFilter | provenance | Config |
-| LdapInjection.java:272:56:272:56 | f : HardcodedFilter | LdapInjection.java:272:24:272:57 | filter(...) | provenance | Config Sink:MaD:49371 |
+| LdapInjection.java:272:56:272:56 | f : HardcodedFilter | LdapInjection.java:272:24:272:57 | filter(...) | provenance | Config Sink:MaD:49376 |
| LdapInjection.java:276:31:276:68 | sBadLdapQueryBase : String | LdapInjection.java:277:42:277:58 | sBadLdapQueryBase : String | provenance | |
-| LdapInjection.java:277:12:277:59 | base(...) : LdapQueryBuilder | LdapInjection.java:277:12:277:66 | base(...) | provenance | Config Sink:MaD:49368 |
+| LdapInjection.java:277:12:277:59 | base(...) : LdapQueryBuilder | LdapInjection.java:277:12:277:66 | base(...) | provenance | Config Sink:MaD:49373 |
| LdapInjection.java:277:42:277:58 | sBadLdapQueryBase : String | LdapInjection.java:277:12:277:59 | base(...) : LdapQueryBuilder | provenance | Config |
| LdapInjection.java:281:31:281:71 | sBadLdapQueryComplex : String | LdapInjection.java:282:54:282:73 | sBadLdapQueryComplex : String | provenance | |
| LdapInjection.java:282:24:282:74 | base(...) : LdapQueryBuilder | LdapInjection.java:282:24:282:87 | where(...) : ConditionCriteria | provenance | Config |
-| LdapInjection.java:282:24:282:87 | where(...) : ConditionCriteria | LdapInjection.java:282:24:282:98 | is(...) | provenance | Config Sink:MaD:49371 |
+| LdapInjection.java:282:24:282:87 | where(...) : ConditionCriteria | LdapInjection.java:282:24:282:98 | is(...) | provenance | Config Sink:MaD:49376 |
| LdapInjection.java:282:54:282:73 | sBadLdapQueryComplex : String | LdapInjection.java:282:24:282:74 | base(...) : LdapQueryBuilder | provenance | Config |
| LdapInjection.java:286:31:286:69 | sBadFilterToString : String | LdapInjection.java:287:38:287:71 | ... + ... : String | provenance | |
-| LdapInjection.java:287:18:287:72 | new HardcodedFilter(...) : HardcodedFilter | LdapInjection.java:287:18:287:83 | toString(...) | provenance | Config Sink:MaD:49370 |
+| LdapInjection.java:287:18:287:72 | new HardcodedFilter(...) : HardcodedFilter | LdapInjection.java:287:18:287:83 | toString(...) | provenance | Config Sink:MaD:49375 |
| LdapInjection.java:287:38:287:71 | ... + ... : String | LdapInjection.java:287:18:287:72 | new HardcodedFilter(...) : HardcodedFilter | provenance | Config |
| LdapInjection.java:291:31:291:67 | sBadFilterEncode : String | LdapInjection.java:293:25:293:56 | ... + ... : String | provenance | |
| LdapInjection.java:293:5:293:57 | new HardcodedFilter(...) : HardcodedFilter | LdapInjection.java:293:66:293:66 | s : StringBuffer | provenance | Config |
| LdapInjection.java:293:25:293:56 | ... + ... : String | LdapInjection.java:293:5:293:57 | new HardcodedFilter(...) : HardcodedFilter | provenance | Config |
| LdapInjection.java:293:66:293:66 | s : StringBuffer | LdapInjection.java:294:18:294:18 | s : StringBuffer | provenance | |
-| LdapInjection.java:294:18:294:18 | s : StringBuffer | LdapInjection.java:294:18:294:29 | toString(...) | provenance | MaD:42727 Sink:MaD:49370 |
+| LdapInjection.java:294:18:294:18 | s : StringBuffer | LdapInjection.java:294:18:294:29 | toString(...) | provenance | MaD:42727 Sink:MaD:49375 |
| LdapInjection.java:314:30:314:54 | aBad : String | LdapInjection.java:316:36:316:55 | ... + ... | provenance | Sink:MaD:47462 |
| LdapInjection.java:314:57:314:83 | aBadDN : String | LdapInjection.java:316:14:316:33 | ... + ... | provenance | Sink:MaD:47462 |
| LdapInjection.java:320:30:320:54 | aBad : String | LdapInjection.java:322:65:322:84 | ... + ... | provenance | Sink:MaD:47462 |
From baf51334e4f5398dd0e43ab9ad36fd92bcd82c7d Mon Sep 17 00:00:00 2001
From: Joe Farebrother
Date: Fri, 19 Jul 2024 09:13:30 +0100
Subject: [PATCH 050/140] Update documentation
---
python/ql/src/Security/CWE-020/CookieInjection.qhelp | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/python/ql/src/Security/CWE-020/CookieInjection.qhelp b/python/ql/src/Security/CWE-020/CookieInjection.qhelp
index e3e03355cdfeb..72dfc4db4568e 100644
--- a/python/ql/src/Security/CWE-020/CookieInjection.qhelp
+++ b/python/ql/src/Security/CWE-020/CookieInjection.qhelp
@@ -4,7 +4,9 @@
-Constructing cookies from user input can allow an attacker to control a user's cookie. Additionally, if the cookie is set using a raw header, cookie attributes such as the Secure
flag may be controlled by an attacker.
+
Constructing cookies from user input can allow an attacker to control a user's cookie.
+This may lead to a session fixation attack. Additionally, client code may not expect a cookie to contain attacker-controlled data, and fail to sanitize it for common vulnerabilities such as Cross Site Scripting (XSS).
+An attacker manipulating the raw cookie header may additionally be able to set cookie attributes such as HttpOnly
to insecure values.
@@ -19,6 +21,7 @@ and the second sets a cookie's raw value through the set-cookie
hea
+Wikipedia - Session Fixation.
From 661a4126ac7b5efb86fe0f1f5deee55dbd5a45f9 Mon Sep 17 00:00:00 2001
From: Joe Farebrother
Date: Fri, 19 Jul 2024 09:23:33 +0100
Subject: [PATCH 051/140] Add change note
---
python/ql/src/change-notes/2024-07-19-cookie-injection.md | 4 ++++
1 file changed, 4 insertions(+)
create mode 100644 python/ql/src/change-notes/2024-07-19-cookie-injection.md
diff --git a/python/ql/src/change-notes/2024-07-19-cookie-injection.md b/python/ql/src/change-notes/2024-07-19-cookie-injection.md
new file mode 100644
index 0000000000000..ceefa99c886ba
--- /dev/null
+++ b/python/ql/src/change-notes/2024-07-19-cookie-injection.md
@@ -0,0 +1,4 @@
+---
+category: newQuery
+---
+* The `py/cookie-injection` query, originally contributed to the experimental query pack by @jorgectf, has been promoted to the main query pack. This query finds instances of cookies being constructed from user input.
\ No newline at end of file
From 620582fc0967ea859dee0f2fdc02d08d59652d23 Mon Sep 17 00:00:00 2001
From: Cornelius Riemenschneider
Date: Fri, 19 Jul 2024 10:50:11 +0200
Subject: [PATCH 052/140] Address review.
---
javascript/ql/integration-tests/all-platforms/no-types/test.py | 3 ---
1 file changed, 3 deletions(-)
diff --git a/javascript/ql/integration-tests/all-platforms/no-types/test.py b/javascript/ql/integration-tests/all-platforms/no-types/test.py
index a9c8a17a4a3fa..2c3862227aa94 100755
--- a/javascript/ql/integration-tests/all-platforms/no-types/test.py
+++ b/javascript/ql/integration-tests/all-platforms/no-types/test.py
@@ -1,5 +1,2 @@
-# from create_database_utils import *
-
-# run_codeql_database_create([], lang="javascript", extra_args=["-Oskip_types=true"])
def test(codeql, javascript):
codeql.database.create(extractor_option="skip_types=true")
From 1ca0de90672788c7a894f2f3ed8f88970150b30d Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Fri, 19 Jul 2024 13:55:33 +0100
Subject: [PATCH 053/140] Swift: Autoformat.
---
swift/ql/lib/codeql/swift/security/SensitiveExprs.qll | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/swift/ql/lib/codeql/swift/security/SensitiveExprs.qll b/swift/ql/lib/codeql/swift/security/SensitiveExprs.qll
index f56a10ee772db..b1cdd64d245d8 100644
--- a/swift/ql/lib/codeql/swift/security/SensitiveExprs.qll
+++ b/swift/ql/lib/codeql/swift/security/SensitiveExprs.qll
@@ -65,8 +65,9 @@ class SensitivePrivateInfo extends SensitiveDataType, TPrivateInfo {
override string getRegexp() {
// we've had good results for the e-mail heuristic in Swift, which isn't part of the default regex. Add it in.
- result = HeuristicNames::maybeSensitiveRegexp(SensitiveDataClassification::private())
- .replaceAll(".*(", ".*(e(mail|_mail)|")
+ result =
+ HeuristicNames::maybeSensitiveRegexp(SensitiveDataClassification::private())
+ .replaceAll(".*(", ".*(e(mail|_mail)|")
}
}
From f83b70dbc2f32d86315028e0fa042a4ed931c867 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Sat, 20 Jul 2024 00:17:36 +0000
Subject: [PATCH 054/140] Add changed framework coverage reports
---
go/documentation/library-coverage/coverage.csv | 8 ++++++--
go/documentation/library-coverage/coverage.rst | 7 ++++---
2 files changed, 10 insertions(+), 5 deletions(-)
diff --git a/go/documentation/library-coverage/coverage.csv b/go/documentation/library-coverage/coverage.csv
index 02773954f5ee3..7d9294b424af8 100644
--- a/go/documentation/library-coverage/coverage.csv
+++ b/go/documentation/library-coverage/coverage.csv
@@ -58,9 +58,11 @@ github.com/go-chi/jwtauth,1,,,1,,,,
github.com/go-jose/go-jose/jwt,1,,4,,1,,4,
github.com/go-kit/kit/auth/jwt,1,,,1,,,,
github.com/go-pg/pg/orm,,,6,,,,6,
+github.com/gobwas/ws,,2,,,,2,,
github.com/golang-jwt/jwt,3,,11,2,1,,11,
github.com/golang/protobuf/proto,,,4,,,,4,
github.com/gorilla/mux,,1,,,,1,,
+github.com/gorilla/websocket,,3,,,,3,,
github.com/json-iterator/go,,,4,,,,4,
github.com/kataras/iris/middleware/jwt,1,,,1,,,,
github.com/kataras/jwt,5,,,5,,,,
@@ -69,14 +71,15 @@ github.com/lestrrat-go/jwx,1,,,1,,,,
github.com/lestrrat-go/jwx/jwk,1,,,1,,,,
github.com/lestrrat/go-jwx/jwk,1,,,1,,,,
github.com/ory/fosite/token/jwt,2,,,2,,,,
-github.com/revel/revel,,21,10,,,21,10,
-github.com/robfig/revel,,21,10,,,21,10,
+github.com/revel/revel,,23,10,,,23,10,
+github.com/robfig/revel,,23,10,,,23,10,
github.com/sendgrid/sendgrid-go/helpers/mail,,,1,,,,1,
github.com/square/go-jose/jwt,1,,4,,1,,4,
github.com/valyala/fasthttp,,50,5,,,50,5,
go.uber.org/zap,,,11,,,,11,
golang.org/x/net/context,,,5,,,,5,
golang.org/x/net/html,,,16,,,,16,
+golang.org/x/net/websocket,,2,,,,2,,
google.golang.org/protobuf/internal/encoding/text,,,1,,,,1,
google.golang.org/protobuf/internal/impl,,,2,,,,2,
google.golang.org/protobuf/proto,,,8,,,,8,
@@ -103,6 +106,7 @@ net/http/httputil,,,10,,,,10,
net/mail,,,6,,,,6,
net/textproto,,,19,,,,19,
net/url,,,23,,,,23,
+nhooyr.io/websocket,,2,,,,2,,
os,,,4,,,,4,
path,,,5,,,,5,
path/filepath,,,13,,,,13,
diff --git a/go/documentation/library-coverage/coverage.rst b/go/documentation/library-coverage/coverage.rst
index daeca0c836e0b..51158f84cb025 100644
--- a/go/documentation/library-coverage/coverage.rst
+++ b/go/documentation/library-coverage/coverage.rst
@@ -17,7 +17,7 @@ Go framework & library support
`Iris `_,``github.com/kataras/iris*``,,,1
`Kubernetes `_,"``k8s.io/api*``, ``k8s.io/apimachinery*``",,57,
`Macaron `_,``gopkg.in/macaron*``,12,1,
- `Revel `_,"``github.com/revel/revel*``, ``github.com/robfig/revel*``",42,20,
+ `Revel `_,"``github.com/revel/revel*``, ``github.com/robfig/revel*``",46,20,
`SendGrid `_,``github.com/sendgrid/sendgrid-go*``,,1,
`Standard library `_,"````, ``archive/*``, ``bufio``, ``bytes``, ``cmp``, ``compress/*``, ``container/*``, ``context``, ``crypto``, ``crypto/*``, ``database/*``, ``debug/*``, ``embed``, ``encoding``, ``encoding/*``, ``errors``, ``expvar``, ``flag``, ``fmt``, ``go/*``, ``hash``, ``hash/*``, ``html``, ``html/*``, ``image``, ``image/*``, ``index/*``, ``io``, ``io/*``, ``log``, ``log/*``, ``maps``, ``math``, ``math/*``, ``mime``, ``mime/*``, ``net``, ``net/*``, ``os``, ``os/*``, ``path``, ``path/*``, ``plugin``, ``reflect``, ``reflect/*``, ``regexp``, ``regexp/*``, ``slices``, ``sort``, ``strconv``, ``strings``, ``sync``, ``sync/*``, ``syscall``, ``syscall/*``, ``testing``, ``testing/*``, ``text/*``, ``time``, ``time/*``, ``unicode``, ``unicode/*``, ``unsafe``",16,584,
`beego `_,"``github.com/astaxie/beego*``, ``github.com/beego/beego*``",63,63,
@@ -26,7 +26,7 @@ Go framework & library support
`fasthttp `_,``github.com/valyala/fasthttp*``,50,5,
`go-pg `_,``github.com/go-pg/pg*``,,6,
`go-restful `_,``github.com/emicklei/go-restful*``,7,,
- `golang.org/x/net `_,``golang.org/x/net*``,,21,
+ `golang.org/x/net `_,``golang.org/x/net*``,2,21,
`goproxy `_,``github.com/elazarl/goproxy*``,2,2,
`gorilla/mux `_,``github.com/gorilla/mux*``,1,,
`json-iterator `_,``github.com/json-iterator/go*``,,4,
@@ -38,5 +38,6 @@ Go framework & library support
`protobuf `_,"``github.com/golang/protobuf*``, ``google.golang.org/protobuf*``",,16,
`yaml `_,``gopkg.in/yaml*``,,9,
`zap `_,``go.uber.org/zap*``,,11,
- Totals,,254,902,25
+ Others,"``github.com/gobwas/ws``, ``github.com/gorilla/websocket``, ``nhooyr.io/websocket``",7,,
+ Totals,,267,902,25
From a64eafca2b634bd94b49be774d1c59a2a997afd4 Mon Sep 17 00:00:00 2001
From: Owen Mansel-Chan
Date: Sat, 20 Jul 2024 21:31:08 +0100
Subject: [PATCH 055/140] Do not mention subcategories of `remote`
They are not in use by any language yet.
---
docs/codeql/reusables/threat-model-description.rst | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/codeql/reusables/threat-model-description.rst b/docs/codeql/reusables/threat-model-description.rst
index bc21e7ad170b2..45fe031745635 100644
--- a/docs/codeql/reusables/threat-model-description.rst
+++ b/docs/codeql/reusables/threat-model-description.rst
@@ -4,7 +4,7 @@ A threat model is a named class of dataflow sources that can be enabled or disab
The ``kind`` property of the ``sourceModel`` determines which threat model a source is associated with. There are two main categories:
-- ``remote`` which represents requests (``request``) and responses (``response``) from the network.
+- ``remote`` which represents requests and responses from the network.
- ``local`` which represents data from local files (``file``), command-line arguments (``commandargs``), database reads (``database``), environment variables(``environment``) and Windows registry values ("windows-registry"). Currently, Windows registry values are used by C# only.
Note that subcategories can be turned included or excluded separately, so you can specify ``local`` without ``database``, or just ``commandargs`` and ``environment`` without the rest of ``local``.
From 2a5144d9d9a41c0d698d3d3693b8a78f6049bd43 Mon Sep 17 00:00:00 2001
From: Owen Mansel-Chan
Date: Sat, 20 Jul 2024 21:40:02 +0100
Subject: [PATCH 056/140] Improve tests for reverse DNS sources
---
java/ql/test/library-tests/dataflow/taintsources/A.java | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/java/ql/test/library-tests/dataflow/taintsources/A.java b/java/ql/test/library-tests/dataflow/taintsources/A.java
index 6b91a4ca1bfe3..f28834e583750 100644
--- a/java/ql/test/library-tests/dataflow/taintsources/A.java
+++ b/java/ql/test/library-tests/dataflow/taintsources/A.java
@@ -44,6 +44,11 @@ public void test(ResultSet rs) throws SQLException {
sink(new URL("test").openConnection().getInputStream()); // $hasRemoteValueFlow
sink(new Socket("test", 1234).getInputStream()); // $hasRemoteValueFlow
sink(InetAddress.getByName("test").getHostName()); // $hasReverseDnsValueFlow
+ sink(InetAddress.getLocalHost().getHostName());
+ sink(InetAddress.getLoopbackAddress().getHostName());
+ sink(InetAddress.getByName("test").getCanonicalHostName()); // $hasReverseDnsValueFlow
+ sink(InetAddress.getLocalHost().getCanonicalHostName());
+ sink(InetAddress.getLoopbackAddress().getCanonicalHostName());
sink(System.in); // $hasLocalValueFlow
sink(new FileInputStream("test")); // $hasLocalValueFlow
From 4790656b7973b62805358a8f4c024f37ed991015 Mon Sep 17 00:00:00 2001
From: Jami Cogswell
Date: Sat, 20 Jul 2024 23:03:32 -0400
Subject: [PATCH 057/140] Java: add TaintInheritingContent for URL synthetic
fields
---
.../lib/semmle/code/java/dataflow/FlowSteps.qll | 1 +
.../semmle/code/java/frameworks/Networking.qll | 7 +++++++
.../frameworks/jdk/java.net/Test.java | 16 ++++++++++++++++
3 files changed, 24 insertions(+)
diff --git a/java/ql/lib/semmle/code/java/dataflow/FlowSteps.qll b/java/ql/lib/semmle/code/java/dataflow/FlowSteps.qll
index 773c480b7e741..e7d34d166b120 100644
--- a/java/ql/lib/semmle/code/java/dataflow/FlowSteps.qll
+++ b/java/ql/lib/semmle/code/java/dataflow/FlowSteps.qll
@@ -22,6 +22,7 @@ private module Frameworks {
private import semmle.code.java.frameworks.IoJsonWebToken
private import semmle.code.java.frameworks.jackson.JacksonSerializability
private import semmle.code.java.frameworks.InputStream
+ private import semmle.code.java.frameworks.Networking
private import semmle.code.java.frameworks.Properties
private import semmle.code.java.frameworks.Protobuf
private import semmle.code.java.frameworks.ThreadLocal
diff --git a/java/ql/lib/semmle/code/java/frameworks/Networking.qll b/java/ql/lib/semmle/code/java/frameworks/Networking.qll
index f86cecd5b4ee7..1139d0d006211 100644
--- a/java/ql/lib/semmle/code/java/frameworks/Networking.qll
+++ b/java/ql/lib/semmle/code/java/frameworks/Networking.qll
@@ -3,6 +3,8 @@
*/
import semmle.code.java.Type
+private import semmle.code.java.dataflow.DataFlow
+private import semmle.code.java.dataflow.FlowSteps
/** The type `java.net.URLConnection`. */
class TypeUrlConnection extends RefType {
@@ -24,6 +26,11 @@ class TypeUrl extends RefType {
TypeUrl() { this.hasQualifiedName("java.net", "URL") }
}
+/** Specifies that if a `URL` is tainted, then so are its synthetic fields. */
+private class UrlFieldsInheritTaint extends DataFlow::SyntheticFieldContent, TaintInheritingContent {
+ UrlFieldsInheritTaint() { this.getField().matches("java.net.URL.%") }
+}
+
/** The type `java.net.URLDecoder`. */
class TypeUrlDecoder extends RefType {
TypeUrlDecoder() { this.hasQualifiedName("java.net", "URLDecoder") }
diff --git a/java/ql/test/library-tests/frameworks/jdk/java.net/Test.java b/java/ql/test/library-tests/frameworks/jdk/java.net/Test.java
index 7f36d66d136b2..1172ce88f3f50 100644
--- a/java/ql/test/library-tests/frameworks/jdk/java.net/Test.java
+++ b/java/ql/test/library-tests/frameworks/jdk/java.net/Test.java
@@ -90,6 +90,14 @@ public void test() throws Exception {
out = in.toURL();
sink(out); // $ hasTaintFlow
}
+ {
+ // manual test for `URI.toURL().getPath()`; checks that if a `URL` is tainted, then so are its synthetic fields
+ // java.net;URL;False;getPath;();;Argument[this].SyntheticField[java.net.URL.path];ReturnValue;taint;ai-manual
+ URL out = null;
+ URI in = (URI) source();
+ out = in.toURL();
+ sink(out.getPath()); // $ hasTaintFlow
+ }
{
// "java.net;URL;false;URL;(String);;Argument[0];Argument[this];taint;manual"
URL out = null;
@@ -97,6 +105,14 @@ public void test() throws Exception {
out = new URL(in);
sink(out); // $ hasTaintFlow
}
+ {
+ // manual test for `URL(String).getPath()`; checks that if a `URL` is tainted, then so are its synthetic fields
+ // java.net;URL;False;getPath;();;Argument[this].SyntheticField[java.net.URL.path];ReturnValue;taint;ai-manual
+ URL out = null;
+ String in = (String) source();
+ out = new URL(in);
+ sink(out.getPath()); // $ hasTaintFlow
+ }
{
// "java.net;URL;false;URL;(URL,String);;Argument[0];Argument[this];taint;ai-generated"
URL out = null;
From 6d468c1bae3cfaf90731b98066e76b8deb37e7dc Mon Sep 17 00:00:00 2001
From: Marcono1234
Date: Sun, 21 Jul 2024 19:19:08 +0200
Subject: [PATCH 058/140] Java: Update `Annotation` predicate examples in
language guide
---
docs/codeql/codeql-language-guides/annotations-in-java.rst | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/docs/codeql/codeql-language-guides/annotations-in-java.rst b/docs/codeql/codeql-language-guides/annotations-in-java.rst
index 09e3290b5fdd6..f817bef7b623c 100644
--- a/docs/codeql/codeql-language-guides/annotations-in-java.rst
+++ b/docs/codeql/codeql-language-guides/annotations-in-java.rst
@@ -103,7 +103,7 @@ As a first step, let's write a query that finds all ``@Override`` annotations. A
As always, it is a good idea to try this query on a CodeQL database for a Java/Kotlin project to make sure it actually produces some results. On the earlier example, it should find the annotation on ``Sub1.m``. Next, we encapsulate the concept of an ``@Override`` annotation as a CodeQL class:
-::
+.. code-block:: ql
class OverrideAnnotation extends Annotation {
OverrideAnnotation() {
@@ -213,11 +213,11 @@ To do so, we first introduce a class for representing all ``@SuppressWarnings``
class SuppressDeprecationWarningAnnotation extends Annotation {
SuppressDeprecationWarningAnnotation() {
this.getType().hasQualifiedName("java.lang", "SuppressWarnings") and
- this.getAValue().(Literal).getLiteral().regexpMatch(".*deprecation.*")
+ this.getAStringArrayValue("value").regexpMatch(".*deprecation.*")
}
}
-Here, we use ``getAValue()`` to retrieve any annotation value: in fact, annotation type ``SuppressWarnings`` only has a single annotation element, so every ``@SuppressWarnings`` annotation only has a single annotation value. Then, we ensure that it is a literal, obtain its string value using ``getLiteral``, and check whether it contains the string ``deprecation`` using a regular expression match.
+Here, we use ``getAStringArrayValue("value")`` to retrieve any of the suppressed warnings: ``@SuppressWarnings`` defines the warnings to suppress using the annotation element named ``value`` of type ``String[]``, and ``getAStringArrayValue`` retrieves all of the array values; the CodeQL class ``Annotation`` also has similar convenience predicates for the other possible annotation element types. Afterwards we check whether one of the values is the string ``deprecation`` using a regular expression match.
For real-world use, this check would have to be generalized a bit: for example, the OpenJDK Java compiler allows ``@SuppressWarnings("all")`` annotations to suppress all warnings. We may also want to make sure that ``deprecation`` is matched as an entire word, and not as part of another word, by changing the regular expression to ``".*\\bdeprecation\\b.*"``.
From ffc61ae1bb2bcb198a37a46ae669eccc0adf1c0d Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Wed, 17 Jul 2024 17:29:11 +0100
Subject: [PATCH 059/140] C++: Make memset_s a clearer recommendation in the
.qhelp for cpp/memset-may-be-deleted.
---
.../src/Security/CWE/CWE-014/MemsetMayBeDeleted.qhelp | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/cpp/ql/src/Security/CWE/CWE-014/MemsetMayBeDeleted.qhelp b/cpp/ql/src/Security/CWE/CWE-014/MemsetMayBeDeleted.qhelp
index 2c087e37eaa8b..15b94a44ec857 100644
--- a/cpp/ql/src/Security/CWE/CWE-014/MemsetMayBeDeleted.qhelp
+++ b/cpp/ql/src/Security/CWE/CWE-014/MemsetMayBeDeleted.qhelp
@@ -10,11 +10,12 @@ contains sensitive data that could somehow be retrieved by an attacker.
-Use alternative platform-supplied functions that will not get optimized away. Examples of such
-functions include memset_s
, SecureZeroMemory
, and bzero_explicit
.
-Alternatively, passing the -fno-builtin-memset
option to the GCC/Clang compiler usually
-also prevents the optimization. Finally, you can use the public-domain secure_memzero
function
-(see references below). This function, however, is not guaranteed to work on all platforms and compilers.
+Use memset_s
(from C11) instead of memset
, as memset_s
will not
+get optimized away. Alternatively use platform-supplied functions such as SecureZeroMemory
or
+bzero_explicit
that make the same guarantee. Passing the -fno-builtin-memset
+option to the GCC/Clang compiler usually also prevents the optimization. Finally, you can use the
+public-domain secure_memzero
function (see references below). This function, however, is not
+guaranteed to work on all platforms and compilers.
From f931dab14a7e2d782b5b3894b3cdc8c5d1d5d9ca Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Wed, 17 Jul 2024 18:41:09 +0100
Subject: [PATCH 060/140] C++: Improve the cpp/cleartext-* query examples by
using libsodium rather than pseudocode.
---
.../Security/CWE/CWE-311/CleartextStorage.c | 37 ++++++++++++++-----
.../CWE/CWE-311/CleartextStorage.inc.qhelp | 9 ++++-
2 files changed, 35 insertions(+), 11 deletions(-)
diff --git a/cpp/ql/src/Security/CWE/CWE-311/CleartextStorage.c b/cpp/ql/src/Security/CWE/CWE-311/CleartextStorage.c
index e0600cc4d2f2e..7f7f6186041a5 100644
--- a/cpp/ql/src/Security/CWE/CWE-311/CleartextStorage.c
+++ b/cpp/ql/src/Security/CWE/CWE-311/CleartextStorage.c
@@ -1,12 +1,31 @@
-void writeCredentials() {
- char *password = "cleartext password";
- FILE* file = fopen("credentials.txt", "w");
-
+#include
+#include
+#include
+
+void writeCredentialsBad(FILE *file, const char *cleartextCredentials) {
// BAD: write password to disk in cleartext
- fputs(password, file);
-
- // GOOD: encrypt password first
- char *encrypted = encrypt(password);
- fputs(encrypted, file);
+ fputs(cleartextCredentials, file);
}
+int writeCredentialsGood(FILE *file, const char *cleartextCredentials, const unsigned char *key, const unsigned char *nonce) {
+ size_t credentialsLen = strlen(cleartextCredentials);
+ size_t ciphertext_len = crypto_secretbox_MACBYTES + credentialsLen;
+ unsigned char *ciphertext = malloc(ciphertext_len);
+ if (!ciphertext) {
+ logError();
+ return -1;
+ }
+
+ // encrypt the password first
+ if (crypto_secretbox_easy(ciphertext, (const unsigned char *)cleartextCredentials, credentialsLen, nonce, key) != 0) {
+ free(ciphertext);
+ logError();
+ return -1;
+ }
+
+ // GOOD: write encrypted password to disk
+ fwrite(ciphertext, 1, ciphertext_len, file);
+
+ free(ciphertext);
+ return 0;
+}
diff --git a/cpp/ql/src/Security/CWE/CWE-311/CleartextStorage.inc.qhelp b/cpp/ql/src/Security/CWE/CWE-311/CleartextStorage.inc.qhelp
index f5e978e05cbac..bda49ea3ac15b 100644
--- a/cpp/ql/src/Security/CWE/CWE-311/CleartextStorage.inc.qhelp
+++ b/cpp/ql/src/Security/CWE/CWE-311/CleartextStorage.inc.qhelp
@@ -19,15 +19,20 @@ cleartext.
The following example shows two ways of storing user credentials in a file. In the 'BAD' case,
-the credentials are simply stored in cleartext. In the 'GOOD' case, the credentials are encrypted before
+the credentials are simply stored in cleartext. In the 'GOOD' case, the credentials are encrypted before
storing them.
+Note that for the good example to work we need to link against the encryption library (in this case libsodium),
+initialize it with a call to sodium_init
, and create the key and nonce with
+crypto_secretbox_keygen
and randombytes_buf
respectively. We also need to store those
+details securely so they can be used for decryption.
+
-M. Dowd, J. McDonald and J. Schuhm, The Art of Software Security Assessment, 1st Edition, Chapter 2 - 'Common Vulnerabilities of Encryption', p. 43. Addison Wesley, 2006.
+M. Dowd, J. McDonald and J. Schuhm, The Art of Software Security Assessment, 1st Edition, Chapter 2 - 'Common Vulnerabilities of Encryption', p. 43. Addison Wesley, 2006.
M. Howard and D. LeBlanc, Writing Secure Code, 2nd Edition, Chapter 9 - 'Protecting Secret Data', p. 299. Microsoft, 2002.
From b00e312569c1a7c7b80fecf45a8f6aed0da8a9ef Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Mon, 22 Jul 2024 10:50:42 +0100
Subject: [PATCH 061/140] C++: Replace placeholder key in the example for
cpp/cleartext-storage-database.
---
.../src/Security/CWE/CWE-313/CleartextSqliteDatabase.c | 10 +++++-----
.../Security/CWE/CWE-313/CleartextSqliteDatabase.qhelp | 4 +++-
2 files changed, 8 insertions(+), 6 deletions(-)
diff --git a/cpp/ql/src/Security/CWE/CWE-313/CleartextSqliteDatabase.c b/cpp/ql/src/Security/CWE/CWE-313/CleartextSqliteDatabase.c
index f92aa8c38684b..8c6a8f439d992 100644
--- a/cpp/ql/src/Security/CWE/CWE-313/CleartextSqliteDatabase.c
+++ b/cpp/ql/src/Security/CWE/CWE-313/CleartextSqliteDatabase.c
@@ -1,6 +1,6 @@
void bad(void) {
- char *password = "cleartext password";
+ const char *password = "cleartext password";
sqlite3 *credentialsDB;
sqlite3_stmt *stmt;
@@ -16,14 +16,15 @@ void bad(void) {
}
}
-void good(void) {
- char *password = "cleartext password";
+void good(const char *secretKey) {
+ const char *password = "cleartext password";
sqlite3 *credentialsDB;
sqlite3_stmt *stmt;
if (sqlite3_open("credentials.db", &credentialsDB) == SQLITE_OK) {
// GOOD: database encryption enabled:
- sqlite3_exec(credentialsDB, "PRAGMA key = 'secretKey!'", NULL, NULL, NULL);
+ std::string setKeyString = std::string("PRAGMA key = '") + secretKey + "'";
+ sqlite3_exec(credentialsDB, setKeyString.c_str(), NULL, NULL, NULL);
sqlite3_exec(credentialsDB, "CREATE TABLE IF NOT EXISTS creds (password TEXT);", NULL, NULL, NULL);
if (sqlite3_prepare_v2(credentialsDB, "INSERT INTO creds(password) VALUES(?)", -1, &stmt, NULL) == SQLITE_OK) {
sqlite3_bind_text(stmt, 1, password, -1, SQLITE_TRANSIENT);
@@ -33,4 +34,3 @@ void good(void) {
}
}
}
-
diff --git a/cpp/ql/src/Security/CWE/CWE-313/CleartextSqliteDatabase.qhelp b/cpp/ql/src/Security/CWE/CWE-313/CleartextSqliteDatabase.qhelp
index c8edcccb92f5a..c3decb0ef8ea1 100644
--- a/cpp/ql/src/Security/CWE/CWE-313/CleartextSqliteDatabase.qhelp
+++ b/cpp/ql/src/Security/CWE/CWE-313/CleartextSqliteDatabase.qhelp
@@ -20,10 +20,12 @@ In the 'GOOD' case, the database (and thus the credentials) are encrypted.
+Note that for the good example to work we need to provide a secret key. Secure key generation and storage is required.
+
-M. Dowd, J. McDonald and J. Schuhm, The Art of Software Security Assessment, 1st Edition, Chapter 2 - 'Common Vulnerabilities of Encryption', p. 43. Addison Wesley, 2006.
+M. Dowd, J. McDonald and J. Schuhm, The Art of Software Security Assessment, 1st Edition, Chapter 2 - 'Common Vulnerabilities of Encryption', p. 43. Addison Wesley, 2006.
M. Howard and D. LeBlanc, Writing Secure Code, 2nd Edition, Chapter 9 - 'Protecting Secret Data', p. 299. Microsoft, 2002.
From 8262330e4d539d53d9d40e4b3cf3138d5c073e09 Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Mon, 22 Jul 2024 12:01:57 +0100
Subject: [PATCH 062/140] C++: Extend the placement new test cases for
cpp/incorrect-allocation-error-handling.
---
.../IncorrectAllocationErrorHandling.expected | 9 +++---
.../query-tests/Security/CWE/CWE-570/test.cpp | 32 ++++++++++++++++++-
2 files changed, 36 insertions(+), 5 deletions(-)
diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-570/IncorrectAllocationErrorHandling.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-570/IncorrectAllocationErrorHandling.expected
index 1d48edd7cea13..b602d51c4ab2b 100644
--- a/cpp/ql/test/query-tests/Security/CWE/CWE-570/IncorrectAllocationErrorHandling.expected
+++ b/cpp/ql/test/query-tests/Security/CWE/CWE-570/IncorrectAllocationErrorHandling.expected
@@ -13,7 +13,8 @@
| test.cpp:92:5:92:31 | new[] | This allocation cannot throw. $@ is unnecessary. | test.cpp:97:36:98:3 | { ... } | This catch block |
| test.cpp:93:15:93:41 | new[] | This allocation cannot throw. $@ is unnecessary. | test.cpp:97:36:98:3 | { ... } | This catch block |
| test.cpp:96:10:96:36 | new[] | This allocation cannot throw. $@ is unnecessary. | test.cpp:97:36:98:3 | { ... } | This catch block |
-| test.cpp:151:9:151:24 | new | This allocation cannot throw. $@ is unnecessary. | test.cpp:152:15:152:18 | { ... } | This catch block |
-| test.cpp:199:15:199:35 | new | This allocation cannot throw. $@ is unnecessary. | test.cpp:201:16:201:19 | { ... } | This catch block |
-| test.cpp:212:14:212:34 | new | This allocation cannot throw. $@ is unnecessary. | test.cpp:213:34:213:36 | { ... } | This catch block |
-| test.cpp:246:17:246:31 | new[] | This allocation cannot return null. $@ is unnecessary. | test.cpp:247:8:247:12 | ! ... | This check |
+| test.cpp:160:9:160:24 | new | This allocation cannot throw. $@ is unnecessary. | test.cpp:161:15:161:18 | { ... } | This catch block |
+| test.cpp:178:12:178:25 | new | This allocation cannot throw. $@ is unnecessary. | test.cpp:179:17:181:3 | { ... } | This catch block |
+| test.cpp:229:15:229:35 | new | This allocation cannot throw. $@ is unnecessary. | test.cpp:231:16:231:19 | { ... } | This catch block |
+| test.cpp:242:14:242:34 | new | This allocation cannot throw. $@ is unnecessary. | test.cpp:243:34:243:36 | { ... } | This catch block |
+| test.cpp:276:17:276:31 | new[] | This allocation cannot return null. $@ is unnecessary. | test.cpp:277:8:277:12 | ! ... | This check |
diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-570/test.cpp b/cpp/ql/test/query-tests/Security/CWE/CWE-570/test.cpp
index cedef98a5d8fa..7a362e97ccefb 100644
--- a/cpp/ql/test/query-tests/Security/CWE/CWE-570/test.cpp
+++ b/cpp/ql/test/query-tests/Security/CWE/CWE-570/test.cpp
@@ -136,6 +136,8 @@ void good_new_handles_nullptr() {
return; // GOOD
}
+// ---
+
void* operator new(std::size_t count, void*) noexcept;
void* operator new[](std::size_t count, void*) noexcept;
@@ -146,18 +148,46 @@ struct Foo {
operator bool();
};
+struct Bar {
+ Bar();
+
+ operator bool();
+};
+
void bad_placement_new_with_exception_handling() {
char buffer[1024];
- try { new (buffer) Foo; } // BAD
+
+ try { new (buffer) Foo; } // BAD (placement new should not fail)
catch (...) { }
}
void good_placement_new_with_exception_handling() {
char buffer[1024];
+
try { new (buffer) Foo(42); } // GOOD: Foo constructor might throw
catch (...) { }
+
+ try { new (buffer) Bar; } // GOOD: Bar constructor might throw
+ catch (...) { }
}
+template F *test_template_platement_new() {
+ char buffer[1024];
+
+ try {
+ return new (buffer) F; // GOOD: `F` constructor might throw (when `F` is `Foo`) [FALSE POSITIVE]
+ } catch (...) {
+ return 0;
+ }
+}
+
+void test_template_platement_new_caller() {
+ test_template_platement_new();
+ test_template_platement_new();
+}
+
+// ---
+
int unknown_value_without_exceptions() noexcept;
void may_throw() {
From 55935fc123cc4d6244ee6787b0ee6c497a72a374 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
Date: Mon, 22 Jul 2024 14:56:15 +0000
Subject: [PATCH 063/140] Release preparation for version 2.18.1
---
cpp/ql/lib/CHANGELOG.md | 8 +++++++
.../2024-07-10-newarrayexpr-arraysize.md | 4 ----
.../2024-07-16-alert-provenance.md | 4 ----
.../1.3.0.md} | 9 +++++---
cpp/ql/lib/codeql-pack.release.yml | 2 +-
cpp/ql/lib/qlpack.yml | 2 +-
cpp/ql/src/CHANGELOG.md | 11 ++++++++++
.../2024-07-08-unsafe-strncat-query.md | 4 ----
...-11-iterator-to-expired-container-query.md | 4 ----
...ed-difference-expression-compared-zero-.md | 4 ----
cpp/ql/src/change-notes/released/1.1.0.md | 10 +++++++++
cpp/ql/src/codeql-pack.release.yml | 2 +-
cpp/ql/src/qlpack.yml | 2 +-
.../ql/campaigns/Solorigate/lib/CHANGELOG.md | 4 ++++
.../lib/change-notes/released/1.7.21.md | 3 +++
.../Solorigate/lib/codeql-pack.release.yml | 2 +-
csharp/ql/campaigns/Solorigate/lib/qlpack.yml | 2 +-
.../ql/campaigns/Solorigate/src/CHANGELOG.md | 4 ++++
.../src/change-notes/released/1.7.21.md | 3 +++
.../Solorigate/src/codeql-pack.release.yml | 2 +-
csharp/ql/campaigns/Solorigate/src/qlpack.yml | 2 +-
csharp/ql/lib/CHANGELOG.md | 4 ++++
csharp/ql/lib/change-notes/released/1.0.4.md | 3 +++
csharp/ql/lib/codeql-pack.release.yml | 2 +-
csharp/ql/lib/qlpack.yml | 2 +-
csharp/ql/src/CHANGELOG.md | 4 ++++
csharp/ql/src/change-notes/released/1.0.4.md | 3 +++
csharp/ql/src/codeql-pack.release.yml | 2 +-
csharp/ql/src/qlpack.yml | 2 +-
go/ql/consistency-queries/CHANGELOG.md | 4 ++++
.../change-notes/released/1.0.4.md | 3 +++
.../codeql-pack.release.yml | 2 +-
go/ql/consistency-queries/qlpack.yml | 2 +-
go/ql/lib/CHANGELOG.md | 6 ++++++
.../1.1.3.md} | 7 ++++---
go/ql/lib/codeql-pack.release.yml | 2 +-
go/ql/lib/qlpack.yml | 2 +-
go/ql/src/CHANGELOG.md | 4 ++++
go/ql/src/change-notes/released/1.0.4.md | 3 +++
go/ql/src/codeql-pack.release.yml | 2 +-
go/ql/src/qlpack.yml | 2 +-
java/ql/automodel/src/CHANGELOG.md | 4 ++++
.../src/change-notes/released/1.0.4.md | 3 +++
java/ql/automodel/src/codeql-pack.release.yml | 2 +-
java/ql/automodel/src/qlpack.yml | 2 +-
java/ql/lib/CHANGELOG.md | 21 +++++++++++++++++++
.../2024-06-12-isandroid-deprecated.md | 4 ----
.../change-notes/2024-06-19-kotlin-2.0.20.md | 4 ----
.../2024-06-25-java-tools-status.md | 4 ----
.../2024-07-03-env-var-semmle-dist.md | 4 ----
.../2024-07-11-FilePath-exists-sink.md | 4 ----
.../lib/change-notes/2024-07-11-kotlin-ga.md | 4 ----
.../2024-07-11-toByteArray-summary.md | 4 ----
java/ql/lib/change-notes/released/2.0.0.md | 20 ++++++++++++++++++
java/ql/lib/codeql-pack.release.yml | 2 +-
java/ql/lib/qlpack.yml | 2 +-
java/ql/src/CHANGELOG.md | 6 ++++++
.../1.1.1.md} | 7 ++++---
java/ql/src/codeql-pack.release.yml | 2 +-
java/ql/src/qlpack.yml | 2 +-
javascript/ql/lib/CHANGELOG.md | 4 ++++
.../ql/lib/change-notes/released/1.1.1.md | 3 +++
javascript/ql/lib/codeql-pack.release.yml | 2 +-
javascript/ql/lib/qlpack.yml | 2 +-
javascript/ql/src/CHANGELOG.md | 14 +++++++++++++
.../2024-06-19-insecure-helmet-config.md | 4 ----
.../1.1.0.md} | 11 +++++++---
javascript/ql/src/codeql-pack.release.yml | 2 +-
javascript/ql/src/qlpack.yml | 2 +-
misc/suite-helpers/CHANGELOG.md | 4 ++++
.../change-notes/released/1.0.4.md | 3 +++
misc/suite-helpers/codeql-pack.release.yml | 2 +-
misc/suite-helpers/qlpack.yml | 2 +-
python/ql/lib/CHANGELOG.md | 6 ++++++
.../1.0.4.md} | 9 ++++----
python/ql/lib/codeql-pack.release.yml | 2 +-
python/ql/lib/qlpack.yml | 2 +-
python/ql/src/CHANGELOG.md | 4 ++++
python/ql/src/change-notes/released/1.0.4.md | 3 +++
python/ql/src/codeql-pack.release.yml | 2 +-
python/ql/src/qlpack.yml | 2 +-
ruby/ql/lib/CHANGELOG.md | 4 ++++
ruby/ql/lib/change-notes/released/1.0.4.md | 3 +++
ruby/ql/lib/codeql-pack.release.yml | 2 +-
ruby/ql/lib/qlpack.yml | 2 +-
ruby/ql/src/CHANGELOG.md | 4 ++++
ruby/ql/src/change-notes/released/1.0.4.md | 3 +++
ruby/ql/src/codeql-pack.release.yml | 2 +-
ruby/ql/src/qlpack.yml | 2 +-
shared/controlflow/CHANGELOG.md | 4 ++++
.../change-notes/released/1.0.4.md | 3 +++
shared/controlflow/codeql-pack.release.yml | 2 +-
shared/controlflow/qlpack.yml | 2 +-
shared/dataflow/CHANGELOG.md | 4 ++++
.../dataflow/change-notes/released/1.0.4.md | 3 +++
shared/dataflow/codeql-pack.release.yml | 2 +-
shared/dataflow/qlpack.yml | 2 +-
shared/mad/CHANGELOG.md | 4 ++++
shared/mad/change-notes/released/1.0.4.md | 3 +++
shared/mad/codeql-pack.release.yml | 2 +-
shared/mad/qlpack.yml | 2 +-
shared/rangeanalysis/CHANGELOG.md | 4 ++++
.../change-notes/released/1.0.4.md | 3 +++
shared/rangeanalysis/codeql-pack.release.yml | 2 +-
shared/rangeanalysis/qlpack.yml | 2 +-
shared/regex/CHANGELOG.md | 4 ++++
shared/regex/change-notes/released/1.0.4.md | 3 +++
shared/regex/codeql-pack.release.yml | 2 +-
shared/regex/qlpack.yml | 2 +-
shared/ssa/CHANGELOG.md | 4 ++++
shared/ssa/change-notes/released/1.0.4.md | 3 +++
shared/ssa/codeql-pack.release.yml | 2 +-
shared/ssa/qlpack.yml | 2 +-
shared/threat-models/CHANGELOG.md | 4 ++++
.../change-notes/released/1.0.4.md | 3 +++
shared/threat-models/codeql-pack.release.yml | 2 +-
shared/threat-models/qlpack.yml | 2 +-
shared/tutorial/CHANGELOG.md | 4 ++++
.../tutorial/change-notes/released/1.0.4.md | 3 +++
shared/tutorial/codeql-pack.release.yml | 2 +-
shared/tutorial/qlpack.yml | 2 +-
shared/typeflow/CHANGELOG.md | 4 ++++
.../typeflow/change-notes/released/1.0.4.md | 3 +++
shared/typeflow/codeql-pack.release.yml | 2 +-
shared/typeflow/qlpack.yml | 2 +-
shared/typetracking/CHANGELOG.md | 4 ++++
.../change-notes/released/1.0.4.md | 3 +++
shared/typetracking/codeql-pack.release.yml | 2 +-
shared/typetracking/qlpack.yml | 2 +-
shared/typos/CHANGELOG.md | 4 ++++
shared/typos/change-notes/released/1.0.4.md | 3 +++
shared/typos/codeql-pack.release.yml | 2 +-
shared/typos/qlpack.yml | 2 +-
shared/util/CHANGELOG.md | 4 ++++
shared/util/change-notes/released/1.0.4.md | 3 +++
shared/util/codeql-pack.release.yml | 2 +-
shared/util/qlpack.yml | 2 +-
shared/xml/CHANGELOG.md | 4 ++++
shared/xml/change-notes/released/1.0.4.md | 3 +++
shared/xml/codeql-pack.release.yml | 2 +-
shared/xml/qlpack.yml | 2 +-
shared/yaml/CHANGELOG.md | 4 ++++
shared/yaml/change-notes/released/1.0.4.md | 3 +++
shared/yaml/codeql-pack.release.yml | 2 +-
shared/yaml/qlpack.yml | 2 +-
swift/ql/lib/CHANGELOG.md | 10 +++++++++
.../lib/change-notes/2024-07-11-swift-ga.md | 4 ----
.../1.1.0.md} | 11 +++++++---
swift/ql/lib/codeql-pack.release.yml | 2 +-
swift/ql/lib/qlpack.yml | 2 +-
swift/ql/src/CHANGELOG.md | 4 ++++
swift/ql/src/change-notes/released/1.0.4.md | 3 +++
swift/ql/src/codeql-pack.release.yml | 2 +-
swift/ql/src/qlpack.yml | 2 +-
154 files changed, 406 insertions(+), 145 deletions(-)
delete mode 100644 cpp/ql/lib/change-notes/2024-07-10-newarrayexpr-arraysize.md
delete mode 100644 cpp/ql/lib/change-notes/2024-07-16-alert-provenance.md
rename cpp/ql/lib/change-notes/{2024-07-11-additional-builtin-support.md => released/1.3.0.md} (57%)
delete mode 100644 cpp/ql/src/change-notes/2024-07-08-unsafe-strncat-query.md
delete mode 100644 cpp/ql/src/change-notes/2024-07-11-iterator-to-expired-container-query.md
delete mode 100644 cpp/ql/src/change-notes/2024-07-16-unsigned-difference-expression-compared-zero-.md
create mode 100644 cpp/ql/src/change-notes/released/1.1.0.md
create mode 100644 csharp/ql/campaigns/Solorigate/lib/change-notes/released/1.7.21.md
create mode 100644 csharp/ql/campaigns/Solorigate/src/change-notes/released/1.7.21.md
create mode 100644 csharp/ql/lib/change-notes/released/1.0.4.md
create mode 100644 csharp/ql/src/change-notes/released/1.0.4.md
create mode 100644 go/ql/consistency-queries/change-notes/released/1.0.4.md
rename go/ql/lib/change-notes/{2024-07-08-fix-clear-sanitizer.md => released/1.1.3.md} (81%)
create mode 100644 go/ql/src/change-notes/released/1.0.4.md
create mode 100644 java/ql/automodel/src/change-notes/released/1.0.4.md
delete mode 100644 java/ql/lib/change-notes/2024-06-12-isandroid-deprecated.md
delete mode 100644 java/ql/lib/change-notes/2024-06-19-kotlin-2.0.20.md
delete mode 100644 java/ql/lib/change-notes/2024-06-25-java-tools-status.md
delete mode 100644 java/ql/lib/change-notes/2024-07-03-env-var-semmle-dist.md
delete mode 100644 java/ql/lib/change-notes/2024-07-11-FilePath-exists-sink.md
delete mode 100644 java/ql/lib/change-notes/2024-07-11-kotlin-ga.md
delete mode 100644 java/ql/lib/change-notes/2024-07-11-toByteArray-summary.md
create mode 100644 java/ql/lib/change-notes/released/2.0.0.md
rename java/ql/src/change-notes/{2024-07-07-android-application-heuristic-updated.md => released/1.1.1.md} (88%)
create mode 100644 javascript/ql/lib/change-notes/released/1.1.1.md
delete mode 100644 javascript/ql/src/change-notes/2024-06-19-insecure-helmet-config.md
rename javascript/ql/src/change-notes/{2024-07-08-functionality-from-untrusted-domain.md => released/1.1.0.md} (79%)
create mode 100644 misc/suite-helpers/change-notes/released/1.0.4.md
rename python/ql/lib/change-notes/{2024-06-24-cookie-header-writes.md => released/1.0.4.md} (65%)
create mode 100644 python/ql/src/change-notes/released/1.0.4.md
create mode 100644 ruby/ql/lib/change-notes/released/1.0.4.md
create mode 100644 ruby/ql/src/change-notes/released/1.0.4.md
create mode 100644 shared/controlflow/change-notes/released/1.0.4.md
create mode 100644 shared/dataflow/change-notes/released/1.0.4.md
create mode 100644 shared/mad/change-notes/released/1.0.4.md
create mode 100644 shared/rangeanalysis/change-notes/released/1.0.4.md
create mode 100644 shared/regex/change-notes/released/1.0.4.md
create mode 100644 shared/ssa/change-notes/released/1.0.4.md
create mode 100644 shared/threat-models/change-notes/released/1.0.4.md
create mode 100644 shared/tutorial/change-notes/released/1.0.4.md
create mode 100644 shared/typeflow/change-notes/released/1.0.4.md
create mode 100644 shared/typetracking/change-notes/released/1.0.4.md
create mode 100644 shared/typos/change-notes/released/1.0.4.md
create mode 100644 shared/util/change-notes/released/1.0.4.md
create mode 100644 shared/xml/change-notes/released/1.0.4.md
create mode 100644 shared/yaml/change-notes/released/1.0.4.md
delete mode 100644 swift/ql/lib/change-notes/2024-07-11-swift-ga.md
rename swift/ql/lib/change-notes/{2024-05-23-sensitive-data.md => released/1.1.0.md} (70%)
create mode 100644 swift/ql/src/change-notes/released/1.0.4.md
diff --git a/cpp/ql/lib/CHANGELOG.md b/cpp/ql/lib/CHANGELOG.md
index 61cbcd1318acd..9f01040830c11 100644
--- a/cpp/ql/lib/CHANGELOG.md
+++ b/cpp/ql/lib/CHANGELOG.md
@@ -1,3 +1,11 @@
+## 1.3.0
+
+### New Features
+
+* Models-as-data alert provenance information has been extended to the C/C++ language. Any qltests that include the edges relation in their output (for example, `.qlref`s that reference path-problem queries) will need to be have their expected output updated accordingly.
+* Added subclasses of `BuiltInOperations` for `__builtin_has_attribute`, `__builtin_is_corresponding_member`, `__builtin_is_pointer_interconvertible_with_class`, `__is_assignable_no_precondition_check`, `__is_bounded_array`, `__is_convertible`, `__is_corresponding_member`, `__is_nothrow_convertible`, `__is_pointer_interconvertible_with_class`, `__is_referenceable`, `__is_same_as`, `__is_trivially_copy_assignable`, `__is_unbounded_array`, `__is_valid_winrt_type`, `_is_win_class`, `__is_win_interface`, `__reference_binds_to_temporary`, `__reference_constructs_from_temporary`, and `__reference_converts_from_temporary`.
+* The class `NewArrayExpr` adds a predicate `getArraySize()` to allow a more convenient way to access the static size of the array when the extent is missing.
+
## 1.2.0
### New Features
diff --git a/cpp/ql/lib/change-notes/2024-07-10-newarrayexpr-arraysize.md b/cpp/ql/lib/change-notes/2024-07-10-newarrayexpr-arraysize.md
deleted file mode 100644
index 0a806c9324329..0000000000000
--- a/cpp/ql/lib/change-notes/2024-07-10-newarrayexpr-arraysize.md
+++ /dev/null
@@ -1,4 +0,0 @@
----
-category: feature
----
-* The class `NewArrayExpr` adds a predicate `getArraySize()` to allow a more convenient way to access the static size of the array when the extent is missing.
diff --git a/cpp/ql/lib/change-notes/2024-07-16-alert-provenance.md b/cpp/ql/lib/change-notes/2024-07-16-alert-provenance.md
deleted file mode 100644
index 3f773028073bb..0000000000000
--- a/cpp/ql/lib/change-notes/2024-07-16-alert-provenance.md
+++ /dev/null
@@ -1,4 +0,0 @@
----
-category: feature
----
-* Models-as-data alert provenance information has been extended to the C/C++ language. Any qltests that include the edges relation in their output (for example, `.qlref`s that reference path-problem queries) will need to be have their expected output updated accordingly.
diff --git a/cpp/ql/lib/change-notes/2024-07-11-additional-builtin-support.md b/cpp/ql/lib/change-notes/released/1.3.0.md
similarity index 57%
rename from cpp/ql/lib/change-notes/2024-07-11-additional-builtin-support.md
rename to cpp/ql/lib/change-notes/released/1.3.0.md
index f389283ad1e14..3c3010da96d32 100644
--- a/cpp/ql/lib/change-notes/2024-07-11-additional-builtin-support.md
+++ b/cpp/ql/lib/change-notes/released/1.3.0.md
@@ -1,4 +1,7 @@
----
-category: feature
----
+## 1.3.0
+
+### New Features
+
+* Models-as-data alert provenance information has been extended to the C/C++ language. Any qltests that include the edges relation in their output (for example, `.qlref`s that reference path-problem queries) will need to be have their expected output updated accordingly.
* Added subclasses of `BuiltInOperations` for `__builtin_has_attribute`, `__builtin_is_corresponding_member`, `__builtin_is_pointer_interconvertible_with_class`, `__is_assignable_no_precondition_check`, `__is_bounded_array`, `__is_convertible`, `__is_corresponding_member`, `__is_nothrow_convertible`, `__is_pointer_interconvertible_with_class`, `__is_referenceable`, `__is_same_as`, `__is_trivially_copy_assignable`, `__is_unbounded_array`, `__is_valid_winrt_type`, `_is_win_class`, `__is_win_interface`, `__reference_binds_to_temporary`, `__reference_constructs_from_temporary`, and `__reference_converts_from_temporary`.
+* The class `NewArrayExpr` adds a predicate `getArraySize()` to allow a more convenient way to access the static size of the array when the extent is missing.
diff --git a/cpp/ql/lib/codeql-pack.release.yml b/cpp/ql/lib/codeql-pack.release.yml
index 75430e73d1c4d..ec16350ed6fd9 100644
--- a/cpp/ql/lib/codeql-pack.release.yml
+++ b/cpp/ql/lib/codeql-pack.release.yml
@@ -1,2 +1,2 @@
---
-lastReleaseVersion: 1.2.0
+lastReleaseVersion: 1.3.0
diff --git a/cpp/ql/lib/qlpack.yml b/cpp/ql/lib/qlpack.yml
index 6b3f05d5f7c1a..aee0698f32a79 100644
--- a/cpp/ql/lib/qlpack.yml
+++ b/cpp/ql/lib/qlpack.yml
@@ -1,5 +1,5 @@
name: codeql/cpp-all
-version: 1.2.1-dev
+version: 1.3.0
groups: cpp
dbscheme: semmlecode.cpp.dbscheme
extractor: cpp
diff --git a/cpp/ql/src/CHANGELOG.md b/cpp/ql/src/CHANGELOG.md
index badaa459be17b..9f10be7db9094 100644
--- a/cpp/ql/src/CHANGELOG.md
+++ b/cpp/ql/src/CHANGELOG.md
@@ -1,3 +1,14 @@
+## 1.1.0
+
+### Query Metadata Changes
+
+* The precision of `cpp/iterator-to-expired-container` ("Iterator to expired container") has been increased to `high`. As a result, it will be run by default as part of the Code Scanning suite.
+* The precision of `cpp/unsafe-strncat` ("Potentially unsafe call to strncat") has been increased to `high`. As a result, it will be run by default as part of the Code Scanning suite.
+
+### Minor Analysis Improvements
+
+* The `cpp/unsigned-difference-expression-compared-zero` ("Unsigned difference expression compared to zero") query now produces fewer false positives.
+
## 1.0.3
No user-facing changes.
diff --git a/cpp/ql/src/change-notes/2024-07-08-unsafe-strncat-query.md b/cpp/ql/src/change-notes/2024-07-08-unsafe-strncat-query.md
deleted file mode 100644
index a85958bc6ba8f..0000000000000
--- a/cpp/ql/src/change-notes/2024-07-08-unsafe-strncat-query.md
+++ /dev/null
@@ -1,4 +0,0 @@
----
-category: queryMetadata
----
-* The precision of `cpp/unsafe-strncat` ("Potentially unsafe call to strncat") has been increased to `high`. As a result, it will be run by default as part of the Code Scanning suite.
diff --git a/cpp/ql/src/change-notes/2024-07-11-iterator-to-expired-container-query.md b/cpp/ql/src/change-notes/2024-07-11-iterator-to-expired-container-query.md
deleted file mode 100644
index 37d1f9eda4a91..0000000000000
--- a/cpp/ql/src/change-notes/2024-07-11-iterator-to-expired-container-query.md
+++ /dev/null
@@ -1,4 +0,0 @@
----
-category: queryMetadata
----
-* The precision of `cpp/iterator-to-expired-container` ("Iterator to expired container") has been increased to `high`. As a result, it will be run by default as part of the Code Scanning suite.
diff --git a/cpp/ql/src/change-notes/2024-07-16-unsigned-difference-expression-compared-zero-.md b/cpp/ql/src/change-notes/2024-07-16-unsigned-difference-expression-compared-zero-.md
deleted file mode 100644
index a4fb27acc4137..0000000000000
--- a/cpp/ql/src/change-notes/2024-07-16-unsigned-difference-expression-compared-zero-.md
+++ /dev/null
@@ -1,4 +0,0 @@
----
-category: minorAnalysis
----
-* The `cpp/unsigned-difference-expression-compared-zero` ("Unsigned difference expression compared to zero") query now produces fewer false positives.
diff --git a/cpp/ql/src/change-notes/released/1.1.0.md b/cpp/ql/src/change-notes/released/1.1.0.md
new file mode 100644
index 0000000000000..50e703a5814aa
--- /dev/null
+++ b/cpp/ql/src/change-notes/released/1.1.0.md
@@ -0,0 +1,10 @@
+## 1.1.0
+
+### Query Metadata Changes
+
+* The precision of `cpp/iterator-to-expired-container` ("Iterator to expired container") has been increased to `high`. As a result, it will be run by default as part of the Code Scanning suite.
+* The precision of `cpp/unsafe-strncat` ("Potentially unsafe call to strncat") has been increased to `high`. As a result, it will be run by default as part of the Code Scanning suite.
+
+### Minor Analysis Improvements
+
+* The `cpp/unsigned-difference-expression-compared-zero` ("Unsigned difference expression compared to zero") query now produces fewer false positives.
diff --git a/cpp/ql/src/codeql-pack.release.yml b/cpp/ql/src/codeql-pack.release.yml
index 06fa75b96cbce..2ac15439f561a 100644
--- a/cpp/ql/src/codeql-pack.release.yml
+++ b/cpp/ql/src/codeql-pack.release.yml
@@ -1,2 +1,2 @@
---
-lastReleaseVersion: 1.0.3
+lastReleaseVersion: 1.1.0
diff --git a/cpp/ql/src/qlpack.yml b/cpp/ql/src/qlpack.yml
index ec7e9e095edf1..179bbafe4ac89 100644
--- a/cpp/ql/src/qlpack.yml
+++ b/cpp/ql/src/qlpack.yml
@@ -1,5 +1,5 @@
name: codeql/cpp-queries
-version: 1.0.4-dev
+version: 1.1.0
groups:
- cpp
- queries
diff --git a/csharp/ql/campaigns/Solorigate/lib/CHANGELOG.md b/csharp/ql/campaigns/Solorigate/lib/CHANGELOG.md
index 4f04af923035b..503822fbd6847 100644
--- a/csharp/ql/campaigns/Solorigate/lib/CHANGELOG.md
+++ b/csharp/ql/campaigns/Solorigate/lib/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 1.7.21
+
+No user-facing changes.
+
## 1.7.20
No user-facing changes.
diff --git a/csharp/ql/campaigns/Solorigate/lib/change-notes/released/1.7.21.md b/csharp/ql/campaigns/Solorigate/lib/change-notes/released/1.7.21.md
new file mode 100644
index 0000000000000..bdd54f47083c9
--- /dev/null
+++ b/csharp/ql/campaigns/Solorigate/lib/change-notes/released/1.7.21.md
@@ -0,0 +1,3 @@
+## 1.7.21
+
+No user-facing changes.
diff --git a/csharp/ql/campaigns/Solorigate/lib/codeql-pack.release.yml b/csharp/ql/campaigns/Solorigate/lib/codeql-pack.release.yml
index 747131a0b2b8e..87eff681b88a7 100644
--- a/csharp/ql/campaigns/Solorigate/lib/codeql-pack.release.yml
+++ b/csharp/ql/campaigns/Solorigate/lib/codeql-pack.release.yml
@@ -1,2 +1,2 @@
---
-lastReleaseVersion: 1.7.20
+lastReleaseVersion: 1.7.21
diff --git a/csharp/ql/campaigns/Solorigate/lib/qlpack.yml b/csharp/ql/campaigns/Solorigate/lib/qlpack.yml
index 30856be18e231..593ee8b9125b3 100644
--- a/csharp/ql/campaigns/Solorigate/lib/qlpack.yml
+++ b/csharp/ql/campaigns/Solorigate/lib/qlpack.yml
@@ -1,5 +1,5 @@
name: codeql/csharp-solorigate-all
-version: 1.7.21-dev
+version: 1.7.21
groups:
- csharp
- solorigate
diff --git a/csharp/ql/campaigns/Solorigate/src/CHANGELOG.md b/csharp/ql/campaigns/Solorigate/src/CHANGELOG.md
index 4f04af923035b..503822fbd6847 100644
--- a/csharp/ql/campaigns/Solorigate/src/CHANGELOG.md
+++ b/csharp/ql/campaigns/Solorigate/src/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 1.7.21
+
+No user-facing changes.
+
## 1.7.20
No user-facing changes.
diff --git a/csharp/ql/campaigns/Solorigate/src/change-notes/released/1.7.21.md b/csharp/ql/campaigns/Solorigate/src/change-notes/released/1.7.21.md
new file mode 100644
index 0000000000000..bdd54f47083c9
--- /dev/null
+++ b/csharp/ql/campaigns/Solorigate/src/change-notes/released/1.7.21.md
@@ -0,0 +1,3 @@
+## 1.7.21
+
+No user-facing changes.
diff --git a/csharp/ql/campaigns/Solorigate/src/codeql-pack.release.yml b/csharp/ql/campaigns/Solorigate/src/codeql-pack.release.yml
index 747131a0b2b8e..87eff681b88a7 100644
--- a/csharp/ql/campaigns/Solorigate/src/codeql-pack.release.yml
+++ b/csharp/ql/campaigns/Solorigate/src/codeql-pack.release.yml
@@ -1,2 +1,2 @@
---
-lastReleaseVersion: 1.7.20
+lastReleaseVersion: 1.7.21
diff --git a/csharp/ql/campaigns/Solorigate/src/qlpack.yml b/csharp/ql/campaigns/Solorigate/src/qlpack.yml
index 434601dad84d6..3182e69d67255 100644
--- a/csharp/ql/campaigns/Solorigate/src/qlpack.yml
+++ b/csharp/ql/campaigns/Solorigate/src/qlpack.yml
@@ -1,5 +1,5 @@
name: codeql/csharp-solorigate-queries
-version: 1.7.21-dev
+version: 1.7.21
groups:
- csharp
- solorigate
diff --git a/csharp/ql/lib/CHANGELOG.md b/csharp/ql/lib/CHANGELOG.md
index 6abef1b2c046c..e8db033195148 100644
--- a/csharp/ql/lib/CHANGELOG.md
+++ b/csharp/ql/lib/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 1.0.4
+
+No user-facing changes.
+
## 1.0.3
No user-facing changes.
diff --git a/csharp/ql/lib/change-notes/released/1.0.4.md b/csharp/ql/lib/change-notes/released/1.0.4.md
new file mode 100644
index 0000000000000..d0255e750ff92
--- /dev/null
+++ b/csharp/ql/lib/change-notes/released/1.0.4.md
@@ -0,0 +1,3 @@
+## 1.0.4
+
+No user-facing changes.
diff --git a/csharp/ql/lib/codeql-pack.release.yml b/csharp/ql/lib/codeql-pack.release.yml
index 06fa75b96cbce..03f7ea71b58ee 100644
--- a/csharp/ql/lib/codeql-pack.release.yml
+++ b/csharp/ql/lib/codeql-pack.release.yml
@@ -1,2 +1,2 @@
---
-lastReleaseVersion: 1.0.3
+lastReleaseVersion: 1.0.4
diff --git a/csharp/ql/lib/qlpack.yml b/csharp/ql/lib/qlpack.yml
index 28319e6dc9961..97d1ed9a89213 100644
--- a/csharp/ql/lib/qlpack.yml
+++ b/csharp/ql/lib/qlpack.yml
@@ -1,5 +1,5 @@
name: codeql/csharp-all
-version: 1.0.4-dev
+version: 1.0.4
groups: csharp
dbscheme: semmlecode.csharp.dbscheme
extractor: csharp
diff --git a/csharp/ql/src/CHANGELOG.md b/csharp/ql/src/CHANGELOG.md
index 5edbf9229620e..0b2583745f1e9 100644
--- a/csharp/ql/src/CHANGELOG.md
+++ b/csharp/ql/src/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 1.0.4
+
+No user-facing changes.
+
## 1.0.3
No user-facing changes.
diff --git a/csharp/ql/src/change-notes/released/1.0.4.md b/csharp/ql/src/change-notes/released/1.0.4.md
new file mode 100644
index 0000000000000..d0255e750ff92
--- /dev/null
+++ b/csharp/ql/src/change-notes/released/1.0.4.md
@@ -0,0 +1,3 @@
+## 1.0.4
+
+No user-facing changes.
diff --git a/csharp/ql/src/codeql-pack.release.yml b/csharp/ql/src/codeql-pack.release.yml
index 06fa75b96cbce..03f7ea71b58ee 100644
--- a/csharp/ql/src/codeql-pack.release.yml
+++ b/csharp/ql/src/codeql-pack.release.yml
@@ -1,2 +1,2 @@
---
-lastReleaseVersion: 1.0.3
+lastReleaseVersion: 1.0.4
diff --git a/csharp/ql/src/qlpack.yml b/csharp/ql/src/qlpack.yml
index 1805c054d6b8d..73aed8329dece 100644
--- a/csharp/ql/src/qlpack.yml
+++ b/csharp/ql/src/qlpack.yml
@@ -1,5 +1,5 @@
name: codeql/csharp-queries
-version: 1.0.4-dev
+version: 1.0.4
groups:
- csharp
- queries
diff --git a/go/ql/consistency-queries/CHANGELOG.md b/go/ql/consistency-queries/CHANGELOG.md
index 86a6976ddc7ca..bdc66d5132249 100644
--- a/go/ql/consistency-queries/CHANGELOG.md
+++ b/go/ql/consistency-queries/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 1.0.4
+
+No user-facing changes.
+
## 1.0.3
No user-facing changes.
diff --git a/go/ql/consistency-queries/change-notes/released/1.0.4.md b/go/ql/consistency-queries/change-notes/released/1.0.4.md
new file mode 100644
index 0000000000000..d0255e750ff92
--- /dev/null
+++ b/go/ql/consistency-queries/change-notes/released/1.0.4.md
@@ -0,0 +1,3 @@
+## 1.0.4
+
+No user-facing changes.
diff --git a/go/ql/consistency-queries/codeql-pack.release.yml b/go/ql/consistency-queries/codeql-pack.release.yml
index 06fa75b96cbce..03f7ea71b58ee 100644
--- a/go/ql/consistency-queries/codeql-pack.release.yml
+++ b/go/ql/consistency-queries/codeql-pack.release.yml
@@ -1,2 +1,2 @@
---
-lastReleaseVersion: 1.0.3
+lastReleaseVersion: 1.0.4
diff --git a/go/ql/consistency-queries/qlpack.yml b/go/ql/consistency-queries/qlpack.yml
index 66c00f275bd7b..e3561decdf013 100644
--- a/go/ql/consistency-queries/qlpack.yml
+++ b/go/ql/consistency-queries/qlpack.yml
@@ -1,5 +1,5 @@
name: codeql-go-consistency-queries
-version: 1.0.4-dev
+version: 1.0.4
groups:
- go
- queries
diff --git a/go/ql/lib/CHANGELOG.md b/go/ql/lib/CHANGELOG.md
index 875c2809beb31..ed4e9b3750f83 100644
--- a/go/ql/lib/CHANGELOG.md
+++ b/go/ql/lib/CHANGELOG.md
@@ -1,3 +1,9 @@
+## 1.1.3
+
+### Minor Analysis Improvements
+
+* There was a bug which meant that the built-in function `clear` was considered as a sanitizer in some cases when it shouldn't have been. This has now been fixed, which may lead to more alerts.
+
## 1.1.2
### Minor Analysis Improvements
diff --git a/go/ql/lib/change-notes/2024-07-08-fix-clear-sanitizer.md b/go/ql/lib/change-notes/released/1.1.3.md
similarity index 81%
rename from go/ql/lib/change-notes/2024-07-08-fix-clear-sanitizer.md
rename to go/ql/lib/change-notes/released/1.1.3.md
index 711287f6a89ae..d97cd24d93ca8 100644
--- a/go/ql/lib/change-notes/2024-07-08-fix-clear-sanitizer.md
+++ b/go/ql/lib/change-notes/released/1.1.3.md
@@ -1,4 +1,5 @@
----
-category: minorAnalysis
----
+## 1.1.3
+
+### Minor Analysis Improvements
+
* There was a bug which meant that the built-in function `clear` was considered as a sanitizer in some cases when it shouldn't have been. This has now been fixed, which may lead to more alerts.
diff --git a/go/ql/lib/codeql-pack.release.yml b/go/ql/lib/codeql-pack.release.yml
index 53ab127707fc1..35e710ab1bf0d 100644
--- a/go/ql/lib/codeql-pack.release.yml
+++ b/go/ql/lib/codeql-pack.release.yml
@@ -1,2 +1,2 @@
---
-lastReleaseVersion: 1.1.2
+lastReleaseVersion: 1.1.3
diff --git a/go/ql/lib/qlpack.yml b/go/ql/lib/qlpack.yml
index 34fec580e8c0c..7e0622a6f07ca 100644
--- a/go/ql/lib/qlpack.yml
+++ b/go/ql/lib/qlpack.yml
@@ -1,5 +1,5 @@
name: codeql/go-all
-version: 1.1.3-dev
+version: 1.1.3
groups: go
dbscheme: go.dbscheme
extractor: go
diff --git a/go/ql/src/CHANGELOG.md b/go/ql/src/CHANGELOG.md
index f02101176a929..7248057e4089e 100644
--- a/go/ql/src/CHANGELOG.md
+++ b/go/ql/src/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 1.0.4
+
+No user-facing changes.
+
## 1.0.3
No user-facing changes.
diff --git a/go/ql/src/change-notes/released/1.0.4.md b/go/ql/src/change-notes/released/1.0.4.md
new file mode 100644
index 0000000000000..d0255e750ff92
--- /dev/null
+++ b/go/ql/src/change-notes/released/1.0.4.md
@@ -0,0 +1,3 @@
+## 1.0.4
+
+No user-facing changes.
diff --git a/go/ql/src/codeql-pack.release.yml b/go/ql/src/codeql-pack.release.yml
index 06fa75b96cbce..03f7ea71b58ee 100644
--- a/go/ql/src/codeql-pack.release.yml
+++ b/go/ql/src/codeql-pack.release.yml
@@ -1,2 +1,2 @@
---
-lastReleaseVersion: 1.0.3
+lastReleaseVersion: 1.0.4
diff --git a/go/ql/src/qlpack.yml b/go/ql/src/qlpack.yml
index 27c6eaf86a9bd..8438e3c589c73 100644
--- a/go/ql/src/qlpack.yml
+++ b/go/ql/src/qlpack.yml
@@ -1,5 +1,5 @@
name: codeql/go-queries
-version: 1.0.4-dev
+version: 1.0.4
groups:
- go
- queries
diff --git a/java/ql/automodel/src/CHANGELOG.md b/java/ql/automodel/src/CHANGELOG.md
index 6e2e78d0a6373..7ef174ca56a50 100644
--- a/java/ql/automodel/src/CHANGELOG.md
+++ b/java/ql/automodel/src/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 1.0.4
+
+No user-facing changes.
+
## 1.0.3
No user-facing changes.
diff --git a/java/ql/automodel/src/change-notes/released/1.0.4.md b/java/ql/automodel/src/change-notes/released/1.0.4.md
new file mode 100644
index 0000000000000..d0255e750ff92
--- /dev/null
+++ b/java/ql/automodel/src/change-notes/released/1.0.4.md
@@ -0,0 +1,3 @@
+## 1.0.4
+
+No user-facing changes.
diff --git a/java/ql/automodel/src/codeql-pack.release.yml b/java/ql/automodel/src/codeql-pack.release.yml
index 06fa75b96cbce..03f7ea71b58ee 100644
--- a/java/ql/automodel/src/codeql-pack.release.yml
+++ b/java/ql/automodel/src/codeql-pack.release.yml
@@ -1,2 +1,2 @@
---
-lastReleaseVersion: 1.0.3
+lastReleaseVersion: 1.0.4
diff --git a/java/ql/automodel/src/qlpack.yml b/java/ql/automodel/src/qlpack.yml
index ad247f25bf1bd..096cba6156aa2 100644
--- a/java/ql/automodel/src/qlpack.yml
+++ b/java/ql/automodel/src/qlpack.yml
@@ -1,5 +1,5 @@
name: codeql/java-automodel-queries
-version: 1.0.4-dev
+version: 1.0.4
groups:
- java
- automodel
diff --git a/java/ql/lib/CHANGELOG.md b/java/ql/lib/CHANGELOG.md
index d4ceec95093c6..365117374e6f4 100644
--- a/java/ql/lib/CHANGELOG.md
+++ b/java/ql/lib/CHANGELOG.md
@@ -1,3 +1,24 @@
+## 2.0.0
+
+### Breaking Changes
+
+* The Java extractor no longer supports the `SEMMLE_DIST` legacy environment variable.
+
+### Deprecated APIs
+
+* The predicate `isAndroid` from the module `semmle.code.java.security.AndroidCertificatePinningQuery` has been deprecated. Use `semmle.code.java.frameworks.android.Android::inAndroidApplication(File)` instead.
+
+### New Features
+
+* Kotlin support is now out of beta, and generally available
+* Kotlin versions up to 2.0.2\ *x* are now supported.
+
+### Minor Analysis Improvements
+
+* Added a path-injection sink for `hudson.FilePath.exists()`.
+* Added summary models for `org.apache.commons.io.IOUtils.toByteArray`.
+* Java build-mode `none` analyses now only report a warning on the CodeQL status page when there are significant analysis problems-- defined as 5% of expressions lacking a type, or 5% of call targets being unknown. Other messages reported on the status page are downgraded from warnings to notes and so are less prominent, but are still available for review.
+
## 1.1.2
### Minor Analysis Improvements
diff --git a/java/ql/lib/change-notes/2024-06-12-isandroid-deprecated.md b/java/ql/lib/change-notes/2024-06-12-isandroid-deprecated.md
deleted file mode 100644
index 3c1ab0de8e25c..0000000000000
--- a/java/ql/lib/change-notes/2024-06-12-isandroid-deprecated.md
+++ /dev/null
@@ -1,4 +0,0 @@
----
-category: deprecated
----
-* The predicate `isAndroid` from the module `semmle.code.java.security.AndroidCertificatePinningQuery` has been deprecated. Use `semmle.code.java.frameworks.android.Android::inAndroidApplication(File)` instead.
diff --git a/java/ql/lib/change-notes/2024-06-19-kotlin-2.0.20.md b/java/ql/lib/change-notes/2024-06-19-kotlin-2.0.20.md
deleted file mode 100644
index f9023051191b8..0000000000000
--- a/java/ql/lib/change-notes/2024-06-19-kotlin-2.0.20.md
+++ /dev/null
@@ -1,4 +0,0 @@
----
-category: feature
----
-* Kotlin versions up to 2.0.2\ *x* are now supported.
diff --git a/java/ql/lib/change-notes/2024-06-25-java-tools-status.md b/java/ql/lib/change-notes/2024-06-25-java-tools-status.md
deleted file mode 100644
index 67a72a12bb736..0000000000000
--- a/java/ql/lib/change-notes/2024-06-25-java-tools-status.md
+++ /dev/null
@@ -1,4 +0,0 @@
----
-category: minorAnalysis
----
-* Java build-mode `none` analyses now only report a warning on the CodeQL status page when there are significant analysis problems-- defined as 5% of expressions lacking a type, or 5% of call targets being unknown. Other messages reported on the status page are downgraded from warnings to notes and so are less prominent, but are still available for review.
diff --git a/java/ql/lib/change-notes/2024-07-03-env-var-semmle-dist.md b/java/ql/lib/change-notes/2024-07-03-env-var-semmle-dist.md
deleted file mode 100644
index 372bed1eb6623..0000000000000
--- a/java/ql/lib/change-notes/2024-07-03-env-var-semmle-dist.md
+++ /dev/null
@@ -1,4 +0,0 @@
----
-category: breaking
----
-* The Java extractor no longer supports the `SEMMLE_DIST` legacy environment variable.
diff --git a/java/ql/lib/change-notes/2024-07-11-FilePath-exists-sink.md b/java/ql/lib/change-notes/2024-07-11-FilePath-exists-sink.md
deleted file mode 100644
index 0c8f80cb71551..0000000000000
--- a/java/ql/lib/change-notes/2024-07-11-FilePath-exists-sink.md
+++ /dev/null
@@ -1,4 +0,0 @@
----
-category: minorAnalysis
----
-* Added a path-injection sink for `hudson.FilePath.exists()`.
diff --git a/java/ql/lib/change-notes/2024-07-11-kotlin-ga.md b/java/ql/lib/change-notes/2024-07-11-kotlin-ga.md
deleted file mode 100644
index 24d6c5d7d76c0..0000000000000
--- a/java/ql/lib/change-notes/2024-07-11-kotlin-ga.md
+++ /dev/null
@@ -1,4 +0,0 @@
----
-category: feature
----
-* Kotlin support is now out of beta, and generally available
diff --git a/java/ql/lib/change-notes/2024-07-11-toByteArray-summary.md b/java/ql/lib/change-notes/2024-07-11-toByteArray-summary.md
deleted file mode 100644
index b24905cb9e735..0000000000000
--- a/java/ql/lib/change-notes/2024-07-11-toByteArray-summary.md
+++ /dev/null
@@ -1,4 +0,0 @@
----
-category: minorAnalysis
----
-* Added summary models for `org.apache.commons.io.IOUtils.toByteArray`.
diff --git a/java/ql/lib/change-notes/released/2.0.0.md b/java/ql/lib/change-notes/released/2.0.0.md
new file mode 100644
index 0000000000000..c78ae3e78e3d6
--- /dev/null
+++ b/java/ql/lib/change-notes/released/2.0.0.md
@@ -0,0 +1,20 @@
+## 2.0.0
+
+### Breaking Changes
+
+* The Java extractor no longer supports the `SEMMLE_DIST` legacy environment variable.
+
+### Deprecated APIs
+
+* The predicate `isAndroid` from the module `semmle.code.java.security.AndroidCertificatePinningQuery` has been deprecated. Use `semmle.code.java.frameworks.android.Android::inAndroidApplication(File)` instead.
+
+### New Features
+
+* Kotlin support is now out of beta, and generally available
+* Kotlin versions up to 2.0.2\ *x* are now supported.
+
+### Minor Analysis Improvements
+
+* Added a path-injection sink for `hudson.FilePath.exists()`.
+* Added summary models for `org.apache.commons.io.IOUtils.toByteArray`.
+* Java build-mode `none` analyses now only report a warning on the CodeQL status page when there are significant analysis problems-- defined as 5% of expressions lacking a type, or 5% of call targets being unknown. Other messages reported on the status page are downgraded from warnings to notes and so are less prominent, but are still available for review.
diff --git a/java/ql/lib/codeql-pack.release.yml b/java/ql/lib/codeql-pack.release.yml
index 53ab127707fc1..0abe6ccede0f5 100644
--- a/java/ql/lib/codeql-pack.release.yml
+++ b/java/ql/lib/codeql-pack.release.yml
@@ -1,2 +1,2 @@
---
-lastReleaseVersion: 1.1.2
+lastReleaseVersion: 2.0.0
diff --git a/java/ql/lib/qlpack.yml b/java/ql/lib/qlpack.yml
index 9d64327d6d8f3..cf98ca82d81a7 100644
--- a/java/ql/lib/qlpack.yml
+++ b/java/ql/lib/qlpack.yml
@@ -1,5 +1,5 @@
name: codeql/java-all
-version: 1.1.3-dev
+version: 2.0.0
groups: java
dbscheme: config/semmlecode.dbscheme
extractor: java
diff --git a/java/ql/src/CHANGELOG.md b/java/ql/src/CHANGELOG.md
index 30ac37246bbda..687e54f3d9b5e 100644
--- a/java/ql/src/CHANGELOG.md
+++ b/java/ql/src/CHANGELOG.md
@@ -1,3 +1,9 @@
+## 1.1.1
+
+### Minor Analysis Improvements
+
+* The heuristic to enable certain Android queries has been improved. Now it ignores Android Manifests which don't define an activity, content provider or service. We also only consider files which are under a folder containing such an Android Manifest for these queries. This should remove some false positive alerts.
+
## 1.1.0
### Major Analysis Improvements
diff --git a/java/ql/src/change-notes/2024-07-07-android-application-heuristic-updated.md b/java/ql/src/change-notes/released/1.1.1.md
similarity index 88%
rename from java/ql/src/change-notes/2024-07-07-android-application-heuristic-updated.md
rename to java/ql/src/change-notes/released/1.1.1.md
index fbf24383c192d..e8403c4e15af7 100644
--- a/java/ql/src/change-notes/2024-07-07-android-application-heuristic-updated.md
+++ b/java/ql/src/change-notes/released/1.1.1.md
@@ -1,4 +1,5 @@
----
-category: minorAnalysis
----
+## 1.1.1
+
+### Minor Analysis Improvements
+
* The heuristic to enable certain Android queries has been improved. Now it ignores Android Manifests which don't define an activity, content provider or service. We also only consider files which are under a folder containing such an Android Manifest for these queries. This should remove some false positive alerts.
diff --git a/java/ql/src/codeql-pack.release.yml b/java/ql/src/codeql-pack.release.yml
index 2ac15439f561a..1a19084be3f75 100644
--- a/java/ql/src/codeql-pack.release.yml
+++ b/java/ql/src/codeql-pack.release.yml
@@ -1,2 +1,2 @@
---
-lastReleaseVersion: 1.1.0
+lastReleaseVersion: 1.1.1
diff --git a/java/ql/src/qlpack.yml b/java/ql/src/qlpack.yml
index 65236db5e5526..66b53f4693964 100644
--- a/java/ql/src/qlpack.yml
+++ b/java/ql/src/qlpack.yml
@@ -1,5 +1,5 @@
name: codeql/java-queries
-version: 1.1.1-dev
+version: 1.1.1
groups:
- java
- queries
diff --git a/javascript/ql/lib/CHANGELOG.md b/javascript/ql/lib/CHANGELOG.md
index c5df4d5fa2764..182f9a9685c5d 100644
--- a/javascript/ql/lib/CHANGELOG.md
+++ b/javascript/ql/lib/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 1.1.1
+
+No user-facing changes.
+
## 1.1.0
### Major Analysis Improvements
diff --git a/javascript/ql/lib/change-notes/released/1.1.1.md b/javascript/ql/lib/change-notes/released/1.1.1.md
new file mode 100644
index 0000000000000..7fb56d3661051
--- /dev/null
+++ b/javascript/ql/lib/change-notes/released/1.1.1.md
@@ -0,0 +1,3 @@
+## 1.1.1
+
+No user-facing changes.
diff --git a/javascript/ql/lib/codeql-pack.release.yml b/javascript/ql/lib/codeql-pack.release.yml
index 2ac15439f561a..1a19084be3f75 100644
--- a/javascript/ql/lib/codeql-pack.release.yml
+++ b/javascript/ql/lib/codeql-pack.release.yml
@@ -1,2 +1,2 @@
---
-lastReleaseVersion: 1.1.0
+lastReleaseVersion: 1.1.1
diff --git a/javascript/ql/lib/qlpack.yml b/javascript/ql/lib/qlpack.yml
index 23b7ec9240a6c..651f453bcede9 100644
--- a/javascript/ql/lib/qlpack.yml
+++ b/javascript/ql/lib/qlpack.yml
@@ -1,5 +1,5 @@
name: codeql/javascript-all
-version: 1.1.1-dev
+version: 1.1.1
groups: javascript
dbscheme: semmlecode.javascript.dbscheme
extractor: javascript
diff --git a/javascript/ql/src/CHANGELOG.md b/javascript/ql/src/CHANGELOG.md
index a3d09c1e02bad..0f30798ecd180 100644
--- a/javascript/ql/src/CHANGELOG.md
+++ b/javascript/ql/src/CHANGELOG.md
@@ -1,3 +1,17 @@
+## 1.1.0
+
+### New Queries
+
+* Added a new query, `js/insecure-helmet-configuration`, to detect instances where Helmet middleware is configured with important security features disabled.
+
+### Minor Analysis Improvements
+
+* Added a new query, `js/functionality-from-untrusted-domain`, which detects uses in HTML and JavaScript scripts from untrusted domains, including the `polyfill.io` content delivery network
+ * it can be extended to detect other compromised scripts using user-provided data extensions of the `untrustedDomain` predicate, which takes one string argument with the domain to warn on (and will warn on any subdomains too).
+* Modified existing query, `js/functionality-from-untrusted-source`, to allow adding this new query, but reusing the same logic
+ * Added the ability to use data extensions to require SRI on CDN hostnames using the `isCdnDomainWithCheckingRequired` predicate, which takes one string argument of the full hostname to require SRI for.
+* Created a new library, `semmle.javascript.security.FunctionalityFromUntrustedSource`, to support both queries.
+
## 1.0.3
### Minor Analysis Improvements
diff --git a/javascript/ql/src/change-notes/2024-06-19-insecure-helmet-config.md b/javascript/ql/src/change-notes/2024-06-19-insecure-helmet-config.md
deleted file mode 100644
index bee7ccb8fb94c..0000000000000
--- a/javascript/ql/src/change-notes/2024-06-19-insecure-helmet-config.md
+++ /dev/null
@@ -1,4 +0,0 @@
----
-category: newQuery
----
-* Added a new query, `js/insecure-helmet-configuration`, to detect instances where Helmet middleware is configured with important security features disabled.
diff --git a/javascript/ql/src/change-notes/2024-07-08-functionality-from-untrusted-domain.md b/javascript/ql/src/change-notes/released/1.1.0.md
similarity index 79%
rename from javascript/ql/src/change-notes/2024-07-08-functionality-from-untrusted-domain.md
rename to javascript/ql/src/change-notes/released/1.1.0.md
index 48a524c0d98f3..81883a0d44f05 100644
--- a/javascript/ql/src/change-notes/2024-07-08-functionality-from-untrusted-domain.md
+++ b/javascript/ql/src/change-notes/released/1.1.0.md
@@ -1,6 +1,11 @@
----
-category: minorAnalysis
----
+## 1.1.0
+
+### New Queries
+
+* Added a new query, `js/insecure-helmet-configuration`, to detect instances where Helmet middleware is configured with important security features disabled.
+
+### Minor Analysis Improvements
+
* Added a new query, `js/functionality-from-untrusted-domain`, which detects uses in HTML and JavaScript scripts from untrusted domains, including the `polyfill.io` content delivery network
* it can be extended to detect other compromised scripts using user-provided data extensions of the `untrustedDomain` predicate, which takes one string argument with the domain to warn on (and will warn on any subdomains too).
* Modified existing query, `js/functionality-from-untrusted-source`, to allow adding this new query, but reusing the same logic
diff --git a/javascript/ql/src/codeql-pack.release.yml b/javascript/ql/src/codeql-pack.release.yml
index 06fa75b96cbce..2ac15439f561a 100644
--- a/javascript/ql/src/codeql-pack.release.yml
+++ b/javascript/ql/src/codeql-pack.release.yml
@@ -1,2 +1,2 @@
---
-lastReleaseVersion: 1.0.3
+lastReleaseVersion: 1.1.0
diff --git a/javascript/ql/src/qlpack.yml b/javascript/ql/src/qlpack.yml
index 96db5feb0c84d..113e769b9fc0d 100644
--- a/javascript/ql/src/qlpack.yml
+++ b/javascript/ql/src/qlpack.yml
@@ -1,5 +1,5 @@
name: codeql/javascript-queries
-version: 1.0.4-dev
+version: 1.1.0
groups:
- javascript
- queries
diff --git a/misc/suite-helpers/CHANGELOG.md b/misc/suite-helpers/CHANGELOG.md
index d38834ba2efad..9f92ac20b2551 100644
--- a/misc/suite-helpers/CHANGELOG.md
+++ b/misc/suite-helpers/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 1.0.4
+
+No user-facing changes.
+
## 1.0.3
No user-facing changes.
diff --git a/misc/suite-helpers/change-notes/released/1.0.4.md b/misc/suite-helpers/change-notes/released/1.0.4.md
new file mode 100644
index 0000000000000..d0255e750ff92
--- /dev/null
+++ b/misc/suite-helpers/change-notes/released/1.0.4.md
@@ -0,0 +1,3 @@
+## 1.0.4
+
+No user-facing changes.
diff --git a/misc/suite-helpers/codeql-pack.release.yml b/misc/suite-helpers/codeql-pack.release.yml
index 06fa75b96cbce..03f7ea71b58ee 100644
--- a/misc/suite-helpers/codeql-pack.release.yml
+++ b/misc/suite-helpers/codeql-pack.release.yml
@@ -1,2 +1,2 @@
---
-lastReleaseVersion: 1.0.3
+lastReleaseVersion: 1.0.4
diff --git a/misc/suite-helpers/qlpack.yml b/misc/suite-helpers/qlpack.yml
index a8a38a7cbd3a9..14e15f3b9a998 100644
--- a/misc/suite-helpers/qlpack.yml
+++ b/misc/suite-helpers/qlpack.yml
@@ -1,4 +1,4 @@
name: codeql/suite-helpers
-version: 1.0.4-dev
+version: 1.0.4
groups: shared
warnOnImplicitThis: true
diff --git a/python/ql/lib/CHANGELOG.md b/python/ql/lib/CHANGELOG.md
index 65d784e6456f1..0b41146d49348 100644
--- a/python/ql/lib/CHANGELOG.md
+++ b/python/ql/lib/CHANGELOG.md
@@ -1,3 +1,9 @@
+## 1.0.4
+
+### Minor Analysis Improvements
+
+* Additional modelling has been added to detect cookie writes from direct writes to the `Set-Cookie` header have been added for several web frameworks.
+
## 1.0.3
### Minor Analysis Improvements
diff --git a/python/ql/lib/change-notes/2024-06-24-cookie-header-writes.md b/python/ql/lib/change-notes/released/1.0.4.md
similarity index 65%
rename from python/ql/lib/change-notes/2024-06-24-cookie-header-writes.md
rename to python/ql/lib/change-notes/released/1.0.4.md
index 583e0f44c0593..267019190ea88 100644
--- a/python/ql/lib/change-notes/2024-06-24-cookie-header-writes.md
+++ b/python/ql/lib/change-notes/released/1.0.4.md
@@ -1,4 +1,5 @@
----
-category: minorAnalysis
----
-* Additional modelling has been added to detect cookie writes from direct writes to the `Set-Cookie` header have been added for several web frameworks.
\ No newline at end of file
+## 1.0.4
+
+### Minor Analysis Improvements
+
+* Additional modelling has been added to detect cookie writes from direct writes to the `Set-Cookie` header have been added for several web frameworks.
diff --git a/python/ql/lib/codeql-pack.release.yml b/python/ql/lib/codeql-pack.release.yml
index 06fa75b96cbce..03f7ea71b58ee 100644
--- a/python/ql/lib/codeql-pack.release.yml
+++ b/python/ql/lib/codeql-pack.release.yml
@@ -1,2 +1,2 @@
---
-lastReleaseVersion: 1.0.3
+lastReleaseVersion: 1.0.4
diff --git a/python/ql/lib/qlpack.yml b/python/ql/lib/qlpack.yml
index f72b0c14f5b69..fdb646bad178b 100644
--- a/python/ql/lib/qlpack.yml
+++ b/python/ql/lib/qlpack.yml
@@ -1,5 +1,5 @@
name: codeql/python-all
-version: 1.0.4-dev
+version: 1.0.4
groups: python
dbscheme: semmlecode.python.dbscheme
extractor: python
diff --git a/python/ql/src/CHANGELOG.md b/python/ql/src/CHANGELOG.md
index 1015dd241444d..b386509bd9793 100644
--- a/python/ql/src/CHANGELOG.md
+++ b/python/ql/src/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 1.0.4
+
+No user-facing changes.
+
## 1.0.3
### Minor Analysis Improvements
diff --git a/python/ql/src/change-notes/released/1.0.4.md b/python/ql/src/change-notes/released/1.0.4.md
new file mode 100644
index 0000000000000..d0255e750ff92
--- /dev/null
+++ b/python/ql/src/change-notes/released/1.0.4.md
@@ -0,0 +1,3 @@
+## 1.0.4
+
+No user-facing changes.
diff --git a/python/ql/src/codeql-pack.release.yml b/python/ql/src/codeql-pack.release.yml
index 06fa75b96cbce..03f7ea71b58ee 100644
--- a/python/ql/src/codeql-pack.release.yml
+++ b/python/ql/src/codeql-pack.release.yml
@@ -1,2 +1,2 @@
---
-lastReleaseVersion: 1.0.3
+lastReleaseVersion: 1.0.4
diff --git a/python/ql/src/qlpack.yml b/python/ql/src/qlpack.yml
index e12dd98749562..698c52f9e8f66 100644
--- a/python/ql/src/qlpack.yml
+++ b/python/ql/src/qlpack.yml
@@ -1,5 +1,5 @@
name: codeql/python-queries
-version: 1.0.4-dev
+version: 1.0.4
groups:
- python
- queries
diff --git a/ruby/ql/lib/CHANGELOG.md b/ruby/ql/lib/CHANGELOG.md
index 140cdd2cdba66..865dc997f3a61 100644
--- a/ruby/ql/lib/CHANGELOG.md
+++ b/ruby/ql/lib/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 1.0.4
+
+No user-facing changes.
+
## 1.0.3
### Minor Analysis Improvements
diff --git a/ruby/ql/lib/change-notes/released/1.0.4.md b/ruby/ql/lib/change-notes/released/1.0.4.md
new file mode 100644
index 0000000000000..d0255e750ff92
--- /dev/null
+++ b/ruby/ql/lib/change-notes/released/1.0.4.md
@@ -0,0 +1,3 @@
+## 1.0.4
+
+No user-facing changes.
diff --git a/ruby/ql/lib/codeql-pack.release.yml b/ruby/ql/lib/codeql-pack.release.yml
index 06fa75b96cbce..03f7ea71b58ee 100644
--- a/ruby/ql/lib/codeql-pack.release.yml
+++ b/ruby/ql/lib/codeql-pack.release.yml
@@ -1,2 +1,2 @@
---
-lastReleaseVersion: 1.0.3
+lastReleaseVersion: 1.0.4
diff --git a/ruby/ql/lib/qlpack.yml b/ruby/ql/lib/qlpack.yml
index caf4ecc62ec4b..bf914c07196d9 100644
--- a/ruby/ql/lib/qlpack.yml
+++ b/ruby/ql/lib/qlpack.yml
@@ -1,5 +1,5 @@
name: codeql/ruby-all
-version: 1.0.4-dev
+version: 1.0.4
groups: ruby
extractor: ruby
dbscheme: ruby.dbscheme
diff --git a/ruby/ql/src/CHANGELOG.md b/ruby/ql/src/CHANGELOG.md
index 766deb435824b..ac5d0c7525c02 100644
--- a/ruby/ql/src/CHANGELOG.md
+++ b/ruby/ql/src/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 1.0.4
+
+No user-facing changes.
+
## 1.0.3
No user-facing changes.
diff --git a/ruby/ql/src/change-notes/released/1.0.4.md b/ruby/ql/src/change-notes/released/1.0.4.md
new file mode 100644
index 0000000000000..d0255e750ff92
--- /dev/null
+++ b/ruby/ql/src/change-notes/released/1.0.4.md
@@ -0,0 +1,3 @@
+## 1.0.4
+
+No user-facing changes.
diff --git a/ruby/ql/src/codeql-pack.release.yml b/ruby/ql/src/codeql-pack.release.yml
index 06fa75b96cbce..03f7ea71b58ee 100644
--- a/ruby/ql/src/codeql-pack.release.yml
+++ b/ruby/ql/src/codeql-pack.release.yml
@@ -1,2 +1,2 @@
---
-lastReleaseVersion: 1.0.3
+lastReleaseVersion: 1.0.4
diff --git a/ruby/ql/src/qlpack.yml b/ruby/ql/src/qlpack.yml
index c6503d479c3e9..3ef18acf2317f 100644
--- a/ruby/ql/src/qlpack.yml
+++ b/ruby/ql/src/qlpack.yml
@@ -1,5 +1,5 @@
name: codeql/ruby-queries
-version: 1.0.4-dev
+version: 1.0.4
groups:
- ruby
- queries
diff --git a/shared/controlflow/CHANGELOG.md b/shared/controlflow/CHANGELOG.md
index dab49cbe60775..047afa97e5104 100644
--- a/shared/controlflow/CHANGELOG.md
+++ b/shared/controlflow/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 1.0.4
+
+No user-facing changes.
+
## 1.0.3
No user-facing changes.
diff --git a/shared/controlflow/change-notes/released/1.0.4.md b/shared/controlflow/change-notes/released/1.0.4.md
new file mode 100644
index 0000000000000..d0255e750ff92
--- /dev/null
+++ b/shared/controlflow/change-notes/released/1.0.4.md
@@ -0,0 +1,3 @@
+## 1.0.4
+
+No user-facing changes.
diff --git a/shared/controlflow/codeql-pack.release.yml b/shared/controlflow/codeql-pack.release.yml
index 06fa75b96cbce..03f7ea71b58ee 100644
--- a/shared/controlflow/codeql-pack.release.yml
+++ b/shared/controlflow/codeql-pack.release.yml
@@ -1,2 +1,2 @@
---
-lastReleaseVersion: 1.0.3
+lastReleaseVersion: 1.0.4
diff --git a/shared/controlflow/qlpack.yml b/shared/controlflow/qlpack.yml
index 72d92972d099a..0b055d4c623df 100644
--- a/shared/controlflow/qlpack.yml
+++ b/shared/controlflow/qlpack.yml
@@ -1,5 +1,5 @@
name: codeql/controlflow
-version: 1.0.4-dev
+version: 1.0.4
groups: shared
library: true
dependencies:
diff --git a/shared/dataflow/CHANGELOG.md b/shared/dataflow/CHANGELOG.md
index ae88f0beac819..ca6c7165b9bf0 100644
--- a/shared/dataflow/CHANGELOG.md
+++ b/shared/dataflow/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 1.0.4
+
+No user-facing changes.
+
## 1.0.3
No user-facing changes.
diff --git a/shared/dataflow/change-notes/released/1.0.4.md b/shared/dataflow/change-notes/released/1.0.4.md
new file mode 100644
index 0000000000000..d0255e750ff92
--- /dev/null
+++ b/shared/dataflow/change-notes/released/1.0.4.md
@@ -0,0 +1,3 @@
+## 1.0.4
+
+No user-facing changes.
diff --git a/shared/dataflow/codeql-pack.release.yml b/shared/dataflow/codeql-pack.release.yml
index 06fa75b96cbce..03f7ea71b58ee 100644
--- a/shared/dataflow/codeql-pack.release.yml
+++ b/shared/dataflow/codeql-pack.release.yml
@@ -1,2 +1,2 @@
---
-lastReleaseVersion: 1.0.3
+lastReleaseVersion: 1.0.4
diff --git a/shared/dataflow/qlpack.yml b/shared/dataflow/qlpack.yml
index 16e7e9af0d2cb..283e277909d3b 100644
--- a/shared/dataflow/qlpack.yml
+++ b/shared/dataflow/qlpack.yml
@@ -1,5 +1,5 @@
name: codeql/dataflow
-version: 1.0.4-dev
+version: 1.0.4
groups: shared
library: true
dependencies:
diff --git a/shared/mad/CHANGELOG.md b/shared/mad/CHANGELOG.md
index 1b49bf2fb0689..8680f86e786b9 100644
--- a/shared/mad/CHANGELOG.md
+++ b/shared/mad/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 1.0.4
+
+No user-facing changes.
+
## 1.0.3
No user-facing changes.
diff --git a/shared/mad/change-notes/released/1.0.4.md b/shared/mad/change-notes/released/1.0.4.md
new file mode 100644
index 0000000000000..d0255e750ff92
--- /dev/null
+++ b/shared/mad/change-notes/released/1.0.4.md
@@ -0,0 +1,3 @@
+## 1.0.4
+
+No user-facing changes.
diff --git a/shared/mad/codeql-pack.release.yml b/shared/mad/codeql-pack.release.yml
index 06fa75b96cbce..03f7ea71b58ee 100644
--- a/shared/mad/codeql-pack.release.yml
+++ b/shared/mad/codeql-pack.release.yml
@@ -1,2 +1,2 @@
---
-lastReleaseVersion: 1.0.3
+lastReleaseVersion: 1.0.4
diff --git a/shared/mad/qlpack.yml b/shared/mad/qlpack.yml
index 3f35765b5d4b2..8167a79b21bc5 100644
--- a/shared/mad/qlpack.yml
+++ b/shared/mad/qlpack.yml
@@ -1,5 +1,5 @@
name: codeql/mad
-version: 1.0.4-dev
+version: 1.0.4
groups: shared
library: true
dependencies:
diff --git a/shared/rangeanalysis/CHANGELOG.md b/shared/rangeanalysis/CHANGELOG.md
index 5093ac17ebd2f..a33a857c90577 100644
--- a/shared/rangeanalysis/CHANGELOG.md
+++ b/shared/rangeanalysis/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 1.0.4
+
+No user-facing changes.
+
## 1.0.3
No user-facing changes.
diff --git a/shared/rangeanalysis/change-notes/released/1.0.4.md b/shared/rangeanalysis/change-notes/released/1.0.4.md
new file mode 100644
index 0000000000000..d0255e750ff92
--- /dev/null
+++ b/shared/rangeanalysis/change-notes/released/1.0.4.md
@@ -0,0 +1,3 @@
+## 1.0.4
+
+No user-facing changes.
diff --git a/shared/rangeanalysis/codeql-pack.release.yml b/shared/rangeanalysis/codeql-pack.release.yml
index 06fa75b96cbce..03f7ea71b58ee 100644
--- a/shared/rangeanalysis/codeql-pack.release.yml
+++ b/shared/rangeanalysis/codeql-pack.release.yml
@@ -1,2 +1,2 @@
---
-lastReleaseVersion: 1.0.3
+lastReleaseVersion: 1.0.4
diff --git a/shared/rangeanalysis/qlpack.yml b/shared/rangeanalysis/qlpack.yml
index 27fc3198a4d40..9490c61761c97 100644
--- a/shared/rangeanalysis/qlpack.yml
+++ b/shared/rangeanalysis/qlpack.yml
@@ -1,5 +1,5 @@
name: codeql/rangeanalysis
-version: 1.0.4-dev
+version: 1.0.4
groups: shared
library: true
dependencies:
diff --git a/shared/regex/CHANGELOG.md b/shared/regex/CHANGELOG.md
index bc4c3b902b9a7..d78925faba07e 100644
--- a/shared/regex/CHANGELOG.md
+++ b/shared/regex/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 1.0.4
+
+No user-facing changes.
+
## 1.0.3
No user-facing changes.
diff --git a/shared/regex/change-notes/released/1.0.4.md b/shared/regex/change-notes/released/1.0.4.md
new file mode 100644
index 0000000000000..d0255e750ff92
--- /dev/null
+++ b/shared/regex/change-notes/released/1.0.4.md
@@ -0,0 +1,3 @@
+## 1.0.4
+
+No user-facing changes.
diff --git a/shared/regex/codeql-pack.release.yml b/shared/regex/codeql-pack.release.yml
index 06fa75b96cbce..03f7ea71b58ee 100644
--- a/shared/regex/codeql-pack.release.yml
+++ b/shared/regex/codeql-pack.release.yml
@@ -1,2 +1,2 @@
---
-lastReleaseVersion: 1.0.3
+lastReleaseVersion: 1.0.4
diff --git a/shared/regex/qlpack.yml b/shared/regex/qlpack.yml
index 37f3735381177..b12651a803582 100644
--- a/shared/regex/qlpack.yml
+++ b/shared/regex/qlpack.yml
@@ -1,5 +1,5 @@
name: codeql/regex
-version: 1.0.4-dev
+version: 1.0.4
groups: shared
library: true
dependencies:
diff --git a/shared/ssa/CHANGELOG.md b/shared/ssa/CHANGELOG.md
index 397322fcfd8a9..1a64a39471c85 100644
--- a/shared/ssa/CHANGELOG.md
+++ b/shared/ssa/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 1.0.4
+
+No user-facing changes.
+
## 1.0.3
No user-facing changes.
diff --git a/shared/ssa/change-notes/released/1.0.4.md b/shared/ssa/change-notes/released/1.0.4.md
new file mode 100644
index 0000000000000..d0255e750ff92
--- /dev/null
+++ b/shared/ssa/change-notes/released/1.0.4.md
@@ -0,0 +1,3 @@
+## 1.0.4
+
+No user-facing changes.
diff --git a/shared/ssa/codeql-pack.release.yml b/shared/ssa/codeql-pack.release.yml
index 06fa75b96cbce..03f7ea71b58ee 100644
--- a/shared/ssa/codeql-pack.release.yml
+++ b/shared/ssa/codeql-pack.release.yml
@@ -1,2 +1,2 @@
---
-lastReleaseVersion: 1.0.3
+lastReleaseVersion: 1.0.4
diff --git a/shared/ssa/qlpack.yml b/shared/ssa/qlpack.yml
index ed7467eebf462..efdee4d845a19 100644
--- a/shared/ssa/qlpack.yml
+++ b/shared/ssa/qlpack.yml
@@ -1,5 +1,5 @@
name: codeql/ssa
-version: 1.0.4-dev
+version: 1.0.4
groups: shared
library: true
dependencies:
diff --git a/shared/threat-models/CHANGELOG.md b/shared/threat-models/CHANGELOG.md
index 86a6976ddc7ca..bdc66d5132249 100644
--- a/shared/threat-models/CHANGELOG.md
+++ b/shared/threat-models/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 1.0.4
+
+No user-facing changes.
+
## 1.0.3
No user-facing changes.
diff --git a/shared/threat-models/change-notes/released/1.0.4.md b/shared/threat-models/change-notes/released/1.0.4.md
new file mode 100644
index 0000000000000..d0255e750ff92
--- /dev/null
+++ b/shared/threat-models/change-notes/released/1.0.4.md
@@ -0,0 +1,3 @@
+## 1.0.4
+
+No user-facing changes.
diff --git a/shared/threat-models/codeql-pack.release.yml b/shared/threat-models/codeql-pack.release.yml
index 06fa75b96cbce..03f7ea71b58ee 100644
--- a/shared/threat-models/codeql-pack.release.yml
+++ b/shared/threat-models/codeql-pack.release.yml
@@ -1,2 +1,2 @@
---
-lastReleaseVersion: 1.0.3
+lastReleaseVersion: 1.0.4
diff --git a/shared/threat-models/qlpack.yml b/shared/threat-models/qlpack.yml
index 1f80ebd498315..fc944afcd9c51 100644
--- a/shared/threat-models/qlpack.yml
+++ b/shared/threat-models/qlpack.yml
@@ -1,5 +1,5 @@
name: codeql/threat-models
-version: 1.0.4-dev
+version: 1.0.4
library: true
groups: shared
dataExtensions:
diff --git a/shared/tutorial/CHANGELOG.md b/shared/tutorial/CHANGELOG.md
index 6212f4cebc70f..ad8f62a4e9d5c 100644
--- a/shared/tutorial/CHANGELOG.md
+++ b/shared/tutorial/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 1.0.4
+
+No user-facing changes.
+
## 1.0.3
No user-facing changes.
diff --git a/shared/tutorial/change-notes/released/1.0.4.md b/shared/tutorial/change-notes/released/1.0.4.md
new file mode 100644
index 0000000000000..d0255e750ff92
--- /dev/null
+++ b/shared/tutorial/change-notes/released/1.0.4.md
@@ -0,0 +1,3 @@
+## 1.0.4
+
+No user-facing changes.
diff --git a/shared/tutorial/codeql-pack.release.yml b/shared/tutorial/codeql-pack.release.yml
index 06fa75b96cbce..03f7ea71b58ee 100644
--- a/shared/tutorial/codeql-pack.release.yml
+++ b/shared/tutorial/codeql-pack.release.yml
@@ -1,2 +1,2 @@
---
-lastReleaseVersion: 1.0.3
+lastReleaseVersion: 1.0.4
diff --git a/shared/tutorial/qlpack.yml b/shared/tutorial/qlpack.yml
index 86c983bb08091..eb3fbc4b6f686 100644
--- a/shared/tutorial/qlpack.yml
+++ b/shared/tutorial/qlpack.yml
@@ -1,7 +1,7 @@
name: codeql/tutorial
description: Library for the CodeQL detective tutorials, helping new users learn to
write CodeQL queries.
-version: 1.0.4-dev
+version: 1.0.4
groups: shared
library: true
warnOnImplicitThis: true
diff --git a/shared/typeflow/CHANGELOG.md b/shared/typeflow/CHANGELOG.md
index 4cf16f9cb1e6c..b9366dadb5c1b 100644
--- a/shared/typeflow/CHANGELOG.md
+++ b/shared/typeflow/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 1.0.4
+
+No user-facing changes.
+
## 1.0.3
No user-facing changes.
diff --git a/shared/typeflow/change-notes/released/1.0.4.md b/shared/typeflow/change-notes/released/1.0.4.md
new file mode 100644
index 0000000000000..d0255e750ff92
--- /dev/null
+++ b/shared/typeflow/change-notes/released/1.0.4.md
@@ -0,0 +1,3 @@
+## 1.0.4
+
+No user-facing changes.
diff --git a/shared/typeflow/codeql-pack.release.yml b/shared/typeflow/codeql-pack.release.yml
index 06fa75b96cbce..03f7ea71b58ee 100644
--- a/shared/typeflow/codeql-pack.release.yml
+++ b/shared/typeflow/codeql-pack.release.yml
@@ -1,2 +1,2 @@
---
-lastReleaseVersion: 1.0.3
+lastReleaseVersion: 1.0.4
diff --git a/shared/typeflow/qlpack.yml b/shared/typeflow/qlpack.yml
index a7590994015b2..4f43727f40dab 100644
--- a/shared/typeflow/qlpack.yml
+++ b/shared/typeflow/qlpack.yml
@@ -1,5 +1,5 @@
name: codeql/typeflow
-version: 1.0.4-dev
+version: 1.0.4
groups: shared
library: true
dependencies:
diff --git a/shared/typetracking/CHANGELOG.md b/shared/typetracking/CHANGELOG.md
index 7a288c03bd9b2..d17f150b27b2f 100644
--- a/shared/typetracking/CHANGELOG.md
+++ b/shared/typetracking/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 1.0.4
+
+No user-facing changes.
+
## 1.0.3
No user-facing changes.
diff --git a/shared/typetracking/change-notes/released/1.0.4.md b/shared/typetracking/change-notes/released/1.0.4.md
new file mode 100644
index 0000000000000..d0255e750ff92
--- /dev/null
+++ b/shared/typetracking/change-notes/released/1.0.4.md
@@ -0,0 +1,3 @@
+## 1.0.4
+
+No user-facing changes.
diff --git a/shared/typetracking/codeql-pack.release.yml b/shared/typetracking/codeql-pack.release.yml
index 06fa75b96cbce..03f7ea71b58ee 100644
--- a/shared/typetracking/codeql-pack.release.yml
+++ b/shared/typetracking/codeql-pack.release.yml
@@ -1,2 +1,2 @@
---
-lastReleaseVersion: 1.0.3
+lastReleaseVersion: 1.0.4
diff --git a/shared/typetracking/qlpack.yml b/shared/typetracking/qlpack.yml
index b83dc55905776..14b58f18a5596 100644
--- a/shared/typetracking/qlpack.yml
+++ b/shared/typetracking/qlpack.yml
@@ -1,5 +1,5 @@
name: codeql/typetracking
-version: 1.0.4-dev
+version: 1.0.4
groups: shared
library: true
dependencies:
diff --git a/shared/typos/CHANGELOG.md b/shared/typos/CHANGELOG.md
index 27be8dccdaad0..d323c0974fe2e 100644
--- a/shared/typos/CHANGELOG.md
+++ b/shared/typos/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 1.0.4
+
+No user-facing changes.
+
## 1.0.3
No user-facing changes.
diff --git a/shared/typos/change-notes/released/1.0.4.md b/shared/typos/change-notes/released/1.0.4.md
new file mode 100644
index 0000000000000..d0255e750ff92
--- /dev/null
+++ b/shared/typos/change-notes/released/1.0.4.md
@@ -0,0 +1,3 @@
+## 1.0.4
+
+No user-facing changes.
diff --git a/shared/typos/codeql-pack.release.yml b/shared/typos/codeql-pack.release.yml
index 06fa75b96cbce..03f7ea71b58ee 100644
--- a/shared/typos/codeql-pack.release.yml
+++ b/shared/typos/codeql-pack.release.yml
@@ -1,2 +1,2 @@
---
-lastReleaseVersion: 1.0.3
+lastReleaseVersion: 1.0.4
diff --git a/shared/typos/qlpack.yml b/shared/typos/qlpack.yml
index 459e9b92621b8..353c40e472edb 100644
--- a/shared/typos/qlpack.yml
+++ b/shared/typos/qlpack.yml
@@ -1,5 +1,5 @@
name: codeql/typos
-version: 1.0.4-dev
+version: 1.0.4
groups: shared
library: true
warnOnImplicitThis: true
diff --git a/shared/util/CHANGELOG.md b/shared/util/CHANGELOG.md
index b098bee611b18..6042620d77cb8 100644
--- a/shared/util/CHANGELOG.md
+++ b/shared/util/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 1.0.4
+
+No user-facing changes.
+
## 1.0.3
No user-facing changes.
diff --git a/shared/util/change-notes/released/1.0.4.md b/shared/util/change-notes/released/1.0.4.md
new file mode 100644
index 0000000000000..d0255e750ff92
--- /dev/null
+++ b/shared/util/change-notes/released/1.0.4.md
@@ -0,0 +1,3 @@
+## 1.0.4
+
+No user-facing changes.
diff --git a/shared/util/codeql-pack.release.yml b/shared/util/codeql-pack.release.yml
index 06fa75b96cbce..03f7ea71b58ee 100644
--- a/shared/util/codeql-pack.release.yml
+++ b/shared/util/codeql-pack.release.yml
@@ -1,2 +1,2 @@
---
-lastReleaseVersion: 1.0.3
+lastReleaseVersion: 1.0.4
diff --git a/shared/util/qlpack.yml b/shared/util/qlpack.yml
index 4df8f4c4e46ca..a4fcfad3f4b0e 100644
--- a/shared/util/qlpack.yml
+++ b/shared/util/qlpack.yml
@@ -1,5 +1,5 @@
name: codeql/util
-version: 1.0.4-dev
+version: 1.0.4
groups: shared
library: true
dependencies: null
diff --git a/shared/xml/CHANGELOG.md b/shared/xml/CHANGELOG.md
index 36b6e75f80335..1323436e6b2fe 100644
--- a/shared/xml/CHANGELOG.md
+++ b/shared/xml/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 1.0.4
+
+No user-facing changes.
+
## 1.0.3
No user-facing changes.
diff --git a/shared/xml/change-notes/released/1.0.4.md b/shared/xml/change-notes/released/1.0.4.md
new file mode 100644
index 0000000000000..d0255e750ff92
--- /dev/null
+++ b/shared/xml/change-notes/released/1.0.4.md
@@ -0,0 +1,3 @@
+## 1.0.4
+
+No user-facing changes.
diff --git a/shared/xml/codeql-pack.release.yml b/shared/xml/codeql-pack.release.yml
index 06fa75b96cbce..03f7ea71b58ee 100644
--- a/shared/xml/codeql-pack.release.yml
+++ b/shared/xml/codeql-pack.release.yml
@@ -1,2 +1,2 @@
---
-lastReleaseVersion: 1.0.3
+lastReleaseVersion: 1.0.4
diff --git a/shared/xml/qlpack.yml b/shared/xml/qlpack.yml
index 832ce27a19c19..f23031247414f 100644
--- a/shared/xml/qlpack.yml
+++ b/shared/xml/qlpack.yml
@@ -1,5 +1,5 @@
name: codeql/xml
-version: 1.0.4-dev
+version: 1.0.4
groups: shared
library: true
dependencies:
diff --git a/shared/yaml/CHANGELOG.md b/shared/yaml/CHANGELOG.md
index 49b8a5aeb8c8f..cd2c2e92ddfd3 100644
--- a/shared/yaml/CHANGELOG.md
+++ b/shared/yaml/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 1.0.4
+
+No user-facing changes.
+
## 1.0.3
No user-facing changes.
diff --git a/shared/yaml/change-notes/released/1.0.4.md b/shared/yaml/change-notes/released/1.0.4.md
new file mode 100644
index 0000000000000..d0255e750ff92
--- /dev/null
+++ b/shared/yaml/change-notes/released/1.0.4.md
@@ -0,0 +1,3 @@
+## 1.0.4
+
+No user-facing changes.
diff --git a/shared/yaml/codeql-pack.release.yml b/shared/yaml/codeql-pack.release.yml
index 06fa75b96cbce..03f7ea71b58ee 100644
--- a/shared/yaml/codeql-pack.release.yml
+++ b/shared/yaml/codeql-pack.release.yml
@@ -1,2 +1,2 @@
---
-lastReleaseVersion: 1.0.3
+lastReleaseVersion: 1.0.4
diff --git a/shared/yaml/qlpack.yml b/shared/yaml/qlpack.yml
index 57b7890f9bbcb..6135b64ec8302 100644
--- a/shared/yaml/qlpack.yml
+++ b/shared/yaml/qlpack.yml
@@ -1,5 +1,5 @@
name: codeql/yaml
-version: 1.0.4-dev
+version: 1.0.4
groups: shared
library: true
warnOnImplicitThis: true
diff --git a/swift/ql/lib/CHANGELOG.md b/swift/ql/lib/CHANGELOG.md
index 0630a303d73dd..21e8b74bb0233 100644
--- a/swift/ql/lib/CHANGELOG.md
+++ b/swift/ql/lib/CHANGELOG.md
@@ -1,3 +1,13 @@
+## 1.1.0
+
+### New Features
+
+* Swift support is now out of beta, and generally available.
+
+### Minor Analysis Improvements
+
+* Additional heuristics for sensitive private information have been added to the `SensitiveExprs.qll` library, improving coverage for credit card and social security numbers. This may result in additional results for queries that use sensitive data such as `swift/cleartext-transmission`.
+
## 1.0.3
No user-facing changes.
diff --git a/swift/ql/lib/change-notes/2024-07-11-swift-ga.md b/swift/ql/lib/change-notes/2024-07-11-swift-ga.md
deleted file mode 100644
index e50a30741574f..0000000000000
--- a/swift/ql/lib/change-notes/2024-07-11-swift-ga.md
+++ /dev/null
@@ -1,4 +0,0 @@
----
-category: feature
----
-* Swift support is now out of beta, and generally available.
diff --git a/swift/ql/lib/change-notes/2024-05-23-sensitive-data.md b/swift/ql/lib/change-notes/released/1.1.0.md
similarity index 70%
rename from swift/ql/lib/change-notes/2024-05-23-sensitive-data.md
rename to swift/ql/lib/change-notes/released/1.1.0.md
index f42901c458956..fd8955658fc52 100644
--- a/swift/ql/lib/change-notes/2024-05-23-sensitive-data.md
+++ b/swift/ql/lib/change-notes/released/1.1.0.md
@@ -1,4 +1,9 @@
----
-category: minorAnalysis
----
+## 1.1.0
+
+### New Features
+
+* Swift support is now out of beta, and generally available.
+
+### Minor Analysis Improvements
+
* Additional heuristics for sensitive private information have been added to the `SensitiveExprs.qll` library, improving coverage for credit card and social security numbers. This may result in additional results for queries that use sensitive data such as `swift/cleartext-transmission`.
diff --git a/swift/ql/lib/codeql-pack.release.yml b/swift/ql/lib/codeql-pack.release.yml
index 06fa75b96cbce..2ac15439f561a 100644
--- a/swift/ql/lib/codeql-pack.release.yml
+++ b/swift/ql/lib/codeql-pack.release.yml
@@ -1,2 +1,2 @@
---
-lastReleaseVersion: 1.0.3
+lastReleaseVersion: 1.1.0
diff --git a/swift/ql/lib/qlpack.yml b/swift/ql/lib/qlpack.yml
index c6bd37e621525..cbb2fa19bf562 100644
--- a/swift/ql/lib/qlpack.yml
+++ b/swift/ql/lib/qlpack.yml
@@ -1,5 +1,5 @@
name: codeql/swift-all
-version: 1.0.4-dev
+version: 1.1.0
groups: swift
extractor: swift
dbscheme: swift.dbscheme
diff --git a/swift/ql/src/CHANGELOG.md b/swift/ql/src/CHANGELOG.md
index f08ae688531c8..ca26ff94f225e 100644
--- a/swift/ql/src/CHANGELOG.md
+++ b/swift/ql/src/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 1.0.4
+
+No user-facing changes.
+
## 1.0.3
No user-facing changes.
diff --git a/swift/ql/src/change-notes/released/1.0.4.md b/swift/ql/src/change-notes/released/1.0.4.md
new file mode 100644
index 0000000000000..d0255e750ff92
--- /dev/null
+++ b/swift/ql/src/change-notes/released/1.0.4.md
@@ -0,0 +1,3 @@
+## 1.0.4
+
+No user-facing changes.
diff --git a/swift/ql/src/codeql-pack.release.yml b/swift/ql/src/codeql-pack.release.yml
index 06fa75b96cbce..03f7ea71b58ee 100644
--- a/swift/ql/src/codeql-pack.release.yml
+++ b/swift/ql/src/codeql-pack.release.yml
@@ -1,2 +1,2 @@
---
-lastReleaseVersion: 1.0.3
+lastReleaseVersion: 1.0.4
diff --git a/swift/ql/src/qlpack.yml b/swift/ql/src/qlpack.yml
index 62409f64983c1..bcd1861583a9f 100644
--- a/swift/ql/src/qlpack.yml
+++ b/swift/ql/src/qlpack.yml
@@ -1,5 +1,5 @@
name: codeql/swift-queries
-version: 1.0.4-dev
+version: 1.0.4
groups:
- swift
- queries
From 999fb07931406a8072c5ace2ae108ae3082c2310 Mon Sep 17 00:00:00 2001
From: Mathias Vorreiter Pedersen
Date: Mon, 22 Jul 2024 16:19:19 +0100
Subject: [PATCH 064/140] C++: Add more alias models.
---
cpp/ql/lib/semmle/code/cpp/models/Models.qll | 5 +
.../cpp/models/implementations/Iterator.qll | 69 +++-
.../cpp/models/implementations/Printf.qll | 23 +-
.../models/implementations/StdAlgorithm.qll | 115 ++++++
.../models/implementations/StdAllocator.qll | 256 +++++++++++++
.../models/implementations/StdContainer.qll | 339 +++++++++++++++++-
.../models/implementations/StdException.qll | 38 ++
.../models/implementations/StdFunction.qll | 53 +++
.../cpp/models/implementations/StdMap.qll | 97 ++++-
.../cpp/models/implementations/StdMath.qll | 98 +++++
.../cpp/models/implementations/StdPair.qll | 72 +++-
.../cpp/models/implementations/StdString.qll | 167 ++++++++-
12 files changed, 1314 insertions(+), 18 deletions(-)
create mode 100644 cpp/ql/lib/semmle/code/cpp/models/implementations/StdAlgorithm.qll
create mode 100644 cpp/ql/lib/semmle/code/cpp/models/implementations/StdAllocator.qll
create mode 100644 cpp/ql/lib/semmle/code/cpp/models/implementations/StdException.qll
create mode 100644 cpp/ql/lib/semmle/code/cpp/models/implementations/StdFunction.qll
create mode 100644 cpp/ql/lib/semmle/code/cpp/models/implementations/StdMath.qll
diff --git a/cpp/ql/lib/semmle/code/cpp/models/Models.qll b/cpp/ql/lib/semmle/code/cpp/models/Models.qll
index 0b104e5e936c3..90a97777d8fb8 100644
--- a/cpp/ql/lib/semmle/code/cpp/models/Models.qll
+++ b/cpp/ql/lib/semmle/code/cpp/models/Models.qll
@@ -27,6 +27,11 @@ private import implementations.StdPair
private import implementations.StdMap
private import implementations.StdSet
private import implementations.StdString
+private import implementations.StdFunction
+private import implementations.StdException
+private import implementations.StdAllocator
+private import implementations.StdAlgorithm
+private import implementations.StdMath
private import implementations.Swap
private import implementations.GetDelim
private import implementations.SmartPointer
diff --git a/cpp/ql/lib/semmle/code/cpp/models/implementations/Iterator.qll b/cpp/ql/lib/semmle/code/cpp/models/implementations/Iterator.qll
index a016210de5a04..8a1901a3c8c36 100644
--- a/cpp/ql/lib/semmle/code/cpp/models/implementations/Iterator.qll
+++ b/cpp/ql/lib/semmle/code/cpp/models/implementations/Iterator.qll
@@ -86,6 +86,41 @@ private class StdIterator extends Iterator, Class {
override Type getValueType() { result = this.getTemplateArgument(1).(Type).getUnderlyingType() }
}
+private class StdReverseIterator extends Iterator, Class {
+ StdReverseIterator() { this.hasQualifiedName(["std", "bsl"], "reverse_iterator") }
+
+ override Type getValueType() { result = this.getTemplateArgument(1).(Type).getUnderlyingType() }
+}
+
+private class StdIstreamBufIterator extends Iterator, Class {
+ StdIstreamBufIterator() { this.hasQualifiedName(["std", "bsl"], ["istreambuf_iterator"]) }
+
+ override Type getValueType() { result = this.getTemplateArgument(1).(Type).getUnderlyingType() }
+}
+
+private class StdIstreambufIteratorConstructor extends Constructor, SideEffectFunction,
+ AliasFunction
+{
+ StdIstreambufIteratorConstructor() { this.getDeclaringType() instanceof StdIstreamBufIterator }
+
+ override predicate parameterNeverEscapes(int index) { index = -1 }
+
+ override predicate parameterEscapesOnlyViaReturn(int index) { none() }
+
+ override predicate hasOnlySpecificReadSideEffects() { any() }
+
+ override predicate hasOnlySpecificWriteSideEffects() { any() }
+
+ override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
+ i = -1 and buffer = false and mustWrite = true
+ }
+
+ override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
+ this.getParameter(i).getUnspecifiedType() instanceof ReferenceType and
+ buffer = false
+ }
+}
+
/**
* Gets the `FunctionInput` corresponding to an iterator parameter to
* user-defined operator `op`, at `index`.
@@ -579,23 +614,43 @@ private class IteratorAssignmentMemberOperatorModel extends IteratorAssignmentMe
override predicate parameterEscapesOnlyViaReturn(int index) { index = -1 }
}
+private string beginName() {
+ result = ["begin", "cbegin", "rbegin", "crbegin", "before_begin", "cbefore_begin"]
+}
+
/**
* A `begin` member function, or a related function, that returns an iterator.
*/
-class BeginFunction extends MemberFunction {
+class BeginFunction extends Function {
BeginFunction() {
- this.hasName(["begin", "cbegin", "rbegin", "crbegin", "before_begin", "cbefore_begin"]) and
- this.getType().getUnspecifiedType() instanceof Iterator
+ this.getUnspecifiedType() instanceof Iterator and
+ (
+ this.hasName(beginName()) and
+ this instanceof MemberFunction
+ or
+ this.hasGlobalOrStdOrBslName(beginName()) and
+ not this instanceof MemberFunction and
+ this.getNumberOfParameters() = 1
+ )
}
}
+private string endName() { result = ["end", "cend", "rend", "crend"] }
+
/**
* An `end` member function, or a related function, that returns an iterator.
*/
-class EndFunction extends MemberFunction {
+class EndFunction extends Function {
EndFunction() {
- this.hasName(["end", "cend", "rend", "crend"]) and
- this.getType().getUnspecifiedType() instanceof Iterator
+ this.getUnspecifiedType() instanceof Iterator and
+ (
+ this.hasName(endName()) and
+ this instanceof MemberFunction
+ or
+ this.hasGlobalOrStdOrBslName(endName()) and
+ this instanceof MemberFunction and
+ this.getNumberOfParameters() = 1
+ )
}
}
@@ -603,7 +658,7 @@ class EndFunction extends MemberFunction {
* A `begin` or `end` member function, or a related member function, that
* returns an iterator.
*/
-class BeginOrEndFunction extends MemberFunction {
+class BeginOrEndFunction extends Function {
BeginOrEndFunction() {
this instanceof BeginFunction or
this instanceof EndFunction
diff --git a/cpp/ql/lib/semmle/code/cpp/models/implementations/Printf.qll b/cpp/ql/lib/semmle/code/cpp/models/implementations/Printf.qll
index 7474631397c16..677b9245b6b85 100644
--- a/cpp/ql/lib/semmle/code/cpp/models/implementations/Printf.qll
+++ b/cpp/ql/lib/semmle/code/cpp/models/implementations/Printf.qll
@@ -7,6 +7,7 @@
import semmle.code.cpp.models.interfaces.FormattingFunction
import semmle.code.cpp.models.interfaces.Alias
+import semmle.code.cpp.models.interfaces.SideEffect
/**
* The standard functions `printf`, `wprintf` and their glib variants.
@@ -96,7 +97,7 @@ private class Sprintf extends FormattingFunction {
/**
* Implements `Snprintf`.
*/
-private class SnprintfImpl extends Snprintf {
+private class SnprintfImpl extends Snprintf, AliasFunction, SideEffectFunction {
SnprintfImpl() {
this instanceof TopLevelFunction and
(
@@ -143,6 +144,26 @@ private class SnprintfImpl extends Snprintf {
}
override int getSizeParameterIndex() { result = 1 }
+
+ override predicate parameterNeverEscapes(int index) {
+ // We don't know how many parameters are passed to the function since it's varargs, but they also don't escape.
+ index = this.getFormatParameterIndex()
+ }
+
+ override predicate parameterEscapesOnlyViaReturn(int index) { none() }
+
+ override predicate hasOnlySpecificReadSideEffects() { any() }
+
+ override predicate hasOnlySpecificWriteSideEffects() { any() }
+
+ override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
+ i = this.getOutputParameterIndex(false) and buffer = true and mustWrite = false
+ }
+
+ override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
+ // We don't know how many parameters are passed to the function since it's varargs, but they also have read side effects.
+ i = this.getFormatParameterIndex() and buffer = true
+ }
}
/**
diff --git a/cpp/ql/lib/semmle/code/cpp/models/implementations/StdAlgorithm.qll b/cpp/ql/lib/semmle/code/cpp/models/implementations/StdAlgorithm.qll
new file mode 100644
index 0000000000000..85b69fc8ac447
--- /dev/null
+++ b/cpp/ql/lib/semmle/code/cpp/models/implementations/StdAlgorithm.qll
@@ -0,0 +1,115 @@
+/**
+ * Provides models for C++ functions from the `algorithms` header.
+ */
+
+import semmle.code.cpp.models.interfaces.Taint
+import semmle.code.cpp.models.interfaces.DataFlow
+import semmle.code.cpp.models.interfaces.Iterator
+import semmle.code.cpp.models.interfaces.SideEffect
+import semmle.code.cpp.models.interfaces.Alias
+
+private class StdPartialSort extends Function, SideEffectFunction, AliasFunction {
+ StdPartialSort() { this.hasGlobalOrStdName("partial_sort") }
+
+ override predicate hasOnlySpecificReadSideEffects() { any() }
+
+ override predicate hasOnlySpecificWriteSideEffects() { any() }
+
+ override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
+ i = this.getAnIteratorParameterIndex() and buffer = true and mustWrite = false
+ }
+
+ override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
+ i = this.getAnIteratorParameterIndex() and
+ buffer = true and
+ this.getParameter(i).getUnspecifiedType() instanceof ReferenceType and
+ buffer = false
+ }
+
+ private int getAnIteratorParameterIndex() {
+ this.getParameter(result).getUnspecifiedType() instanceof Iterator
+ }
+
+ override predicate parameterNeverEscapes(int index) {
+ index = this.getAnIteratorParameterIndex()
+ or
+ this.getParameter(index).getUnspecifiedType() instanceof ReferenceType
+ }
+
+ override predicate parameterEscapesOnlyViaReturn(int index) { none() }
+}
+
+private class StdSortHeap extends Function, SideEffectFunction, AliasFunction {
+ StdSortHeap() { this.hasGlobalOrStdName("sort_heap") }
+
+ override predicate hasOnlySpecificReadSideEffects() { any() }
+
+ override predicate hasOnlySpecificWriteSideEffects() { any() }
+
+ override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
+ i = this.getAnIteratorParameterIndex() and buffer = true and mustWrite = false
+ }
+
+ override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
+ i = this.getAnIteratorParameterIndex() and
+ buffer = true
+ }
+
+ private int getAnIteratorParameterIndex() {
+ this.getParameter(result).getUnspecifiedType() instanceof Iterator
+ }
+
+ override predicate parameterNeverEscapes(int index) { index = this.getAnIteratorParameterIndex() }
+
+ override predicate parameterEscapesOnlyViaReturn(int index) { none() }
+}
+
+private class StdGenerateN extends Function, SideEffectFunction, AliasFunction {
+ StdGenerateN() { this.hasGlobalOrStdName("generate_n") }
+
+ override predicate hasOnlySpecificReadSideEffects() { any() }
+
+ override predicate hasOnlySpecificWriteSideEffects() { any() }
+
+ override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
+ i = this.getAnIteratorParameterIndex() and buffer = true and mustWrite = false
+ }
+
+ override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
+ this.getParameter(i).getUnspecifiedType() instanceof ReferenceType and buffer = false
+ }
+
+ private int getAnIteratorParameterIndex() {
+ this.getParameter(result).getUnspecifiedType() instanceof Iterator
+ }
+
+ override predicate parameterNeverEscapes(int index) { index = this.getAnIteratorParameterIndex() }
+
+ override predicate parameterEscapesOnlyViaReturn(int index) { none() }
+}
+
+private class StdFindIfOrIfNot extends Function, SideEffectFunction, AliasFunction {
+ StdFindIfOrIfNot() { this.hasGlobalOrStdName(["find_if", "find_if_not"]) }
+
+ override predicate hasOnlySpecificReadSideEffects() { any() }
+
+ override predicate hasOnlySpecificWriteSideEffects() { any() }
+
+ override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
+ i = this.getAnIteratorParameterIndex() and buffer = true
+ or
+ this.getParameter(i).getUnspecifiedType() instanceof ReferenceType and buffer = false
+ }
+
+ private int getAnIteratorParameterIndex() {
+ this.getParameter(result).getUnspecifiedType() instanceof Iterator
+ }
+
+ override predicate parameterNeverEscapes(int index) {
+ this.getParameter(index).getUnspecifiedType() instanceof ReferenceType
+ }
+
+ override predicate parameterEscapesOnlyViaReturn(int index) {
+ index = this.getAnIteratorParameterIndex()
+ }
+}
diff --git a/cpp/ql/lib/semmle/code/cpp/models/implementations/StdAllocator.qll b/cpp/ql/lib/semmle/code/cpp/models/implementations/StdAllocator.qll
new file mode 100644
index 0000000000000..189d0ad862bab
--- /dev/null
+++ b/cpp/ql/lib/semmle/code/cpp/models/implementations/StdAllocator.qll
@@ -0,0 +1,256 @@
+/**
+ * Provides models for C++ `allocator` and `allocator_traits` classes.
+ */
+
+import semmle.code.cpp.models.interfaces.SideEffect
+import semmle.code.cpp.models.interfaces.Alias
+
+/** The `std::allocator` class. */
+class StdAllocator extends Class {
+ StdAllocator() { this.hasGlobalOrStdOrBslName("allocator") }
+}
+
+/** The `std::allocator_traits` class. */
+class StdAllocatorTraits extends Class {
+ StdAllocatorTraits() { this.hasGlobalOrStdOrBslName("allocator_traits") }
+}
+
+private class StdAllocatorConstructor extends Constructor, AliasFunction, SideEffectFunction {
+ StdAllocatorConstructor() { this.getDeclaringType() instanceof StdAllocator }
+
+ override predicate parameterNeverEscapes(int index) { index = -1 }
+
+ override predicate parameterEscapesOnlyViaReturn(int index) { none() }
+
+ override predicate hasOnlySpecificReadSideEffects() { any() }
+
+ override predicate hasOnlySpecificWriteSideEffects() { any() }
+
+ override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
+ i = -1 and
+ buffer = false and
+ mustWrite = true
+ }
+
+ override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
+ this.getParameter(i).getUnspecifiedType() instanceof ReferenceType and buffer = false
+ }
+}
+
+private class StdAllocatorDestructor extends Destructor, AliasFunction, SideEffectFunction {
+ StdAllocatorDestructor() { this.getDeclaringType() instanceof StdAllocator }
+
+ override predicate parameterNeverEscapes(int index) { index = -1 }
+
+ override predicate parameterEscapesOnlyViaReturn(int index) { none() }
+
+ override predicate hasOnlySpecificReadSideEffects() { any() }
+
+ override predicate hasOnlySpecificWriteSideEffects() { any() }
+
+ override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
+ i = -1 and
+ buffer = false and
+ mustWrite = true
+ }
+}
+
+private class StdAllocatorAddress extends MemberFunction, AliasFunction, SideEffectFunction {
+ StdAllocatorAddress() { this.getClassAndName("address") instanceof StdAllocator }
+
+ override predicate parameterNeverEscapes(int index) { index = -1 }
+
+ override predicate parameterEscapesOnlyViaReturn(int index) { none() }
+
+ override predicate hasOnlySpecificReadSideEffects() { any() }
+
+ override predicate hasOnlySpecificWriteSideEffects() { any() }
+}
+
+private class StdAllocatorAllocate extends MemberFunction, AliasFunction, SideEffectFunction {
+ StdAllocatorAllocate() { this.getClassAndName("allocate") instanceof StdAllocator }
+
+ override predicate parameterNeverEscapes(int index) { index = -1 }
+
+ override predicate parameterEscapesOnlyViaReturn(int index) { none() }
+
+ override predicate hasOnlySpecificReadSideEffects() { any() }
+
+ override predicate hasOnlySpecificWriteSideEffects() { any() }
+}
+
+private class StdAllocatorTraitsAllocate extends MemberFunction, AliasFunction, SideEffectFunction {
+ StdAllocatorTraitsAllocate() {
+ this.getClassAndName(["allocate", "allocate_at_least"]) instanceof StdAllocatorTraits
+ }
+
+ override predicate parameterNeverEscapes(int index) {
+ this.getParameter(index).getUnspecifiedType() instanceof ReferenceType
+ }
+
+ override predicate parameterEscapesOnlyViaReturn(int index) { none() }
+
+ override predicate hasOnlySpecificReadSideEffects() { any() }
+
+ override predicate hasOnlySpecificWriteSideEffects() { any() }
+
+ override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
+ this.getParameter(i).getUnspecifiedType() instanceof ReferenceType and buffer = false
+ }
+}
+
+private class StdAllocatorDeallocate extends MemberFunction, AliasFunction, SideEffectFunction {
+ StdAllocatorDeallocate() { this.getClassAndName("deallocate") instanceof StdAllocator }
+
+ override predicate parameterNeverEscapes(int index) { index = -1 }
+
+ override predicate parameterEscapesOnlyViaReturn(int index) { none() }
+
+ override predicate hasOnlySpecificReadSideEffects() { any() }
+
+ override predicate hasOnlySpecificWriteSideEffects() { any() }
+
+ override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
+ i = 0 and
+ buffer = false and
+ mustWrite = false
+ }
+
+ override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
+ i = 0 and
+ buffer = false
+ }
+}
+
+private class StdAllocatorTraitsDeallocate extends MemberFunction, AliasFunction, SideEffectFunction
+{
+ StdAllocatorTraitsDeallocate() {
+ this.getClassAndName("deallocate") instanceof StdAllocatorTraits
+ }
+
+ override predicate parameterNeverEscapes(int index) { index = [0, 1] }
+
+ override predicate parameterEscapesOnlyViaReturn(int index) { none() }
+
+ override predicate hasOnlySpecificReadSideEffects() { any() }
+
+ override predicate hasOnlySpecificWriteSideEffects() { any() }
+
+ override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
+ i = 1 and
+ buffer = false and
+ mustWrite = false
+ }
+
+ override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
+ i = [0, 1] and
+ buffer = false
+ }
+}
+
+private class StdAllocatorMaxSize extends MemberFunction, AliasFunction, SideEffectFunction {
+ StdAllocatorMaxSize() { this.getClassAndName("max_size") instanceof StdAllocator }
+
+ override predicate parameterNeverEscapes(int index) { index = -1 }
+
+ override predicate parameterEscapesOnlyViaReturn(int index) { none() }
+
+ override predicate hasOnlySpecificReadSideEffects() { any() }
+
+ override predicate hasOnlySpecificWriteSideEffects() { any() }
+}
+
+private class StdAllocatTraitsMaxSize extends MemberFunction, AliasFunction, SideEffectFunction {
+ StdAllocatTraitsMaxSize() { this.getClassAndName("max_size") instanceof StdAllocatorTraits }
+
+ override predicate parameterNeverEscapes(int index) { index = -1 }
+
+ override predicate parameterEscapesOnlyViaReturn(int index) { none() }
+
+ override predicate hasOnlySpecificReadSideEffects() { any() }
+
+ override predicate hasOnlySpecificWriteSideEffects() { any() }
+}
+
+private class StdAllocatorConstruct extends MemberFunction, AliasFunction, SideEffectFunction {
+ StdAllocatorConstruct() { this.getClassAndName("construct") instanceof StdAllocator }
+
+ override predicate parameterNeverEscapes(int index) { index = -1 }
+
+ override predicate parameterEscapesOnlyViaReturn(int index) { none() }
+
+ override predicate hasOnlySpecificReadSideEffects() { any() }
+
+ override predicate hasOnlySpecificWriteSideEffects() { any() }
+
+ override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
+ i = 0 and buffer = false and mustWrite = true
+ }
+
+ override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
+ this.getParameter(i).getUnspecifiedType() instanceof ReferenceType and buffer = false
+ }
+}
+
+class StdAllocatorTraitsConstruct extends MemberFunction, AliasFunction, SideEffectFunction {
+ StdAllocatorTraitsConstruct() { this.getClassAndName("construct") instanceof StdAllocatorTraits }
+
+ override predicate parameterNeverEscapes(int index) {
+ index = 1 or this.getParameter(index).getUnspecifiedType() instanceof ReferenceType
+ }
+
+ override predicate parameterEscapesOnlyViaReturn(int index) { none() }
+
+ override predicate hasOnlySpecificReadSideEffects() { any() }
+
+ override predicate hasOnlySpecificWriteSideEffects() { any() }
+
+ override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
+ i = 1 and buffer = false and mustWrite = true
+ }
+
+ override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
+ this.getParameter(i).getUnspecifiedType() instanceof ReferenceType and
+ buffer = false
+ }
+}
+
+class StdAllocatorDestroy extends MemberFunction, AliasFunction, SideEffectFunction {
+ StdAllocatorDestroy() { this.getClassAndName("destroy") instanceof StdAllocator }
+
+ override predicate parameterNeverEscapes(int index) { index = -1 }
+
+ override predicate parameterEscapesOnlyViaReturn(int index) { none() }
+
+ override predicate hasOnlySpecificReadSideEffects() { any() }
+
+ override predicate hasOnlySpecificWriteSideEffects() { any() }
+
+ override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
+ i = 0 and buffer = false and mustWrite = true
+ }
+
+ override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
+ i = 0 and buffer = false
+ }
+}
+
+class StdAllocatorTraitsDestroy extends MemberFunction, AliasFunction, SideEffectFunction {
+ StdAllocatorTraitsDestroy() { this.getClassAndName("destroy") instanceof StdAllocatorTraits }
+
+ override predicate parameterNeverEscapes(int index) { index = [0, 1] }
+
+ override predicate parameterEscapesOnlyViaReturn(int index) { none() }
+
+ override predicate hasOnlySpecificReadSideEffects() { any() }
+
+ override predicate hasOnlySpecificWriteSideEffects() { any() }
+
+ override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
+ i = 1 and buffer = false and mustWrite = true
+ }
+
+ override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
+ i = 0 and buffer = false
+ }
+}
diff --git a/cpp/ql/lib/semmle/code/cpp/models/implementations/StdContainer.qll b/cpp/ql/lib/semmle/code/cpp/models/implementations/StdContainer.qll
index bf9e05991b4c3..8ac54336da6fa 100644
--- a/cpp/ql/lib/semmle/code/cpp/models/implementations/StdContainer.qll
+++ b/cpp/ql/lib/semmle/code/cpp/models/implementations/StdContainer.qll
@@ -4,6 +4,8 @@
import semmle.code.cpp.models.interfaces.FlowSource
import semmle.code.cpp.models.interfaces.Iterator
+import semmle.code.cpp.models.interfaces.SideEffect
+import semmle.code.cpp.models.interfaces.Alias
/**
* A sequence container template class (for example, `std::vector`) from the
@@ -58,7 +60,7 @@ private class Vector extends StdSequenceContainer {
/**
* The standard container functions `push_back` and `push_front`.
*/
-class StdSequenceContainerPush extends MemberFunction {
+class StdSequenceContainerPush extends MemberFunction, SideEffectFunction, AliasFunction {
StdSequenceContainerPush() {
this.getClassAndName("push_back") instanceof Vector or
this.getClassAndName(["push_back", "push_front"]) instanceof Deque or
@@ -74,12 +76,111 @@ class StdSequenceContainerPush extends MemberFunction {
this.getParameter(result).getUnspecifiedType().(ReferenceType).getBaseType() =
this.getDeclaringType().getTemplateArgument(0).(Type).getUnspecifiedType() // i.e. the `T` of this `std::vector`
}
+
+ override predicate parameterNeverEscapes(int index) { index = -1 }
+
+ override predicate parameterEscapesOnlyViaReturn(int index) { none() }
+
+ override predicate hasOnlySpecificReadSideEffects() { any() }
+
+ override predicate hasOnlySpecificWriteSideEffects() { any() }
+
+ override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
+ i = -1 and
+ buffer = false and
+ mustWrite = true
+ }
+
+ override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
+ i = 0 and buffer = false
+ }
+}
+
+private class StdSequenceContainerPopFrontOrBack extends MemberFunction, SideEffectFunction,
+ AliasFunction
+{
+ StdSequenceContainerPopFrontOrBack() {
+ this.getClassAndName("pop_back") instanceof Vector or
+ this.getClassAndName("pop_front") instanceof ForwardList or
+ this.getClassAndName(["pop_front", "pop_back"]) instanceof Deque or
+ this.getClassAndName(["pop_front", "pop_back"]) instanceof List
+ }
+
+ override predicate parameterNeverEscapes(int index) { index = -1 }
+
+ override predicate parameterEscapesOnlyViaReturn(int index) { none() }
+
+ override predicate hasOnlySpecificReadSideEffects() { any() }
+
+ override predicate hasOnlySpecificWriteSideEffects() { any() }
+
+ override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
+ i = -1 and
+ buffer = false and
+ mustWrite = true
+ }
+
+ override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
+ i = -1 and
+ buffer = false
+ }
+}
+
+private class StdSequenceContainerClear extends MemberFunction, SideEffectFunction, AliasFunction {
+ StdSequenceContainerClear() {
+ this.getClassAndName("clear") instanceof Vector or
+ this.getClassAndName("clear") instanceof Deque or
+ this.getClassAndName("clear") instanceof ForwardList or
+ this.getClassAndName("clear") instanceof List
+ }
+
+ override predicate parameterNeverEscapes(int index) { index = -1 }
+
+ override predicate parameterEscapesOnlyViaReturn(int index) { none() }
+
+ override predicate hasOnlySpecificReadSideEffects() { any() }
+
+ override predicate hasOnlySpecificWriteSideEffects() { any() }
+
+ override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
+ i = -1 and
+ buffer = false and
+ mustWrite = true
+ }
+
+ override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
+ i = -1 and
+ buffer = false
+ }
+}
+
+private class StdVectorReserve extends MemberFunction, SideEffectFunction, AliasFunction {
+ StdVectorReserve() { this.getClassAndName("reserve") instanceof Vector }
+
+ override predicate parameterNeverEscapes(int index) { index = -1 }
+
+ override predicate parameterEscapesOnlyViaReturn(int index) { none() }
+
+ override predicate hasOnlySpecificReadSideEffects() { any() }
+
+ override predicate hasOnlySpecificWriteSideEffects() { any() }
+
+ override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
+ i = -1 and
+ buffer = false and
+ mustWrite = true
+ }
+
+ override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
+ i = -1 and
+ buffer = false
+ }
}
/**
* The standard container functions `insert` and `insert_after`.
*/
-class StdSequenceContainerInsert extends MemberFunction {
+class StdSequenceContainerInsert extends MemberFunction, SideEffectFunction, AliasFunction {
StdSequenceContainerInsert() {
this.getClassAndName("insert") instanceof Deque or
this.getClassAndName("insert") instanceof List or
@@ -100,17 +201,138 @@ class StdSequenceContainerInsert extends MemberFunction {
* Gets the index of a parameter to this function that is an iterator.
*/
int getAnIteratorParameterIndex() { this.getParameter(result).getType() instanceof Iterator }
+
+ override predicate parameterNeverEscapes(int index) { index = -1 }
+
+ override predicate parameterEscapesOnlyViaReturn(int index) { none() }
+
+ override predicate hasOnlySpecificReadSideEffects() { any() }
+
+ override predicate hasOnlySpecificWriteSideEffects() { any() }
+
+ override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
+ i = -1 and
+ buffer = false and
+ mustWrite = true
+ }
+
+ override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
+ this.getParameter(i).getUnspecifiedType() instanceof ReferenceType and
+ buffer = false
+ }
+}
+
+private class StdSequenceContainerFrontBack extends MemberFunction, SideEffectFunction,
+ AliasFunction
+{
+ StdSequenceContainerFrontBack() {
+ this.getClassAndName(["front", "back"]) instanceof Deque or
+ this.getClassAndName(["front", "back"]) instanceof List or
+ this.getClassAndName(["front", "back"]) instanceof Vector or
+ // forward_list does not have a 'back' member function
+ this.getClassAndName("front") instanceof ForwardList
+ }
+
+ override predicate parameterNeverEscapes(int index) { index = -1 }
+
+ override predicate parameterEscapesOnlyViaReturn(int index) { none() }
+
+ override predicate hasOnlySpecificReadSideEffects() { any() }
+
+ override predicate hasOnlySpecificWriteSideEffects() { any() }
+
+ override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
+ i = -1 and buffer = false
+ }
}
/**
* The standard container functions `at` and `operator[]`.
*/
-class StdSequenceContainerAt extends MemberFunction {
+class StdSequenceContainerAt extends MemberFunction, SideEffectFunction, AliasFunction {
StdSequenceContainerAt() {
this.getClassAndName(["at", "operator[]"]) instanceof Array or
this.getClassAndName(["at", "operator[]"]) instanceof Deque or
this.getClassAndName(["at", "operator[]"]) instanceof Vector
}
+
+ override predicate parameterNeverEscapes(int index) { index = -1 }
+
+ override predicate parameterEscapesOnlyViaReturn(int index) { none() }
+
+ override predicate hasOnlySpecificReadSideEffects() { any() }
+
+ override predicate hasOnlySpecificWriteSideEffects() { any() }
+
+ override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
+ none()
+ }
+
+ override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
+ i = -1 and buffer = false
+ }
+}
+
+private class StdSequenceContainerMemberEquals extends MemberFunction, SideEffectFunction,
+ AliasFunction
+{
+ StdSequenceContainerMemberEquals() {
+ this.getClassAndName("operator==") instanceof Array or
+ this.getClassAndName("operator==") instanceof Deque or
+ this.getClassAndName("operator==") instanceof Vector
+ }
+
+ override predicate hasOnlySpecificReadSideEffects() { any() }
+
+ override predicate hasOnlySpecificWriteSideEffects() { any() }
+
+ override predicate parameterNeverEscapes(int index) { index = -1 or index = 0 }
+
+ override predicate parameterEscapesOnlyViaReturn(int index) { none() }
+
+ override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
+ none()
+ }
+
+ override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
+ i = -1 and buffer = false
+ or
+ i = 0 and buffer = false
+ }
+}
+
+private class StdSequenceContainerEquals extends Function, SideEffectFunction, AliasFunction {
+ StdSequenceContainerEquals() {
+ this.hasGlobalOrStdOrBslName("operator==") and
+ not this instanceof MemberFunction and
+ this.getNumberOfParameters() = 2 and
+ (
+ this.getParameter(0).getUnspecifiedType().(ReferenceType).getBaseType() instanceof Vector and
+ this.getParameter(1).getUnspecifiedType().(ReferenceType).getBaseType() instanceof Vector
+ or
+ this.getParameter(0).getUnspecifiedType().(ReferenceType).getBaseType() instanceof List and
+ this.getParameter(1).getUnspecifiedType().(ReferenceType).getBaseType() instanceof List
+ or
+ this.getParameter(0).getUnspecifiedType().(ReferenceType).getBaseType() instanceof Deque and
+ this.getParameter(1).getUnspecifiedType().(ReferenceType).getBaseType() instanceof Deque
+ )
+ }
+
+ override predicate parameterNeverEscapes(int index) { index = 0 or index = 1 }
+
+ override predicate parameterEscapesOnlyViaReturn(int index) { none() }
+
+ override predicate hasOnlySpecificReadSideEffects() { any() }
+
+ override predicate hasOnlySpecificWriteSideEffects() { any() }
+
+ override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
+ none()
+ }
+
+ override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
+ i = [0, 1] and buffer = false
+ }
}
/**
@@ -142,6 +364,117 @@ class StdVectorEmplace extends StdSequenceEmplace {
StdVectorEmplace() { this.getDeclaringType() instanceof Vector }
}
+private class StdSequenceSize extends MemberFunction, SideEffectFunction, AliasFunction {
+ StdSequenceSize() {
+ this.getClassAndName("size") instanceof Vector
+ or
+ this.getClassAndName("size") instanceof List
+ or
+ this.getClassAndName("size") instanceof Deque
+ }
+
+ override predicate parameterNeverEscapes(int index) { index = -1 }
+
+ override predicate parameterEscapesOnlyViaReturn(int index) { none() }
+
+ override predicate hasOnlySpecificReadSideEffects() { any() }
+
+ override predicate hasOnlySpecificWriteSideEffects() { any() }
+
+ override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
+ i = -1 and buffer = false
+ }
+}
+
+private class StdSequenceDestructor extends Destructor, SideEffectFunction, AliasFunction {
+ StdSequenceDestructor() {
+ this.getDeclaringType() instanceof Vector
+ or
+ this.getDeclaringType() instanceof List
+ or
+ this.getDeclaringType() instanceof Deque
+ }
+
+ private Destructor getElementDestructor() {
+ result.getDeclaringType() = this.getTemplateArgument(0)
+ }
+
+ override predicate parameterNeverEscapes(int index) { index = -1 }
+
+ override predicate parameterEscapesOnlyViaReturn(int index) { none() }
+
+ override predicate hasOnlySpecificReadSideEffects() {
+ this.getElementDestructor().(SideEffectFunction).hasOnlySpecificReadSideEffects()
+ or
+ not exists(this.getElementDestructor())
+ }
+
+ override predicate hasOnlySpecificWriteSideEffects() {
+ this.getElementDestructor().(SideEffectFunction).hasOnlySpecificWriteSideEffects()
+ or
+ not exists(this.getElementDestructor())
+ }
+
+ override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
+ i = -1 and buffer = false and mustWrite = true
+ }
+
+ override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
+ i = -1 and buffer = false
+ }
+}
+
+private class StdSequenceConstructor extends Constructor, SideEffectFunction, AliasFunction {
+ StdSequenceConstructor() {
+ this.getDeclaringType() instanceof Vector
+ or
+ this.getDeclaringType() instanceof List
+ or
+ this.getDeclaringType() instanceof Deque
+ }
+
+ override predicate parameterNeverEscapes(int index) { index = -1 }
+
+ override predicate parameterEscapesOnlyViaReturn(int index) { none() }
+
+ override predicate hasOnlySpecificReadSideEffects() { any() }
+
+ override predicate hasOnlySpecificWriteSideEffects() { any() }
+
+ override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
+ i = -1 and buffer = false and mustWrite = true
+ }
+
+ override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
+ this.getParameter(i).getUnspecifiedType() instanceof ReferenceType and
+ buffer = false
+ }
+}
+
+private class InitializerList extends Class {
+ InitializerList() { this.hasQualifiedName(["std", "bsl"], "initializer_list") }
+
+ Type getElementType() { result = this.getTemplateArgument(0) }
+}
+
+private class InitializerListConstructor extends Constructor, SideEffectFunction, AliasFunction {
+ InitializerListConstructor() { this.getDeclaringType() instanceof InitializerList }
+
+ override predicate parameterNeverEscapes(int index) { index = -1 }
+
+ override predicate parameterEscapesOnlyViaReturn(int index) { none() }
+
+ override predicate hasOnlySpecificReadSideEffects() { any() }
+
+ override predicate hasOnlySpecificWriteSideEffects() { any() }
+
+ override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
+ i = -1 and buffer = false and mustWrite = true
+ }
+
+ override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) { none() }
+}
+
/**
* The standard vector `emplace_back` function.
*/
diff --git a/cpp/ql/lib/semmle/code/cpp/models/implementations/StdException.qll b/cpp/ql/lib/semmle/code/cpp/models/implementations/StdException.qll
new file mode 100644
index 0000000000000..ff822c874cd00
--- /dev/null
+++ b/cpp/ql/lib/semmle/code/cpp/models/implementations/StdException.qll
@@ -0,0 +1,38 @@
+/**
+ * Provides models for the C++ `std::pair` class.
+ */
+
+import semmle.code.cpp.models.interfaces.Taint
+import semmle.code.cpp.models.interfaces.Alias
+import semmle.code.cpp.models.interfaces.SideEffect
+
+/** The `std::exception` class. */
+class StdException extends Class {
+ StdException() { this.hasGlobalOrStdOrBslName("exception") }
+}
+
+/** The `std::bad_alloc` class. */
+class StdBadAllocException extends Class {
+ StdBadAllocException() { this.hasGlobalOrStdOrBslName("bad_alloc") }
+}
+
+private class StdBadAllocExceptionConstructor extends Constructor, SideEffectFunction, AliasFunction
+{
+ StdBadAllocExceptionConstructor() { this.getDeclaringType() instanceof StdBadAllocException }
+
+ override predicate parameterNeverEscapes(int index) { index = -1 }
+
+ override predicate parameterEscapesOnlyViaReturn(int index) { none() }
+
+ override predicate hasOnlySpecificReadSideEffects() { any() }
+
+ override predicate hasOnlySpecificWriteSideEffects() { any() }
+
+ override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
+ i = -1 and buffer = false and mustWrite = true
+ }
+
+ override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
+ this.getParameter(i).getUnspecifiedType() instanceof ReferenceType and buffer = false
+ }
+}
diff --git a/cpp/ql/lib/semmle/code/cpp/models/implementations/StdFunction.qll b/cpp/ql/lib/semmle/code/cpp/models/implementations/StdFunction.qll
new file mode 100644
index 0000000000000..ba90eeceeb4dc
--- /dev/null
+++ b/cpp/ql/lib/semmle/code/cpp/models/implementations/StdFunction.qll
@@ -0,0 +1,53 @@
+/**
+ * Provides models for C++ containers `std::array`, `std::vector`, `std::deque`, `std::list` and `std::forward_list`.
+ */
+
+import semmle.code.cpp.models.interfaces.SideEffect
+import semmle.code.cpp.models.interfaces.Alias
+
+/**
+ * An instantiation of the `std::function` class template.
+ */
+class StdFunction extends ClassTemplateInstantiation {
+ StdFunction() { this.hasGlobalOrStdOrBslName("function") }
+}
+
+private class StdFunctionConstructor extends Constructor, SideEffectFunction, AliasFunction {
+ StdFunctionConstructor() { this.getDeclaringType() instanceof StdFunction }
+
+ override predicate parameterNeverEscapes(int index) { index = -1 }
+
+ override predicate parameterEscapesOnlyViaReturn(int index) { none() }
+
+ override predicate hasOnlySpecificReadSideEffects() { any() }
+
+ override predicate hasOnlySpecificWriteSideEffects() { any() }
+
+ override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
+ i = -1 and buffer = false and mustWrite = true
+ }
+
+ override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
+ this.getParameter(i).getUnspecifiedType() instanceof ReferenceType and buffer = false
+ }
+}
+
+private class StdFunctionDestructor extends Destructor, SideEffectFunction, AliasFunction {
+ StdFunctionDestructor() { this.getDeclaringType() instanceof StdFunction }
+
+ override predicate parameterNeverEscapes(int index) { index = -1 }
+
+ override predicate parameterEscapesOnlyViaReturn(int index) { none() }
+
+ override predicate hasOnlySpecificReadSideEffects() { any() }
+
+ override predicate hasOnlySpecificWriteSideEffects() { any() }
+
+ override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
+ i = -1 and buffer = false and mustWrite = true
+ }
+
+ override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
+ i = -1 and buffer = false
+ }
+}
diff --git a/cpp/ql/lib/semmle/code/cpp/models/implementations/StdMap.qll b/cpp/ql/lib/semmle/code/cpp/models/implementations/StdMap.qll
index ce3c596f308aa..5d2133b6f4506 100644
--- a/cpp/ql/lib/semmle/code/cpp/models/implementations/StdMap.qll
+++ b/cpp/ql/lib/semmle/code/cpp/models/implementations/StdMap.qll
@@ -5,6 +5,8 @@
import semmle.code.cpp.models.interfaces.Taint
import semmle.code.cpp.models.interfaces.DataFlow
import semmle.code.cpp.models.interfaces.Iterator
+import semmle.code.cpp.models.interfaces.SideEffect
+import semmle.code.cpp.models.interfaces.Alias
/**
* The `std::map` and `std::unordered_map` template classes.
@@ -16,7 +18,9 @@ private class MapOrUnorderedMap extends Class {
/**
* Additional model for map constructors using iterator inputs.
*/
-private class StdMapConstructor extends Constructor, TaintFunction {
+private class StdMapConstructor extends Constructor, TaintFunction, AliasFunction,
+ SideEffectFunction
+{
StdMapConstructor() { this.getDeclaringType() instanceof MapOrUnorderedMap }
/**
@@ -35,6 +39,23 @@ private class StdMapConstructor extends Constructor, TaintFunction {
output.isQualifierObject()
)
}
+
+ override predicate hasOnlySpecificReadSideEffects() { any() }
+
+ override predicate hasOnlySpecificWriteSideEffects() { any() }
+
+ override predicate parameterNeverEscapes(int index) { index = -1 }
+
+ override predicate parameterEscapesOnlyViaReturn(int index) { none() }
+
+ override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
+ i = -1 and buffer = false and mustWrite = true
+ }
+
+ override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
+ this.getParameter(i).getUnspecifiedType() instanceof ReferenceType and
+ buffer = false
+ }
}
/**
@@ -133,7 +154,7 @@ class StdMapAt extends MemberFunction {
StdMapAt() { this.getClassAndName(["at", "operator[]"]) instanceof MapOrUnorderedMap }
}
-private class StdMapAtModels extends StdMapAt, TaintFunction {
+private class StdMapAtModels extends StdMapAt, TaintFunction, AliasFunction, SideEffectFunction {
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
// flow from qualifier to referenced return value
input.isQualifierObject() and
@@ -144,6 +165,18 @@ private class StdMapAtModels extends StdMapAt, TaintFunction {
output.isQualifierObject()
}
+ override predicate hasOnlySpecificReadSideEffects() { any() }
+
+ override predicate hasOnlySpecificWriteSideEffects() { any() }
+
+ override predicate parameterNeverEscapes(int index) { index = -1 }
+
+ override predicate parameterEscapesOnlyViaReturn(int index) { none() }
+
+ override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
+ i = -1 and buffer = false
+ }
+
override predicate isPartialWrite(FunctionOutput output) { output.isQualifierObject() }
}
@@ -187,3 +220,63 @@ private class StdMapEqualRange extends TaintFunction {
output.isReturnValue()
}
}
+
+class StdMapDestructor extends Destructor, SideEffectFunction, AliasFunction {
+ StdMapDestructor() { this.getDeclaringType() instanceof MapOrUnorderedMap }
+
+ override predicate hasOnlySpecificReadSideEffects() { any() }
+
+ override predicate hasOnlySpecificWriteSideEffects() { any() }
+
+ override predicate parameterNeverEscapes(int index) { index = -1 }
+
+ override predicate parameterEscapesOnlyViaReturn(int index) { none() }
+
+ override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
+ i = -1 and buffer = false and mustWrite = true
+ }
+
+ override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
+ i = -1 and buffer = false
+ }
+}
+
+private class StdMapClear extends MemberFunction, SideEffectFunction, AliasFunction {
+ StdMapClear() { this.getClassAndName("clear") instanceof MapOrUnorderedMap }
+
+ override predicate parameterNeverEscapes(int index) { index = -1 }
+
+ override predicate parameterEscapesOnlyViaReturn(int index) { none() }
+
+ override predicate hasOnlySpecificReadSideEffects() { any() }
+
+ override predicate hasOnlySpecificWriteSideEffects() { any() }
+
+ override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
+ i = -1 and
+ buffer = false and
+ mustWrite = true
+ }
+
+ override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
+ i = -1 and
+ buffer = false
+ }
+}
+
+class StdMapSize extends MemberFunction, SideEffectFunction, AliasFunction {
+ StdMapSize() { this.getClassAndName("size") instanceof MapOrUnorderedMap }
+
+ override predicate parameterNeverEscapes(int index) { index = -1 }
+
+ override predicate parameterEscapesOnlyViaReturn(int index) { none() }
+
+ override predicate hasOnlySpecificReadSideEffects() { any() }
+
+ override predicate hasOnlySpecificWriteSideEffects() { any() }
+
+ override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
+ i = -1 and
+ buffer = false
+ }
+}
diff --git a/cpp/ql/lib/semmle/code/cpp/models/implementations/StdMath.qll b/cpp/ql/lib/semmle/code/cpp/models/implementations/StdMath.qll
new file mode 100644
index 0000000000000..fb44377875405
--- /dev/null
+++ b/cpp/ql/lib/semmle/code/cpp/models/implementations/StdMath.qll
@@ -0,0 +1,98 @@
+/**
+ * Provides models for C++ functions from the `cmath` header.
+ */
+
+private import semmle.code.cpp.models.interfaces.SideEffect
+private import semmle.code.cpp.models.interfaces.Alias
+
+private class LdExp extends Function, SideEffectFunction {
+ LdExp() { this.hasGlobalOrStdOrBslName(["ldexp", "ldexpf", "ldexpl"]) }
+
+ override predicate hasOnlySpecificReadSideEffects() { any() }
+
+ override predicate hasOnlySpecificWriteSideEffects() { any() }
+}
+
+private class Abs extends Function, SideEffectFunction {
+ Abs() { this.hasGlobalOrStdOrBslName(["abs", "fabs", "fabsf", "fabsl", "llabs", "imaxabs"]) }
+
+ override predicate hasOnlySpecificReadSideEffects() { any() }
+
+ override predicate hasOnlySpecificWriteSideEffects() { any() }
+}
+
+private class Div extends Function, SideEffectFunction {
+ Div() { this.hasGlobalOrStdOrBslName(["div", "ldiv", "lldiv", "imaxdiv"]) }
+
+ override predicate hasOnlySpecificReadSideEffects() { any() }
+
+ override predicate hasOnlySpecificWriteSideEffects() { any() }
+}
+
+private class FMod extends Function, SideEffectFunction {
+ FMod() { this.hasGlobalOrStdOrBslName(["fmod", "fmodf", "fmodl"]) }
+
+ override predicate hasOnlySpecificReadSideEffects() { any() }
+
+ override predicate hasOnlySpecificWriteSideEffects() { any() }
+}
+
+private class Remainder extends Function, SideEffectFunction {
+ Remainder() { this.hasGlobalOrStdOrBslName(["remainder", "remainderf", "remainderl"]) }
+
+ override predicate hasOnlySpecificReadSideEffects() { any() }
+
+ override predicate hasOnlySpecificWriteSideEffects() { any() }
+}
+
+private class Remquo extends Function, SideEffectFunction {
+ Remquo() { this.hasGlobalOrStdOrBslName(["remquo", "remquof", "remquol"]) }
+
+ override predicate hasOnlySpecificReadSideEffects() { any() }
+
+ override predicate hasOnlySpecificWriteSideEffects() { any() }
+}
+
+private class Fma extends Function, SideEffectFunction {
+ Fma() { this.hasGlobalOrStdOrBslName(["fma", "fmaf", "fmal"]) }
+
+ override predicate hasOnlySpecificReadSideEffects() { any() }
+
+ override predicate hasOnlySpecificWriteSideEffects() { any() }
+}
+
+private class Fmax extends Function, SideEffectFunction {
+ Fmax() { this.hasGlobalOrStdOrBslName(["fmax", "fmaxf", "fmaxl"]) }
+
+ override predicate hasOnlySpecificReadSideEffects() { any() }
+
+ override predicate hasOnlySpecificWriteSideEffects() { any() }
+}
+
+private class Fmin extends Function, SideEffectFunction {
+ Fmin() { this.hasGlobalOrStdOrBslName(["fmin", "fminf", "fminl"]) }
+
+ override predicate hasOnlySpecificReadSideEffects() { any() }
+
+ override predicate hasOnlySpecificWriteSideEffects() { any() }
+}
+
+private class Fdim extends Function, SideEffectFunction {
+ Fdim() { this.hasGlobalOrStdOrBslName(["fdim", "fdimf", "fdiml"]) }
+
+ override predicate hasOnlySpecificReadSideEffects() { any() }
+
+ override predicate hasOnlySpecificWriteSideEffects() { any() }
+}
+
+private class Nan extends Function, SideEffectFunction, AliasFunction {
+ Nan() { this.hasGlobalOrStdOrBslName(["nan", "nanf", "nanl"]) }
+
+ override predicate hasOnlySpecificReadSideEffects() { any() }
+
+ override predicate hasOnlySpecificWriteSideEffects() { any() }
+
+ override predicate parameterNeverEscapes(int index) { index = 0 }
+
+ override predicate parameterEscapesOnlyViaReturn(int index) { none() }
+}
diff --git a/cpp/ql/lib/semmle/code/cpp/models/implementations/StdPair.qll b/cpp/ql/lib/semmle/code/cpp/models/implementations/StdPair.qll
index 28d05e5c30691..bb097d5fe858d 100644
--- a/cpp/ql/lib/semmle/code/cpp/models/implementations/StdPair.qll
+++ b/cpp/ql/lib/semmle/code/cpp/models/implementations/StdPair.qll
@@ -3,6 +3,8 @@
*/
import semmle.code.cpp.models.interfaces.Taint
+import semmle.code.cpp.models.interfaces.Alias
+import semmle.code.cpp.models.interfaces.SideEffect
/**
* An instantiation of `std::pair`.
@@ -37,7 +39,9 @@ class StdPairCopyishConstructor extends Constructor, TaintFunction {
/**
* Additional model for `std::pair` constructors.
*/
-private class StdPairConstructor extends Constructor, TaintFunction {
+private class StdPairConstructor extends Constructor, TaintFunction, AliasFunction,
+ SideEffectFunction
+{
StdPairConstructor() { this.getDeclaringType() instanceof StdPair }
/**
@@ -59,4 +63,70 @@ private class StdPairConstructor extends Constructor, TaintFunction {
output.isQualifierObject()
)
}
+
+ override predicate parameterNeverEscapes(int index) { index = -1 }
+
+ override predicate parameterEscapesOnlyViaReturn(int index) { none() }
+
+ override predicate hasOnlySpecificReadSideEffects() { any() }
+
+ override predicate hasOnlySpecificWriteSideEffects() { any() }
+
+ override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
+ i = -1 and buffer = false and mustWrite = true
+ }
+
+ override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
+ i = [0, 1] and buffer = false
+ }
+}
+
+private class StdPairDestructor extends Destructor, AliasFunction, SideEffectFunction {
+ StdPairDestructor() { this.getDeclaringType() instanceof StdPair }
+
+ private Type getFirstType() { result = this.getDeclaringType().getTemplateArgument(0) }
+
+ private Type getSecondType() { result = this.getDeclaringType().getTemplateArgument(0) }
+
+ private Type getAType() { result = [this.getFirstType(), this.getSecondType()] }
+
+ /**
+ * Gets the destructor associated with the base type of this pair
+ */
+ private Destructor getADestructor() { result.getDeclaringType() = this.getAType() }
+
+ override predicate hasOnlySpecificReadSideEffects() {
+ this.getADestructor().(SideEffectFunction).hasOnlySpecificReadSideEffects()
+ or
+ // If there's no declared destructor for the base type then it won't have
+ // any strange read side effects.
+ not exists(this.getADestructor())
+ }
+
+ override predicate hasOnlySpecificWriteSideEffects() {
+ this.getADestructor().(SideEffectFunction).hasOnlySpecificWriteSideEffects()
+ or
+ // If there's no declared destructor for the base type then it won't have
+ // any strange write side effects.
+ not exists(this.getADestructor())
+ }
+
+ override predicate parameterEscapesOnlyViaReturn(int index) { none() }
+
+ override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
+ i = -1 and buffer = false
+ }
+
+ override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
+ i = -1 and buffer = false and mustWrite = true
+ }
+
+ override predicate parameterNeverEscapes(int index) {
+ this.getADestructor().(AliasFunction).parameterNeverEscapes(index)
+ or
+ // If there's no declared destructor for the base type then it won't cause
+ // anything to escape.
+ not exists(this.getADestructor()) and
+ index = -1
+ }
}
diff --git a/cpp/ql/lib/semmle/code/cpp/models/implementations/StdString.qll b/cpp/ql/lib/semmle/code/cpp/models/implementations/StdString.qll
index fd28363297a63..f76ad8ff844aa 100644
--- a/cpp/ql/lib/semmle/code/cpp/models/implementations/StdString.qll
+++ b/cpp/ql/lib/semmle/code/cpp/models/implementations/StdString.qll
@@ -7,6 +7,8 @@
import semmle.code.cpp.models.interfaces.Taint
import semmle.code.cpp.models.interfaces.Iterator
import semmle.code.cpp.models.interfaces.DataFlow
+import semmle.code.cpp.models.interfaces.SideEffect
+import semmle.code.cpp.models.interfaces.Alias
/**
* The `std::basic_string` template class instantiations.
@@ -78,7 +80,9 @@ abstract private class StdStringTaintFunction extends TaintFunction {
* std::string b(a.begin(), a.end());
* ```
*/
-private class StdStringConstructor extends Constructor, StdStringTaintFunction {
+private class StdStringConstructor extends Constructor, StdStringTaintFunction, SideEffectFunction,
+ AliasFunction
+{
StdStringConstructor() { this.getDeclaringType() instanceof StdBasicString }
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
@@ -94,6 +98,42 @@ private class StdStringConstructor extends Constructor, StdStringTaintFunction {
output.isQualifierObject()
)
}
+
+ override predicate parameterNeverEscapes(int index) { index = -1 }
+
+ override predicate parameterEscapesOnlyViaReturn(int index) { none() }
+
+ override predicate hasOnlySpecificReadSideEffects() { any() }
+
+ override predicate hasOnlySpecificWriteSideEffects() { any() }
+
+ override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
+ i = -1 and buffer = false and mustWrite = true
+ }
+
+ override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
+ i = -1 and buffer = false
+ }
+}
+
+private class StdStringDestructor extends Destructor, SideEffectFunction, AliasFunction {
+ StdStringDestructor() { this.getDeclaringType() instanceof StdBasicString }
+
+ override predicate hasOnlySpecificReadSideEffects() { any() }
+
+ override predicate hasOnlySpecificWriteSideEffects() { any() }
+
+ override predicate parameterNeverEscapes(int index) { index = -1 }
+
+ override predicate parameterEscapesOnlyViaReturn(int index) { none() }
+
+ override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
+ i = -1 and buffer = false and mustWrite = true
+ }
+
+ override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
+ i = -1 and buffer = false
+ }
}
/**
@@ -164,7 +204,7 @@ private class StdStringFrontBack extends StdStringTaintFunction {
/**
* The (non-member) `std::string` function `operator+`.
*/
-private class StdStringPlus extends StdStringTaintFunction {
+private class StdStringPlus extends StdStringTaintFunction, SideEffectFunction, AliasFunction {
StdStringPlus() {
this.hasQualifiedName(["std", "bsl"], "operator+") and
this.getUnspecifiedType() instanceof StdBasicString
@@ -178,6 +218,18 @@ private class StdStringPlus extends StdStringTaintFunction {
) and
output.isReturnValue()
}
+
+ override predicate hasOnlySpecificReadSideEffects() { any() }
+
+ override predicate hasOnlySpecificWriteSideEffects() { any() }
+
+ override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
+ i = [0, 1] and buffer = false
+ }
+
+ override predicate parameterNeverEscapes(int index) { index = [0, 1] }
+
+ override predicate parameterEscapesOnlyViaReturn(int index) { none() }
}
/**
@@ -185,7 +237,7 @@ private class StdStringPlus extends StdStringTaintFunction {
* All of these functions combine the existing string with a new
* string (or character) from one of the arguments.
*/
-private class StdStringAppend extends StdStringTaintFunction {
+private class StdStringAppend extends StdStringTaintFunction, SideEffectFunction, AliasFunction {
StdStringAppend() {
this.getClassAndName(["operator+=", "append", "replace"]) instanceof StdBasicString
}
@@ -210,6 +262,22 @@ private class StdStringAppend extends StdStringTaintFunction {
}
override predicate isPartialWrite(FunctionOutput output) { output.isQualifierObject() }
+
+ override predicate hasOnlySpecificReadSideEffects() { any() }
+
+ override predicate hasOnlySpecificWriteSideEffects() { any() }
+
+ override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
+ i = -1 and mustWrite = false and buffer = true
+ }
+
+ override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
+ i = [-1, 0] and buffer = true
+ }
+
+ override predicate parameterNeverEscapes(int index) { index = [-1, 0] }
+
+ override predicate parameterEscapesOnlyViaReturn(int index) { none() }
}
/**
@@ -301,7 +369,7 @@ private class StdStringSubstr extends StdStringTaintFunction {
/**
* The `std::string` functions `at` and `operator[]`.
*/
-private class StdStringAt extends StdStringTaintFunction {
+private class StdStringAt extends StdStringTaintFunction, SideEffectFunction, AliasFunction {
StdStringAt() { this.getClassAndName(["at", "operator[]"]) instanceof StdBasicString }
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
@@ -315,6 +383,22 @@ private class StdStringAt extends StdStringTaintFunction {
}
override predicate isPartialWrite(FunctionOutput output) { output.isQualifierObject() }
+
+ override predicate parameterNeverEscapes(int index) { index = -1 }
+
+ override predicate parameterEscapesOnlyViaReturn(int index) { none() }
+
+ override predicate hasOnlySpecificReadSideEffects() { any() }
+
+ override predicate hasOnlySpecificWriteSideEffects() { any() }
+
+ override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
+ none()
+ }
+
+ override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
+ i = -1 and buffer = false
+ }
}
/**
@@ -324,6 +408,54 @@ private class StdBasicIStream extends ClassTemplateInstantiation {
StdBasicIStream() { this.hasQualifiedName(["std", "bsl"], "basic_istream") }
}
+private class StdBasicIfStream extends ClassTemplateInstantiation {
+ StdBasicIfStream() { this.hasQualifiedName(["std", "bsl"], "basic_ifstream") }
+}
+
+class StdBasicIfStreamConstructor extends Constructor, SideEffectFunction, AliasFunction {
+ StdBasicIfStreamConstructor() { this.getDeclaringType() instanceof StdBasicIfStream }
+
+ override predicate parameterNeverEscapes(int index) { index = -1 }
+
+ override predicate parameterEscapesOnlyViaReturn(int index) { none() }
+
+ override predicate hasOnlySpecificReadSideEffects() { any() }
+
+ override predicate hasOnlySpecificWriteSideEffects() { any() }
+
+ override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
+ i = -1 and buffer = false and mustWrite = true
+ }
+
+ override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
+ exists(Type t | t = this.getParameter(i).getUnspecifiedType() |
+ t instanceof PointerType and buffer = true
+ or
+ t instanceof ReferenceType and buffer = false
+ )
+ }
+}
+
+class StdBasicIfStreamDestructor extends Destructor, SideEffectFunction, AliasFunction {
+ StdBasicIfStreamDestructor() { this.getDeclaringType() instanceof StdBasicIfStream }
+
+ override predicate parameterNeverEscapes(int index) { index = -1 }
+
+ override predicate parameterEscapesOnlyViaReturn(int index) { none() }
+
+ override predicate hasOnlySpecificReadSideEffects() { any() }
+
+ override predicate hasOnlySpecificWriteSideEffects() { any() }
+
+ override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
+ i = -1 and buffer = false and mustWrite = true
+ }
+
+ override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
+ i = -1 and buffer = false
+ }
+}
+
/**
* The `std::istream` function `operator>>` (defined as a member function).
*/
@@ -542,6 +674,33 @@ private class StdBasicOStream extends ClassTemplateInstantiation {
StdBasicOStream() { this.hasQualifiedName(["std", "bsl"], "basic_ostream") }
}
+private class StdStringLessThan extends Function, AliasFunction, SideEffectFunction {
+ StdStringLessThan() {
+ this.hasQualifiedName(["std", "bsl"], "operator<") and
+ this.getNumberOfParameters() = 2 and
+ this.getParameter(0).getUnspecifiedType().(ReferenceType).getBaseType() instanceof
+ StdBasicString and
+ this.getParameter(1).getUnspecifiedType().(ReferenceType).getBaseType() instanceof
+ StdBasicString
+ }
+
+ override predicate parameterNeverEscapes(int index) { index = [0, 1] }
+
+ override predicate parameterEscapesOnlyViaReturn(int index) { none() }
+
+ override predicate hasOnlySpecificReadSideEffects() { any() }
+
+ override predicate hasOnlySpecificWriteSideEffects() { any() }
+
+ override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
+ none()
+ }
+
+ override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
+ i = [0, 1] and buffer = false
+ }
+}
+
/**
* The `std::ostream` functions `operator<<` (defined as a member function),
* `put` and `write`.
From 281212a22cecf4666c3ff20eba7a51327c5275e7 Mon Sep 17 00:00:00 2001
From: Mathias Vorreiter Pedersen
Date: Mon, 22 Jul 2024 16:23:26 +0100
Subject: [PATCH 065/140] C++: Accept test changes.
---
.../library-tests/ir/ir/aliased_ir.expected | 1170 ++++++++---------
.../test/library-tests/ir/ir/raw_ir.expected | 836 ++++++------
2 files changed, 972 insertions(+), 1034 deletions(-)
diff --git a/cpp/ql/test/library-tests/ir/ir/aliased_ir.expected b/cpp/ql/test/library-tests/ir/ir/aliased_ir.expected
index ea445b599fa49..6a10e618ae34c 100644
--- a/cpp/ql/test/library-tests/ir/ir/aliased_ir.expected
+++ b/cpp/ql/test/library-tests/ir/ir/aliased_ir.expected
@@ -15538,230 +15538,219 @@ ir.cpp:
# 2215| m2215_8(ClassWithDestructor) = Chi : total:m2215_2, partial:m2215_7
# 2216| r2216_1(glval>) = VariableAddress[ys] :
# 2216| m2216_2(vector) = Uninitialized[ys] : &:r2216_1
-# 2216| m2216_3(unknown) = Chi : total:m2215_6, partial:m2216_2
-# 2216| r2216_4(glval) = FunctionAddress[vector] :
-# 2216| r2216_5(glval) = VariableAddress[#temp2216:45] :
-# 2216| r2216_6(glval) = VariableAddress[x] :
-# 2216| r2216_7(ClassWithDestructor) = Load[x] : &:r2216_6, m2215_8
-# 2216| m2216_8(ClassWithDestructor) = Store[#temp2216:45] : &:r2216_5, r2216_7
-# 2216| r2216_9(ClassWithDestructor) = Load[#temp2216:45] : &:r2216_5, m2216_8
-# 2216| v2216_10(void) = Call[vector] : func:r2216_4, this:r2216_1, 0:r2216_9
-# 2216| m2216_11(unknown) = ^CallSideEffect : ~m2216_3
-# 2216| m2216_12(unknown) = Chi : total:m2216_3, partial:m2216_11
-# 2216| m2216_13(vector) = ^IndirectMayWriteSideEffect[-1] : &:r2216_1
-# 2216| m2216_14(unknown) = Chi : total:m2216_12, partial:m2216_13
-# 2216| r2216_15(glval) = CopyValue : r2216_5
-# 2216| r2216_16(glval) = FunctionAddress[~ClassWithDestructor] :
-# 2216| v2216_17(void) = Call[~ClassWithDestructor] : func:r2216_16, this:r2216_15
-# 2216| m2216_18(unknown) = ^CallSideEffect : ~m2216_14
-# 2216| m2216_19(unknown) = Chi : total:m2216_14, partial:m2216_18
-# 2216| v2216_20(void) = ^IndirectReadSideEffect[-1] : &:r2216_15, m2216_8
-# 2216| m2216_21(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r2216_15
-# 2216| m2216_22(ClassWithDestructor) = Chi : total:m2216_8, partial:m2216_21
-# 2216| r2216_23(glval &>) = VariableAddress[(__range)] :
-# 2216| r2216_24(glval>) = VariableAddress[ys] :
-# 2216| r2216_25(vector &) = CopyValue : r2216_24
-# 2216| m2216_26(vector &) = Store[(__range)] : &:r2216_23, r2216_25
-# 2216| r2216_27(glval>) = VariableAddress[(__begin)] :
-# 2216| r2216_28(glval &>) = VariableAddress[(__range)] :
-# 2216| r2216_29(vector &) = Load[(__range)] : &:r2216_28, m2216_26
-#-----| r0_1(glval>) = CopyValue : r2216_29
+# 2216| r2216_3(glval) = FunctionAddress[vector] :
+# 2216| r2216_4(glval) = VariableAddress[#temp2216:45] :
+# 2216| r2216_5(glval) = VariableAddress[x] :
+# 2216| r2216_6(ClassWithDestructor) = Load[x] : &:r2216_5, m2215_8
+# 2216| m2216_7(ClassWithDestructor) = Store[#temp2216:45] : &:r2216_4, r2216_6
+# 2216| r2216_8(ClassWithDestructor) = Load[#temp2216:45] : &:r2216_4, m2216_7
+# 2216| v2216_9(void) = Call[vector] : func:r2216_3, this:r2216_1, 0:r2216_8
+# 2216| m2216_10(vector) = ^IndirectMustWriteSideEffect[-1] : &:r2216_1
+# 2216| r2216_11(glval) = CopyValue : r2216_4
+# 2216| r2216_12(glval) = FunctionAddress[~ClassWithDestructor] :
+# 2216| v2216_13(void) = Call[~ClassWithDestructor] : func:r2216_12, this:r2216_11
+# 2216| m2216_14(unknown) = ^CallSideEffect : ~m2215_6
+# 2216| m2216_15(unknown) = Chi : total:m2215_6, partial:m2216_14
+# 2216| v2216_16(void) = ^IndirectReadSideEffect[-1] : &:r2216_11, m2216_7
+# 2216| m2216_17(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r2216_11
+# 2216| m2216_18(ClassWithDestructor) = Chi : total:m2216_7, partial:m2216_17
+# 2216| r2216_19(glval &>) = VariableAddress[(__range)] :
+# 2216| r2216_20(glval>) = VariableAddress[ys] :
+# 2216| r2216_21(vector &) = CopyValue : r2216_20
+# 2216| m2216_22(vector &) = Store[(__range)] : &:r2216_19, r2216_21
+# 2216| r2216_23(glval>) = VariableAddress[(__begin)] :
+# 2216| r2216_24(glval &>) = VariableAddress[(__range)] :
+# 2216| r2216_25(vector &) = Load[(__range)] : &:r2216_24, m2216_22
+#-----| r0_1(glval>) = CopyValue : r2216_25
#-----| r0_2(glval>) = Convert : r0_1
-# 2216| r2216_30(glval) = FunctionAddress[begin] :
-# 2216| r2216_31(iterator) = Call[begin] : func:r2216_30, this:r0_2
-#-----| v0_3(void) = ^IndirectReadSideEffect[-1] : &:r0_2, ~m2216_19
-# 2216| m2216_32(iterator) = Store[(__begin)] : &:r2216_27, r2216_31
-# 2216| r2216_33(glval>) = VariableAddress[(__end)] :
-# 2216| r2216_34(glval &>) = VariableAddress[(__range)] :
-# 2216| r2216_35(vector &) = Load[(__range)] : &:r2216_34, m2216_26
-#-----| r0_4(glval>) = CopyValue : r2216_35
+# 2216| r2216_26(glval) = FunctionAddress[begin] :
+# 2216| r2216_27(iterator) = Call[begin] : func:r2216_26, this:r0_2
+#-----| v0_3(void) = ^IndirectReadSideEffect[-1] : &:r0_2, m2216_10
+# 2216| m2216_28(iterator) = Store[(__begin)] : &:r2216_23, r2216_27
+# 2216| r2216_29(glval>) = VariableAddress[(__end)] :
+# 2216| r2216_30(glval &>) = VariableAddress[(__range)] :
+# 2216| r2216_31(vector &) = Load[(__range)] : &:r2216_30, m2216_22
+#-----| r0_4(glval>) = CopyValue : r2216_31
#-----| r0_5(glval>) = Convert : r0_4
-# 2216| r2216_36(glval) = FunctionAddress[end] :
-# 2216| r2216_37(iterator) = Call[end] : func:r2216_36, this:r0_5
-#-----| v0_6(void) = ^IndirectReadSideEffect[-1] : &:r0_5, ~m2216_19
-# 2216| m2216_38(iterator) = Store[(__end)] : &:r2216_33, r2216_37
-# 2216| m2216_39(unknown) = Chi : total:m2216_19, partial:m2216_38
+# 2216| r2216_32(glval) = FunctionAddress[end] :
+# 2216| r2216_33(iterator) = Call[end] : func:r2216_32, this:r0_5
+#-----| v0_6(void) = ^IndirectReadSideEffect[-1] : &:r0_5, m2216_10
+# 2216| m2216_34(iterator) = Store[(__end)] : &:r2216_29, r2216_33
+# 2216| m2216_35(unknown) = Chi : total:m2216_15, partial:m2216_34
#-----| Goto -> Block 8
# 2216| Block 8
-# 2216| m2216_40(iterator) = Phi : from 7:m2216_32, from 9:m2216_64
-# 2216| m2216_41(unknown) = Phi : from 7:~m2216_39, from 9:~m2216_69
-# 2216| r2216_42(glval>) = VariableAddress[(__begin)] :
-#-----| r0_7(glval>) = Convert : r2216_42
-# 2216| r2216_43(glval) = FunctionAddress[operator!=] :
+# 2216| m2216_36(iterator) = Phi : from 7:m2216_28, from 9:m2216_60
+# 2216| m2216_37(unknown) = Phi : from 7:~m2216_35, from 9:~m2216_65
+# 2216| r2216_38(glval>) = VariableAddress[(__begin)] :
+#-----| r0_7(glval>) = Convert : r2216_38
+# 2216| r2216_39(glval) = FunctionAddress[operator!=] :
#-----| r0_8(glval>) = VariableAddress[#temp0:0] :
#-----| m0_9(iterator) = Uninitialized[#temp0:0] : &:r0_8
-#-----| m0_10(unknown) = Chi : total:m2216_41, partial:m0_9
-# 2216| r2216_44(glval) = FunctionAddress[iterator] :
-# 2216| r2216_45(glval>) = VariableAddress[(__end)] :
-#-----| r0_11(glval>) = Convert : r2216_45
+#-----| m0_10(unknown) = Chi : total:m2216_37, partial:m0_9
+# 2216| r2216_40(glval) = FunctionAddress[iterator] :
+# 2216| r2216_41(glval>) = VariableAddress[(__end)] :
+#-----| r0_11(glval>) = Convert : r2216_41
#-----| r0_12(iterator &) = CopyValue : r0_11
-# 2216| v2216_46(void) = Call[iterator] : func:r2216_44, this:r0_8, 0:r0_12
-# 2216| m2216_47(unknown) = ^CallSideEffect : ~m0_10
-# 2216| m2216_48(unknown) = Chi : total:m0_10, partial:m2216_47
-#-----| v0_13(void) = ^BufferReadSideEffect[0] : &:r0_12, ~m2216_48
-# 2216| m2216_49(iterator) = ^IndirectMayWriteSideEffect[-1] : &:r0_8
-# 2216| m2216_50(unknown) = Chi : total:m2216_48, partial:m2216_49
-#-----| r0_14(iterator) = Load[#temp0:0] : &:r0_8, ~m2216_50
-# 2216| r2216_51(bool) = Call[operator!=] : func:r2216_43, this:r0_7, 0:r0_14
-#-----| v0_15(void) = ^IndirectReadSideEffect[-1] : &:r0_7, m2216_40
-# 2216| v2216_52(void) = ConditionalBranch : r2216_51
+# 2216| v2216_42(void) = Call[iterator] : func:r2216_40, this:r0_8, 0:r0_12
+# 2216| m2216_43(unknown) = ^CallSideEffect : ~m0_10
+# 2216| m2216_44(unknown) = Chi : total:m0_10, partial:m2216_43
+#-----| v0_13(void) = ^BufferReadSideEffect[0] : &:r0_12, ~m2216_44
+# 2216| m2216_45(iterator) = ^IndirectMayWriteSideEffect[-1] : &:r0_8
+# 2216| m2216_46(unknown) = Chi : total:m2216_44, partial:m2216_45
+#-----| r0_14(iterator) = Load[#temp0:0] : &:r0_8, ~m2216_46
+# 2216| r2216_47(bool) = Call[operator!=] : func:r2216_39, this:r0_7, 0:r0_14
+#-----| v0_15(void) = ^IndirectReadSideEffect[-1] : &:r0_7, m2216_36
+# 2216| v2216_48(void) = ConditionalBranch : r2216_47
#-----| False -> Block 10
#-----| True -> Block 9
# 2216| Block 9
-# 2216| r2216_53(glval) = VariableAddress[y] :
-# 2216| r2216_54(glval>) = VariableAddress[(__begin)] :
-#-----| r0_16(glval>) = Convert : r2216_54
-# 2216| r2216_55(glval) = FunctionAddress[operator*] :
-# 2216| r2216_56(ClassWithDestructor &) = Call[operator*] : func:r2216_55, this:r0_16
-#-----| v0_17(void) = ^IndirectReadSideEffect[-1] : &:r0_16, m2216_40
-# 2216| r2216_57(ClassWithDestructor) = Load[?] : &:r2216_56, ~m2216_50
-# 2216| m2216_58(ClassWithDestructor) = Store[y] : &:r2216_53, r2216_57
+# 2216| r2216_49(glval) = VariableAddress[y] :
+# 2216| r2216_50(glval>) = VariableAddress[(__begin)] :
+#-----| r0_16(glval>) = Convert : r2216_50
+# 2216| r2216_51(glval) = FunctionAddress[operator*] :
+# 2216| r2216_52(ClassWithDestructor &) = Call[operator*] : func:r2216_51, this:r0_16
+#-----| v0_17(void) = ^IndirectReadSideEffect[-1] : &:r0_16, m2216_36
+# 2216| r2216_53(ClassWithDestructor) = Load[?] : &:r2216_52, ~m2216_46
+# 2216| m2216_54(ClassWithDestructor) = Store[y] : &:r2216_49, r2216_53
# 2217| r2217_1(glval) = VariableAddress[y] :
# 2217| r2217_2(glval) = FunctionAddress[set_x] :
# 2217| r2217_3(char) = Constant[97] :
# 2217| v2217_4(void) = Call[set_x] : func:r2217_2, this:r2217_1, 0:r2217_3
-# 2217| m2217_5(unknown) = ^CallSideEffect : ~m2216_50
-# 2217| m2217_6(unknown) = Chi : total:m2216_50, partial:m2217_5
-# 2217| v2217_7(void) = ^IndirectReadSideEffect[-1] : &:r2217_1, m2216_58
+# 2217| m2217_5(unknown) = ^CallSideEffect : ~m2216_46
+# 2217| m2217_6(unknown) = Chi : total:m2216_46, partial:m2217_5
+# 2217| v2217_7(void) = ^IndirectReadSideEffect[-1] : &:r2217_1, m2216_54
# 2217| m2217_8(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r2217_1
-# 2217| m2217_9(ClassWithDestructor) = Chi : total:m2216_58, partial:m2217_8
-# 2216| r2216_59(glval>) = VariableAddress[(__begin)] :
-# 2216| r2216_60(glval) = FunctionAddress[operator++] :
-# 2216| r2216_61(iterator &) = Call[operator++] : func:r2216_60, this:r2216_59
-# 2216| v2216_62(void) = ^IndirectReadSideEffect[-1] : &:r2216_59, m2216_40
-# 2216| m2216_63(iterator) = ^IndirectMayWriteSideEffect[-1] : &:r2216_59
-# 2216| m2216_64(iterator) = Chi : total:m2216_40, partial:m2216_63
-# 2216| r2216_65(glval) = VariableAddress[y] :
-# 2216| r2216_66(glval) = FunctionAddress[~ClassWithDestructor] :
-# 2216| v2216_67(void) = Call[~ClassWithDestructor] : func:r2216_66, this:r2216_65
-# 2216| m2216_68(unknown) = ^CallSideEffect : ~m2217_6
-# 2216| m2216_69(unknown) = Chi : total:m2217_6, partial:m2216_68
-# 2216| v2216_70(void) = ^IndirectReadSideEffect[-1] : &:r2216_65, m2217_9
-# 2216| m2216_71(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r2216_65
-# 2216| m2216_72(ClassWithDestructor) = Chi : total:m2217_9, partial:m2216_71
-# 2216| r2216_73(glval>) = CopyValue : r2216_61
+# 2217| m2217_9(ClassWithDestructor) = Chi : total:m2216_54, partial:m2217_8
+# 2216| r2216_55(glval>) = VariableAddress[(__begin)] :
+# 2216| r2216_56(glval) = FunctionAddress[operator++] :
+# 2216| r2216_57(iterator &) = Call[operator++] : func:r2216_56, this:r2216_55
+# 2216| v2216_58(void) = ^IndirectReadSideEffect[-1] : &:r2216_55, m2216_36
+# 2216| m2216_59(iterator) = ^IndirectMayWriteSideEffect[-1] : &:r2216_55
+# 2216| m2216_60(iterator) = Chi : total:m2216_36, partial:m2216_59
+# 2216| r2216_61(glval) = VariableAddress[y] :
+# 2216| r2216_62(glval) = FunctionAddress[~ClassWithDestructor] :
+# 2216| v2216_63(void) = Call[~ClassWithDestructor] : func:r2216_62, this:r2216_61
+# 2216| m2216_64(unknown) = ^CallSideEffect : ~m2217_6
+# 2216| m2216_65(unknown) = Chi : total:m2217_6, partial:m2216_64
+# 2216| v2216_66(void) = ^IndirectReadSideEffect[-1] : &:r2216_61, m2217_9
+# 2216| m2216_67(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r2216_61
+# 2216| m2216_68(ClassWithDestructor) = Chi : total:m2217_9, partial:m2216_67
+# 2216| r2216_69(glval>) = CopyValue : r2216_57
#-----| Goto (back edge) -> Block 8
# 2216| Block 10
-# 2216| r2216_74(glval>) = VariableAddress[ys] :
-# 2216| r2216_75(glval) = FunctionAddress[~vector] :
-# 2216| v2216_76(void) = Call[~vector] : func:r2216_75, this:r2216_74
-# 2216| m2216_77(unknown) = ^CallSideEffect : ~m2216_50
-# 2216| m2216_78(unknown) = Chi : total:m2216_50, partial:m2216_77
-# 2216| v2216_79(void) = ^IndirectReadSideEffect[-1] : &:r2216_74, ~m2216_78
-# 2216| m2216_80(vector) = ^IndirectMayWriteSideEffect[-1] : &:r2216_74
-# 2216| m2216_81(unknown) = Chi : total:m2216_78, partial:m2216_80
+# 2216| r2216_70(glval>) = VariableAddress[ys] :
+# 2216| r2216_71(glval) = FunctionAddress[~vector] :
+# 2216| v2216_72(void) = Call[~vector] : func:r2216_71, this:r2216_70
+# 2216| v2216_73(void) = ^IndirectReadSideEffect[-1] : &:r2216_70, m2216_10
+# 2216| m2216_74(vector) = ^IndirectMustWriteSideEffect[-1] : &:r2216_70
# 2219| r2219_1(glval>) = VariableAddress[ys] :
# 2219| m2219_2(vector) = Uninitialized[ys] : &:r2219_1
-# 2219| m2219_3(unknown) = Chi : total:m2216_81, partial:m2219_2
-# 2219| r2219_4(glval) = FunctionAddress[vector] :
-# 2219| r2219_5(glval) = VariableAddress[#temp2219:45] :
-# 2219| r2219_6(glval) = VariableAddress[x] :
-# 2219| r2219_7(ClassWithDestructor) = Load[x] : &:r2219_6, m2215_8
-# 2219| m2219_8(ClassWithDestructor) = Store[#temp2219:45] : &:r2219_5, r2219_7
-# 2219| r2219_9(ClassWithDestructor) = Load[#temp2219:45] : &:r2219_5, m2219_8
-# 2219| v2219_10(void) = Call[vector] : func:r2219_4, this:r2219_1, 0:r2219_9
-# 2219| m2219_11(unknown) = ^CallSideEffect : ~m2219_3
-# 2219| m2219_12(unknown) = Chi : total:m2219_3, partial:m2219_11
-# 2219| m2219_13(vector) = ^IndirectMayWriteSideEffect[-1] : &:r2219_1
-# 2219| m2219_14(unknown) = Chi : total:m2219_12, partial:m2219_13
-# 2219| r2219_15(glval) = CopyValue : r2219_5
-# 2219| r2219_16(glval) = FunctionAddress[~ClassWithDestructor] :
-# 2219| v2219_17(void) = Call[~ClassWithDestructor] : func:r2219_16, this:r2219_15
-# 2219| m2219_18(unknown) = ^CallSideEffect : ~m2219_14
-# 2219| m2219_19(unknown) = Chi : total:m2219_14, partial:m2219_18
-# 2219| v2219_20(void) = ^IndirectReadSideEffect[-1] : &:r2219_15, m2219_8
-# 2219| m2219_21(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r2219_15
-# 2219| m2219_22(ClassWithDestructor) = Chi : total:m2219_8, partial:m2219_21
-# 2219| r2219_23(glval &>) = VariableAddress[(__range)] :
-# 2219| r2219_24(glval>) = VariableAddress[ys] :
-# 2219| r2219_25(vector &) = CopyValue : r2219_24
-# 2219| m2219_26(vector &) = Store[(__range)] : &:r2219_23, r2219_25
-# 2219| r2219_27(glval>) = VariableAddress[(__begin)] :
-# 2219| r2219_28(glval &>) = VariableAddress[(__range)] :
-# 2219| r2219_29(vector &) = Load[(__range)] : &:r2219_28, m2219_26
-#-----| r0_18(glval>) = CopyValue : r2219_29
+# 2219| r2219_3(glval) = FunctionAddress[vector] :
+# 2219| r2219_4(glval) = VariableAddress[#temp2219:45] :
+# 2219| r2219_5(glval) = VariableAddress[x] :
+# 2219| r2219_6(ClassWithDestructor) = Load[x] : &:r2219_5, m2215_8
+# 2219| m2219_7(ClassWithDestructor) = Store[#temp2219:45] : &:r2219_4, r2219_6
+# 2219| r2219_8(ClassWithDestructor) = Load[#temp2219:45] : &:r2219_4, m2219_7
+# 2219| v2219_9(void) = Call[vector] : func:r2219_3, this:r2219_1, 0:r2219_8
+# 2219| m2219_10(vector) = ^IndirectMustWriteSideEffect[-1] : &:r2219_1
+# 2219| r2219_11(glval) = CopyValue : r2219_4
+# 2219| r2219_12(glval) = FunctionAddress[~ClassWithDestructor] :
+# 2219| v2219_13(void) = Call[~ClassWithDestructor] : func:r2219_12, this:r2219_11
+# 2219| m2219_14(unknown) = ^CallSideEffect : ~m2216_46
+# 2219| m2219_15(unknown) = Chi : total:m2216_46, partial:m2219_14
+# 2219| v2219_16(void) = ^IndirectReadSideEffect[-1] : &:r2219_11, m2219_7
+# 2219| m2219_17(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r2219_11
+# 2219| m2219_18(ClassWithDestructor) = Chi : total:m2219_7, partial:m2219_17
+# 2219| r2219_19(glval &>) = VariableAddress[(__range)] :
+# 2219| r2219_20(glval>) = VariableAddress[ys] :
+# 2219| r2219_21(vector &) = CopyValue : r2219_20
+# 2219| m2219_22(vector &) = Store[(__range)] : &:r2219_19, r2219_21
+# 2219| r2219_23(glval>) = VariableAddress[(__begin)] :
+# 2219| r2219_24(glval &>) = VariableAddress[(__range)] :
+# 2219| r2219_25(vector &) = Load[(__range)] : &:r2219_24, m2219_22
+#-----| r0_18(glval>) = CopyValue : r2219_25
#-----| r0_19(glval>) = Convert : r0_18
-# 2219| r2219_30(glval) = FunctionAddress[begin] :
-# 2219| r2219_31(iterator) = Call[begin] : func:r2219_30, this:r0_19
-#-----| v0_20(void) = ^IndirectReadSideEffect[-1] : &:r0_19, ~m2219_19
-# 2219| m2219_32(iterator) = Store[(__begin)] : &:r2219_27, r2219_31
-# 2219| r2219_33(glval>) = VariableAddress[(__end)] :
-# 2219| r2219_34(glval &>) = VariableAddress[(__range)] :
-# 2219| r2219_35(vector &) = Load[(__range)] : &:r2219_34, m2219_26
-#-----| r0_21(glval>) = CopyValue : r2219_35
+# 2219| r2219_26(glval) = FunctionAddress[begin] :
+# 2219| r2219_27(iterator) = Call[begin] : func:r2219_26, this:r0_19
+#-----| v0_20(void) = ^IndirectReadSideEffect[-1] : &:r0_19, m2219_10
+# 2219| m2219_28(iterator) = Store[(__begin)] : &:r2219_23, r2219_27
+# 2219| r2219_29(glval>) = VariableAddress[(__end)] :
+# 2219| r2219_30(glval &>) = VariableAddress[(__range)] :
+# 2219| r2219_31(vector &) = Load[(__range)] : &:r2219_30, m2219_22
+#-----| r0_21(glval>) = CopyValue : r2219_31
#-----| r0_22(glval>) = Convert : r0_21
-# 2219| r2219_36(glval) = FunctionAddress[end] :
-# 2219| r2219_37(iterator) = Call[end] : func:r2219_36, this:r0_22
-#-----| v0_23(void) = ^IndirectReadSideEffect[-1] : &:r0_22, ~m2219_19
-# 2219| m2219_38(iterator) = Store[(__end)] : &:r2219_33, r2219_37
-# 2219| m2219_39(unknown) = Chi : total:m2219_19, partial:m2219_38
+# 2219| r2219_32(glval) = FunctionAddress[end] :
+# 2219| r2219_33(iterator) = Call[end] : func:r2219_32, this:r0_22
+#-----| v0_23(void) = ^IndirectReadSideEffect[-1] : &:r0_22, m2219_10
+# 2219| m2219_34(iterator) = Store[(__end)] : &:r2219_29, r2219_33
+# 2219| m2219_35(unknown) = Chi : total:m2219_15, partial:m2219_34
#-----| Goto -> Block 11
# 2219| Block 11
-# 2219| m2219_40(iterator) = Phi : from 10:m2219_32, from 12:m2219_58
-# 2219| m2219_41(unknown) = Phi : from 10:~m2219_39, from 12:~m2219_63
-# 2219| r2219_42(glval>) = VariableAddress[(__begin)] :
-#-----| r0_24(glval>) = Convert : r2219_42
-# 2219| r2219_43(glval) = FunctionAddress[operator!=] :
+# 2219| m2219_36(iterator) = Phi : from 10:m2219_28, from 12:m2219_54
+# 2219| m2219_37(unknown) = Phi : from 10:~m2219_35, from 12:~m2219_59
+# 2219| r2219_38(glval>) = VariableAddress[(__begin)] :
+#-----| r0_24(glval>) = Convert : r2219_38
+# 2219| r2219_39(glval) = FunctionAddress[operator!=] :
#-----| r0_25(glval>) = VariableAddress[#temp0:0] :
#-----| m0_26(iterator) = Uninitialized[#temp0:0] : &:r0_25
-#-----| m0_27(unknown) = Chi : total:m2219_41, partial:m0_26
-# 2219| r2219_44(glval) = FunctionAddress[iterator] :
-# 2219| r2219_45(glval>) = VariableAddress[(__end)] :
-#-----| r0_28(glval>) = Convert : r2219_45
+#-----| m0_27(unknown) = Chi : total:m2219_37, partial:m0_26
+# 2219| r2219_40(glval) = FunctionAddress[iterator] :
+# 2219| r2219_41(glval>) = VariableAddress[(__end)] :
+#-----| r0_28(glval>) = Convert : r2219_41
#-----| r0_29(iterator &) = CopyValue : r0_28
-# 2219| v2219_46(void) = Call[iterator] : func:r2219_44, this:r0_25, 0:r0_29
-# 2219| m2219_47(unknown) = ^CallSideEffect : ~m0_27
-# 2219| m2219_48(unknown) = Chi : total:m0_27, partial:m2219_47
-#-----| v0_30(void) = ^BufferReadSideEffect[0] : &:r0_29, ~m2219_48
-# 2219| m2219_49(iterator) = ^IndirectMayWriteSideEffect[-1] : &:r0_25
-# 2219| m2219_50(unknown) = Chi : total:m2219_48, partial:m2219_49
-#-----| r0_31(iterator) = Load[#temp0:0] : &:r0_25, ~m2219_50
-# 2219| r2219_51(bool) = Call[operator!=] : func:r2219_43, this:r0_24, 0:r0_31
-#-----| v0_32(void) = ^IndirectReadSideEffect[-1] : &:r0_24, m2219_40
-# 2219| v2219_52(void) = ConditionalBranch : r2219_51
+# 2219| v2219_42(void) = Call[iterator] : func:r2219_40, this:r0_25, 0:r0_29
+# 2219| m2219_43(unknown) = ^CallSideEffect : ~m0_27
+# 2219| m2219_44(unknown) = Chi : total:m0_27, partial:m2219_43
+#-----| v0_30(void) = ^BufferReadSideEffect[0] : &:r0_29, ~m2219_44
+# 2219| m2219_45(iterator) = ^IndirectMayWriteSideEffect[-1] : &:r0_25
+# 2219| m2219_46(unknown) = Chi : total:m2219_44, partial:m2219_45
+#-----| r0_31(iterator) = Load[#temp0:0] : &:r0_25, ~m2219_46
+# 2219| r2219_47(bool) = Call[operator!=] : func:r2219_39, this:r0_24, 0:r0_31
+#-----| v0_32(void) = ^IndirectReadSideEffect[-1] : &:r0_24, m2219_36
+# 2219| v2219_48(void) = ConditionalBranch : r2219_47
#-----| False -> Block 15
#-----| True -> Block 13
# 2219| Block 12
-# 2219| r2219_53(glval>) = VariableAddress[(__begin)] :
-# 2219| r2219_54(glval) = FunctionAddress[operator++] :
-# 2219| r2219_55(iterator &) = Call[operator++] : func:r2219_54, this:r2219_53
-# 2219| v2219_56(void) = ^IndirectReadSideEffect[-1] : &:r2219_53, m2219_40
-# 2219| m2219_57(iterator) = ^IndirectMayWriteSideEffect[-1] : &:r2219_53
-# 2219| m2219_58(iterator) = Chi : total:m2219_40, partial:m2219_57
-# 2219| r2219_59(glval) = VariableAddress[y] :
-# 2219| r2219_60(glval) = FunctionAddress[~ClassWithDestructor] :
-# 2219| v2219_61(void) = Call[~ClassWithDestructor] : func:r2219_60, this:r2219_59
-# 2219| m2219_62(unknown) = ^CallSideEffect : ~m2221_5
-# 2219| m2219_63(unknown) = Chi : total:m2221_5, partial:m2219_62
-# 2219| v2219_64(void) = ^IndirectReadSideEffect[-1] : &:r2219_59, m2221_8
-# 2219| m2219_65(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r2219_59
-# 2219| m2219_66(ClassWithDestructor) = Chi : total:m2221_8, partial:m2219_65
-# 2219| r2219_67(glval>) = CopyValue : r2219_55
+# 2219| r2219_49(glval>) = VariableAddress[(__begin)] :
+# 2219| r2219_50(glval) = FunctionAddress[operator++] :
+# 2219| r2219_51(iterator &) = Call[operator++] : func:r2219_50, this:r2219_49
+# 2219| v2219_52(void) = ^IndirectReadSideEffect[-1] : &:r2219_49, m2219_36
+# 2219| m2219_53(iterator) = ^IndirectMayWriteSideEffect[-1] : &:r2219_49
+# 2219| m2219_54(iterator) = Chi : total:m2219_36, partial:m2219_53
+# 2219| r2219_55(glval) = VariableAddress[y] :
+# 2219| r2219_56(glval) = FunctionAddress[~ClassWithDestructor] :
+# 2219| v2219_57(void) = Call[~ClassWithDestructor] : func:r2219_56, this:r2219_55
+# 2219| m2219_58(unknown) = ^CallSideEffect : ~m2221_5
+# 2219| m2219_59(unknown) = Chi : total:m2221_5, partial:m2219_58
+# 2219| v2219_60(void) = ^IndirectReadSideEffect[-1] : &:r2219_55, m2221_8
+# 2219| m2219_61(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r2219_55
+# 2219| m2219_62(ClassWithDestructor) = Chi : total:m2221_8, partial:m2219_61
+# 2219| r2219_63(glval>) = CopyValue : r2219_51
#-----| Goto (back edge) -> Block 11
# 2219| Block 13
-# 2219| r2219_68(glval) = VariableAddress[y] :
-# 2219| r2219_69(glval>) = VariableAddress[(__begin)] :
-#-----| r0_33(glval>) = Convert : r2219_69
-# 2219| r2219_70(glval) = FunctionAddress[operator*] :
-# 2219| r2219_71(ClassWithDestructor &) = Call[operator*] : func:r2219_70, this:r0_33
-#-----| v0_34(void) = ^IndirectReadSideEffect[-1] : &:r0_33, m2219_40
-# 2219| r2219_72(ClassWithDestructor) = Load[?] : &:r2219_71, ~m2219_50
-# 2219| m2219_73(ClassWithDestructor) = Store[y] : &:r2219_68, r2219_72
+# 2219| r2219_64(glval) = VariableAddress[y] :
+# 2219| r2219_65(glval>) = VariableAddress[(__begin)] :
+#-----| r0_33(glval>) = Convert : r2219_65
+# 2219| r2219_66(glval) = FunctionAddress[operator*] :
+# 2219| r2219_67(ClassWithDestructor &) = Call[operator*] : func:r2219_66, this:r0_33
+#-----| v0_34(void) = ^IndirectReadSideEffect[-1] : &:r0_33, m2219_36
+# 2219| r2219_68(ClassWithDestructor) = Load[?] : &:r2219_67, ~m2219_46
+# 2219| m2219_69(ClassWithDestructor) = Store[y] : &:r2219_64, r2219_68
# 2220| r2220_1(glval) = VariableAddress[y] :
# 2220| r2220_2(glval) = FunctionAddress[set_x] :
# 2220| r2220_3(char) = Constant[97] :
# 2220| v2220_4(void) = Call[set_x] : func:r2220_2, this:r2220_1, 0:r2220_3
-# 2220| m2220_5(unknown) = ^CallSideEffect : ~m2219_50
-# 2220| m2220_6(unknown) = Chi : total:m2219_50, partial:m2220_5
-# 2220| v2220_7(void) = ^IndirectReadSideEffect[-1] : &:r2220_1, m2219_73
+# 2220| m2220_5(unknown) = ^CallSideEffect : ~m2219_46
+# 2220| m2220_6(unknown) = Chi : total:m2219_46, partial:m2220_5
+# 2220| v2220_7(void) = ^IndirectReadSideEffect[-1] : &:r2220_1, m2219_69
# 2220| m2220_8(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r2220_1
-# 2220| m2220_9(ClassWithDestructor) = Chi : total:m2219_73, partial:m2220_8
+# 2220| m2220_9(ClassWithDestructor) = Chi : total:m2219_69, partial:m2220_8
# 2221| r2221_1(glval) = VariableAddress[y] :
# 2221| r2221_2(glval) = FunctionAddress[get_x] :
# 2221| r2221_3(char) = Call[get_x] : func:r2221_2, this:r2221_1
@@ -15779,123 +15768,113 @@ ir.cpp:
# 2222| Block 14
# 2222| v2222_1(void) = NoOp :
-# 2219| r2219_74(glval) = VariableAddress[y] :
-# 2219| r2219_75(glval) = FunctionAddress[~ClassWithDestructor] :
-# 2219| v2219_76(void) = Call[~ClassWithDestructor] : func:r2219_75, this:r2219_74
-# 2219| m2219_77(unknown) = ^CallSideEffect : ~m2221_5
-# 2219| m2219_78(unknown) = Chi : total:m2221_5, partial:m2219_77
-# 2219| v2219_79(void) = ^IndirectReadSideEffect[-1] : &:r2219_74, m2221_8
-# 2219| m2219_80(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r2219_74
-# 2219| m2219_81(ClassWithDestructor) = Chi : total:m2221_8, partial:m2219_80
-# 2219| r2219_82(glval>) = VariableAddress[ys] :
-# 2219| r2219_83(glval) = FunctionAddress[~vector] :
-# 2219| v2219_84(void) = Call[~vector] : func:r2219_83, this:r2219_82
-# 2219| m2219_85(unknown) = ^CallSideEffect : ~m2219_78
-# 2219| m2219_86(unknown) = Chi : total:m2219_78, partial:m2219_85
-# 2219| v2219_87(void) = ^IndirectReadSideEffect[-1] : &:r2219_82, ~m2219_86
-# 2219| m2219_88(vector) = ^IndirectMayWriteSideEffect[-1] : &:r2219_82
-# 2219| m2219_89(unknown) = Chi : total:m2219_86, partial:m2219_88
+# 2219| r2219_70(glval) = VariableAddress[y] :
+# 2219| r2219_71(glval) = FunctionAddress[~ClassWithDestructor] :
+# 2219| v2219_72(void) = Call[~ClassWithDestructor] : func:r2219_71, this:r2219_70
+# 2219| m2219_73(unknown) = ^CallSideEffect : ~m2221_5
+# 2219| m2219_74(unknown) = Chi : total:m2221_5, partial:m2219_73
+# 2219| v2219_75(void) = ^IndirectReadSideEffect[-1] : &:r2219_70, m2221_8
+# 2219| m2219_76(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r2219_70
+# 2219| m2219_77(ClassWithDestructor) = Chi : total:m2221_8, partial:m2219_76
+# 2219| r2219_78(glval>) = VariableAddress[ys] :
+# 2219| r2219_79(glval) = FunctionAddress[~vector] :
+# 2219| v2219_80(void) = Call[~vector] : func:r2219_79, this:r2219_78
+# 2219| v2219_81(void) = ^IndirectReadSideEffect[-1] : &:r2219_78, m2219_10
+# 2219| m2219_82(vector) = ^IndirectMustWriteSideEffect[-1] : &:r2219_78
# 2234| r2234_1(glval) = VariableAddress[x] :
# 2234| r2234_2(glval) = FunctionAddress[~ClassWithDestructor] :
# 2234| v2234_3(void) = Call[~ClassWithDestructor] : func:r2234_2, this:r2234_1
-# 2234| m2234_4(unknown) = ^CallSideEffect : ~m2219_89
-# 2234| m2234_5(unknown) = Chi : total:m2219_89, partial:m2234_4
+# 2234| m2234_4(unknown) = ^CallSideEffect : ~m2219_74
+# 2234| m2234_5(unknown) = Chi : total:m2219_74, partial:m2234_4
# 2234| v2234_6(void) = ^IndirectReadSideEffect[-1] : &:r2234_1, m2215_8
# 2234| m2234_7(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r2234_1
# 2234| m2234_8(ClassWithDestructor) = Chi : total:m2215_8, partial:m2234_7
#-----| Goto -> Block 1
# 2219| Block 15
-# 2219| r2219_90(glval>) = VariableAddress[ys] :
-# 2219| r2219_91(glval) = FunctionAddress[~vector] :
-# 2219| v2219_92(void) = Call[~vector] : func:r2219_91, this:r2219_90
-# 2219| m2219_93(unknown) = ^CallSideEffect : ~m2219_50
-# 2219| m2219_94(unknown) = Chi : total:m2219_50, partial:m2219_93
-# 2219| v2219_95(void) = ^IndirectReadSideEffect[-1] : &:r2219_90, ~m2219_94
-# 2219| m2219_96(vector) = ^IndirectMayWriteSideEffect[-1] : &:r2219_90
-# 2219| m2219_97(unknown) = Chi : total:m2219_94, partial:m2219_96
-# 2225| r2225_1(glval>) = VariableAddress[ys] :
-# 2225| m2225_2(vector) = Uninitialized[ys] : &:r2225_1
-# 2225| m2225_3(unknown) = Chi : total:m2219_97, partial:m2225_2
-# 2225| r2225_4(glval) = FunctionAddress[vector] :
-# 2225| r2225_5(int) = Constant[1] :
-# 2225| v2225_6(void) = Call[vector] : func:r2225_4, this:r2225_1, 0:r2225_5
-# 2225| m2225_7(unknown) = ^CallSideEffect : ~m2225_3
-# 2225| m2225_8(unknown) = Chi : total:m2225_3, partial:m2225_7
-# 2225| m2225_9(vector) = ^IndirectMayWriteSideEffect[-1] : &:r2225_1
-# 2225| m2225_10(unknown) = Chi : total:m2225_8, partial:m2225_9
-# 2225| r2225_11(glval &>) = VariableAddress[(__range)] :
-# 2225| r2225_12(glval>) = VariableAddress[ys] :
-# 2225| r2225_13(vector &) = CopyValue : r2225_12
-# 2225| m2225_14(vector &) = Store[(__range)] : &:r2225_11, r2225_13
-# 2225| r2225_15(glval>) = VariableAddress[(__begin)] :
-# 2225| r2225_16(glval &>) = VariableAddress[(__range)] :
-# 2225| r2225_17(vector &) = Load[(__range)] : &:r2225_16, m2225_14
-#-----| r0_35(glval>) = CopyValue : r2225_17
-#-----| r0_36(glval>) = Convert : r0_35
-# 2225| r2225_18(glval) = FunctionAddress[begin] :
-# 2225| r2225_19(iterator) = Call[begin] : func:r2225_18, this:r0_36
-#-----| v0_37(void) = ^IndirectReadSideEffect[-1] : &:r0_36, ~m2225_10
-# 2225| m2225_20(iterator) = Store[(__begin)] : &:r2225_15, r2225_19
-# 2225| r2225_21(glval>) = VariableAddress[(__end)] :
-# 2225| r2225_22(glval &>) = VariableAddress[(__range)] :
-# 2225| r2225_23(vector &) = Load[(__range)] : &:r2225_22, m2225_14
-#-----| r0_38(glval>) = CopyValue : r2225_23
-#-----| r0_39(glval>) = Convert : r0_38
-# 2225| r2225_24(glval) = FunctionAddress[end] :
-# 2225| r2225_25(iterator) = Call[end] : func:r2225_24, this:r0_39
-#-----| v0_40(void) = ^IndirectReadSideEffect[-1] : &:r0_39, ~m2225_10
-# 2225| m2225_26(iterator