---
.../Security/CWE-116/IncompleteMultiCharacterSanitization.qhelp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/javascript/ql/src/Security/CWE-116/IncompleteMultiCharacterSanitization.qhelp b/javascript/ql/src/Security/CWE-116/IncompleteMultiCharacterSanitization.qhelp
index 0e0b25b5f6c..63f28578ec1 100644
--- a/javascript/ql/src/Security/CWE-116/IncompleteMultiCharacterSanitization.qhelp
+++ b/javascript/ql/src/Security/CWE-116/IncompleteMultiCharacterSanitization.qhelp
@@ -8,7 +8,7 @@
Sanitizing untrusted input is a common technique for preventing injection attacks and other security
vulnerabilities. Regular expressions are often used to perform this sanitization. However, when the
regular expression matches multiple consecutive characters, replacing it just once
-can result in the unsafe text re-appearing in the sanitized input.
+can result in the unsafe text reappearing in the sanitized input.
Attackers can exploit this issue by crafting inputs that, when sanitized with an ineffective regular
From 4c8accd5ba24f00d4133221f20a62e6098dd6b08 Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Fri, 4 Aug 2023 17:13:24 +0100
Subject: [PATCH 039/788] Swift: Add a few more test cases.
---
.../CWE-078/CommandInjection.expected | 85 +++++++++++++++++++
.../Security/CWE-078/CommandInjection.swift | 37 ++++++++
2 files changed, 122 insertions(+)
diff --git a/swift/ql/test/query-tests/Security/CWE-078/CommandInjection.expected b/swift/ql/test/query-tests/Security/CWE-078/CommandInjection.expected
index 8c9bfed2078..a015cb69b64 100644
--- a/swift/ql/test/query-tests/Security/CWE-078/CommandInjection.expected
+++ b/swift/ql/test/query-tests/Security/CWE-078/CommandInjection.expected
@@ -78,6 +78,45 @@ edges
| CommandInjection.swift:158:45:158:77 | call to URL.init(string:) [some:0] | CommandInjection.swift:158:45:158:78 | ...! |
| CommandInjection.swift:158:45:158:78 | ...! | file://:0:0:0:0 | url |
| CommandInjection.swift:158:57:158:57 | userControlledString | CommandInjection.swift:158:45:158:77 | call to URL.init(string:) [some:0] |
+| CommandInjection.swift:172:3:172:3 | newValue | CommandInjection.swift:173:19:173:19 | newValue |
+| CommandInjection.swift:172:3:172:3 | newValue | CommandInjection.swift:174:20:174:20 | newValue |
+| CommandInjection.swift:172:3:172:3 | newValue | CommandInjection.swift:175:19:175:19 | newValue |
+| CommandInjection.swift:173:4:173:4 | [post] getter for .p1 [arguments] | CommandInjection.swift:173:4:173:4 | [post] getter for .p1 |
+| CommandInjection.swift:173:19:173:19 | newValue | CommandInjection.swift:173:4:173:4 | [post] getter for .p1 [arguments] |
+| CommandInjection.swift:174:4:174:6 | [post] ...! [arguments] | CommandInjection.swift:174:4:174:6 | [post] ...! |
+| CommandInjection.swift:174:20:174:20 | newValue | CommandInjection.swift:174:4:174:6 | [post] ...! [arguments] |
+| CommandInjection.swift:175:4:175:4 | [post] ...! [arguments] | CommandInjection.swift:175:4:175:4 | [post] ...! |
+| CommandInjection.swift:175:19:175:19 | newValue | CommandInjection.swift:175:4:175:4 | [post] ...! [arguments] |
+| CommandInjection.swift:180:9:180:13 | let ...? [some:0] | CommandInjection.swift:180:13:180:13 | userControlledString |
+| CommandInjection.swift:180:13:180:13 | userControlledString | CommandInjection.swift:184:19:184:19 | userControlledString |
+| CommandInjection.swift:180:41:180:95 | call to String.init(contentsOf:) | CommandInjection.swift:180:41:180:95 | call to String.init(contentsOf:) [some:0] |
+| CommandInjection.swift:180:41:180:95 | call to String.init(contentsOf:) [some:0] | CommandInjection.swift:180:9:180:13 | let ...? [some:0] |
+| CommandInjection.swift:184:18:184:39 | [...] | CommandInjection.swift:186:18:186:18 | tainted1 |
+| CommandInjection.swift:184:18:184:39 | [...] | CommandInjection.swift:187:19:187:19 | tainted1 |
+| CommandInjection.swift:184:18:184:39 | [...] | CommandInjection.swift:188:18:188:18 | tainted1 |
+| CommandInjection.swift:184:19:184:19 | userControlledString | CommandInjection.swift:184:18:184:39 | [...] |
+| CommandInjection.swift:184:19:184:19 | userControlledString | CommandInjection.swift:190:31:190:31 | userControlledString |
+| CommandInjection.swift:186:3:186:3 | [post] getter for .p1 [arguments] | CommandInjection.swift:186:3:186:3 | [post] getter for .p1 |
+| CommandInjection.swift:186:18:186:18 | tainted1 | CommandInjection.swift:186:3:186:3 | [post] getter for .p1 [arguments] |
+| CommandInjection.swift:186:18:186:18 | tainted1 | CommandInjection.swift:187:19:187:19 | tainted1 |
+| CommandInjection.swift:186:18:186:18 | tainted1 | CommandInjection.swift:188:18:188:18 | tainted1 |
+| CommandInjection.swift:187:3:187:5 | [post] ...! [arguments] | CommandInjection.swift:187:3:187:5 | [post] ...! |
+| CommandInjection.swift:187:19:187:19 | tainted1 | CommandInjection.swift:187:3:187:5 | [post] ...! [arguments] |
+| CommandInjection.swift:187:19:187:19 | tainted1 | CommandInjection.swift:188:18:188:18 | tainted1 |
+| CommandInjection.swift:188:3:188:3 | [post] ...! [arguments] | CommandInjection.swift:188:3:188:3 | [post] ...! |
+| CommandInjection.swift:188:18:188:18 | tainted1 | CommandInjection.swift:188:3:188:3 | [post] ...! [arguments] |
+| CommandInjection.swift:190:30:190:51 | [...] | CommandInjection.swift:192:18:192:18 | tainted2 |
+| CommandInjection.swift:190:30:190:51 | [...] | CommandInjection.swift:193:19:193:19 | tainted2 |
+| CommandInjection.swift:190:30:190:51 | [...] | CommandInjection.swift:194:18:194:18 | tainted2 |
+| CommandInjection.swift:190:30:190:51 | [...] | CommandInjection.swift:196:13:196:13 | tainted2 |
+| CommandInjection.swift:190:31:190:31 | userControlledString | CommandInjection.swift:190:30:190:51 | [...] |
+| CommandInjection.swift:192:3:192:3 | [post] getter for .p1 [arguments] | CommandInjection.swift:192:3:192:3 | [post] getter for .p1 |
+| CommandInjection.swift:192:18:192:18 | tainted2 | CommandInjection.swift:192:3:192:3 | [post] getter for .p1 [arguments] |
+| CommandInjection.swift:193:3:193:5 | [post] ...! [arguments] | CommandInjection.swift:193:3:193:5 | [post] ...! |
+| CommandInjection.swift:193:19:193:19 | tainted2 | CommandInjection.swift:193:3:193:5 | [post] ...! [arguments] |
+| CommandInjection.swift:194:3:194:3 | [post] ...! [arguments] | CommandInjection.swift:194:3:194:3 | [post] ...! |
+| CommandInjection.swift:194:18:194:18 | tainted2 | CommandInjection.swift:194:3:194:3 | [post] ...! [arguments] |
+| CommandInjection.swift:196:13:196:13 | tainted2 | CommandInjection.swift:172:3:172:3 | newValue |
| file://:0:0:0:0 | url | file://:0:0:0:0 | url |
| file://:0:0:0:0 | url | file://:0:0:0:0 | url |
nodes
@@ -159,6 +198,43 @@ nodes
| CommandInjection.swift:158:45:158:78 | ...! | semmle.label | ...! |
| CommandInjection.swift:158:45:158:78 | ...! | semmle.label | ...! |
| CommandInjection.swift:158:57:158:57 | userControlledString | semmle.label | userControlledString |
+| CommandInjection.swift:172:3:172:3 | newValue | semmle.label | newValue |
+| CommandInjection.swift:173:4:173:4 | [post] getter for .p1 | semmle.label | [post] getter for .p1 |
+| CommandInjection.swift:173:4:173:4 | [post] getter for .p1 [arguments] | semmle.label | [post] getter for .p1 [arguments] |
+| CommandInjection.swift:173:19:173:19 | newValue | semmle.label | newValue |
+| CommandInjection.swift:174:4:174:6 | [post] ...! | semmle.label | [post] ...! |
+| CommandInjection.swift:174:4:174:6 | [post] ...! [arguments] | semmle.label | [post] ...! [arguments] |
+| CommandInjection.swift:174:20:174:20 | newValue | semmle.label | newValue |
+| CommandInjection.swift:175:4:175:4 | [post] ...! | semmle.label | [post] ...! |
+| CommandInjection.swift:175:4:175:4 | [post] ...! [arguments] | semmle.label | [post] ...! [arguments] |
+| CommandInjection.swift:175:19:175:19 | newValue | semmle.label | newValue |
+| CommandInjection.swift:180:9:180:13 | let ...? [some:0] | semmle.label | let ...? [some:0] |
+| CommandInjection.swift:180:13:180:13 | userControlledString | semmle.label | userControlledString |
+| CommandInjection.swift:180:41:180:95 | call to String.init(contentsOf:) | semmle.label | call to String.init(contentsOf:) |
+| CommandInjection.swift:180:41:180:95 | call to String.init(contentsOf:) [some:0] | semmle.label | call to String.init(contentsOf:) [some:0] |
+| CommandInjection.swift:184:18:184:39 | [...] | semmle.label | [...] |
+| CommandInjection.swift:184:19:184:19 | userControlledString | semmle.label | userControlledString |
+| CommandInjection.swift:186:3:186:3 | [post] getter for .p1 | semmle.label | [post] getter for .p1 |
+| CommandInjection.swift:186:3:186:3 | [post] getter for .p1 [arguments] | semmle.label | [post] getter for .p1 [arguments] |
+| CommandInjection.swift:186:18:186:18 | tainted1 | semmle.label | tainted1 |
+| CommandInjection.swift:187:3:187:5 | [post] ...! | semmle.label | [post] ...! |
+| CommandInjection.swift:187:3:187:5 | [post] ...! [arguments] | semmle.label | [post] ...! [arguments] |
+| CommandInjection.swift:187:19:187:19 | tainted1 | semmle.label | tainted1 |
+| CommandInjection.swift:188:3:188:3 | [post] ...! | semmle.label | [post] ...! |
+| CommandInjection.swift:188:3:188:3 | [post] ...! [arguments] | semmle.label | [post] ...! [arguments] |
+| CommandInjection.swift:188:18:188:18 | tainted1 | semmle.label | tainted1 |
+| CommandInjection.swift:190:30:190:51 | [...] | semmle.label | [...] |
+| CommandInjection.swift:190:31:190:31 | userControlledString | semmle.label | userControlledString |
+| CommandInjection.swift:192:3:192:3 | [post] getter for .p1 | semmle.label | [post] getter for .p1 |
+| CommandInjection.swift:192:3:192:3 | [post] getter for .p1 [arguments] | semmle.label | [post] getter for .p1 [arguments] |
+| CommandInjection.swift:192:18:192:18 | tainted2 | semmle.label | tainted2 |
+| CommandInjection.swift:193:3:193:5 | [post] ...! | semmle.label | [post] ...! |
+| CommandInjection.swift:193:3:193:5 | [post] ...! [arguments] | semmle.label | [post] ...! [arguments] |
+| CommandInjection.swift:193:19:193:19 | tainted2 | semmle.label | tainted2 |
+| CommandInjection.swift:194:3:194:3 | [post] ...! | semmle.label | [post] ...! |
+| CommandInjection.swift:194:3:194:3 | [post] ...! [arguments] | semmle.label | [post] ...! [arguments] |
+| CommandInjection.swift:194:18:194:18 | tainted2 | semmle.label | tainted2 |
+| CommandInjection.swift:196:13:196:13 | tainted2 | semmle.label | tainted2 |
| file://:0:0:0:0 | url | semmle.label | url |
| file://:0:0:0:0 | url | semmle.label | url |
| file://:0:0:0:0 | url | semmle.label | url |
@@ -183,5 +259,14 @@ subpaths
| CommandInjection.swift:155:40:155:73 | ...! | CommandInjection.swift:99:40:99:94 | call to String.init(contentsOf:) | CommandInjection.swift:155:40:155:73 | ...! | This command depends on a $@. | CommandInjection.swift:99:40:99:94 | call to String.init(contentsOf:) | user-provided value |
| CommandInjection.swift:156:32:156:53 | [...] | CommandInjection.swift:99:40:99:94 | call to String.init(contentsOf:) | CommandInjection.swift:156:32:156:53 | [...] | This command depends on a $@. | CommandInjection.swift:99:40:99:94 | call to String.init(contentsOf:) | user-provided value |
| CommandInjection.swift:158:45:158:78 | ...! | CommandInjection.swift:99:40:99:94 | call to String.init(contentsOf:) | CommandInjection.swift:158:45:158:78 | ...! | This command depends on a $@. | CommandInjection.swift:99:40:99:94 | call to String.init(contentsOf:) | user-provided value |
+| CommandInjection.swift:173:4:173:4 | [post] getter for .p1 | CommandInjection.swift:180:41:180:95 | call to String.init(contentsOf:) | CommandInjection.swift:173:4:173:4 | [post] getter for .p1 | This command depends on a $@. | CommandInjection.swift:180:41:180:95 | call to String.init(contentsOf:) | user-provided value |
+| CommandInjection.swift:174:4:174:6 | [post] ...! | CommandInjection.swift:180:41:180:95 | call to String.init(contentsOf:) | CommandInjection.swift:174:4:174:6 | [post] ...! | This command depends on a $@. | CommandInjection.swift:180:41:180:95 | call to String.init(contentsOf:) | user-provided value |
+| CommandInjection.swift:175:4:175:4 | [post] ...! | CommandInjection.swift:180:41:180:95 | call to String.init(contentsOf:) | CommandInjection.swift:175:4:175:4 | [post] ...! | This command depends on a $@. | CommandInjection.swift:180:41:180:95 | call to String.init(contentsOf:) | user-provided value |
+| CommandInjection.swift:186:3:186:3 | [post] getter for .p1 | CommandInjection.swift:180:41:180:95 | call to String.init(contentsOf:) | CommandInjection.swift:186:3:186:3 | [post] getter for .p1 | This command depends on a $@. | CommandInjection.swift:180:41:180:95 | call to String.init(contentsOf:) | user-provided value |
+| CommandInjection.swift:187:3:187:5 | [post] ...! | CommandInjection.swift:180:41:180:95 | call to String.init(contentsOf:) | CommandInjection.swift:187:3:187:5 | [post] ...! | This command depends on a $@. | CommandInjection.swift:180:41:180:95 | call to String.init(contentsOf:) | user-provided value |
+| CommandInjection.swift:188:3:188:3 | [post] ...! | CommandInjection.swift:180:41:180:95 | call to String.init(contentsOf:) | CommandInjection.swift:188:3:188:3 | [post] ...! | This command depends on a $@. | CommandInjection.swift:180:41:180:95 | call to String.init(contentsOf:) | user-provided value |
+| CommandInjection.swift:192:3:192:3 | [post] getter for .p1 | CommandInjection.swift:180:41:180:95 | call to String.init(contentsOf:) | CommandInjection.swift:192:3:192:3 | [post] getter for .p1 | This command depends on a $@. | CommandInjection.swift:180:41:180:95 | call to String.init(contentsOf:) | user-provided value |
+| CommandInjection.swift:193:3:193:5 | [post] ...! | CommandInjection.swift:180:41:180:95 | call to String.init(contentsOf:) | CommandInjection.swift:193:3:193:5 | [post] ...! | This command depends on a $@. | CommandInjection.swift:180:41:180:95 | call to String.init(contentsOf:) | user-provided value |
+| CommandInjection.swift:194:3:194:3 | [post] ...! | CommandInjection.swift:180:41:180:95 | call to String.init(contentsOf:) | CommandInjection.swift:194:3:194:3 | [post] ...! | This command depends on a $@. | CommandInjection.swift:180:41:180:95 | call to String.init(contentsOf:) | user-provided value |
| file://:0:0:0:0 | url | CommandInjection.swift:99:40:99:94 | call to String.init(contentsOf:) | file://:0:0:0:0 | url | This command depends on a $@. | CommandInjection.swift:99:40:99:94 | call to String.init(contentsOf:) | user-provided value |
| file://:0:0:0:0 | url | CommandInjection.swift:99:40:99:94 | call to String.init(contentsOf:) | file://:0:0:0:0 | url | This command depends on a $@. | CommandInjection.swift:99:40:99:94 | call to String.init(contentsOf:) | user-provided value |
diff --git a/swift/ql/test/query-tests/Security/CWE-078/CommandInjection.swift b/swift/ql/test/query-tests/Security/CWE-078/CommandInjection.swift
index 9c7827fe009..c1facad1305 100644
--- a/swift/ql/test/query-tests/Security/CWE-078/CommandInjection.swift
+++ b/swift/ql/test/query-tests/Security/CWE-078/CommandInjection.swift
@@ -159,3 +159,40 @@ func testCommandInjectionMore(mySafeString: String) {
task11.variables = ["abc": userControlledString] // BAD [NOT DETECTED]
task11.execute(withInput: nil)
}
+
+struct MyClass {
+ let p1 : Process
+ let p2 : Process?
+ let p3 : Process!
+
+ var myValue: [String]? {
+ get {
+ return nil
+ }
+ set {
+ p1.arguments = newValue // BAD
+ p2!.arguments = newValue // BAD
+ p3.arguments = newValue // BAD
+ }
+ }
+
+ mutating func myFunc() {
+ guard let userControlledString = try? String(contentsOf: URL(string: "http://example.com/")!) else {
+ return
+ }
+
+ let tainted1 = [userControlledString]
+
+ p1.arguments = tainted1 // BAD
+ p2!.arguments = tainted1 // BAD
+ p3.arguments = tainted1 // BAD
+
+ let tainted2 : [String]? = [userControlledString]
+
+ p1.arguments = tainted2 // BAD
+ p2!.arguments = tainted2 // BAD
+ p3.arguments = tainted2 // BAD
+
+ myValue = tainted2
+ }
+}
From a73354d0b3d29a59f1822b9bc789dff5662b3b5c Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Mon, 7 Aug 2023 20:14:07 +0100
Subject: [PATCH 040/788] Swift: Accept test failures.
---
.../CWE-079/UnsafeWebViewFetch.expected | 50 +------------------
1 file changed, 2 insertions(+), 48 deletions(-)
diff --git a/swift/ql/test/query-tests/Security/CWE-079/UnsafeWebViewFetch.expected b/swift/ql/test/query-tests/Security/CWE-079/UnsafeWebViewFetch.expected
index a4fc0d17312..fb06adf5fb0 100644
--- a/swift/ql/test/query-tests/Security/CWE-079/UnsafeWebViewFetch.expected
+++ b/swift/ql/test/query-tests/Security/CWE-079/UnsafeWebViewFetch.expected
@@ -17,27 +17,13 @@ edges
| UnsafeWebViewFetch.swift:117:21:117:35 | call to getRemoteData() | UnsafeWebViewFetch.swift:139:25:139:25 | remoteString |
| UnsafeWebViewFetch.swift:117:21:117:35 | call to getRemoteData() | UnsafeWebViewFetch.swift:141:25:141:25 | remoteString |
| UnsafeWebViewFetch.swift:117:21:117:35 | call to getRemoteData() | UnsafeWebViewFetch.swift:150:24:150:37 | .utf8 |
-| UnsafeWebViewFetch.swift:131:18:131:42 | call to URL.init(string:) | UnsafeWebViewFetch.swift:131:18:131:42 | call to URL.init(string:) [some:0] |
-| UnsafeWebViewFetch.swift:131:18:131:42 | call to URL.init(string:) | UnsafeWebViewFetch.swift:132:52:132:52 | remoteURL |
-| UnsafeWebViewFetch.swift:131:18:131:42 | call to URL.init(string:) | UnsafeWebViewFetch.swift:138:47:138:56 | ...! |
-| UnsafeWebViewFetch.swift:131:18:131:42 | call to URL.init(string:) | UnsafeWebViewFetch.swift:139:48:139:57 | ...! |
-| UnsafeWebViewFetch.swift:131:18:131:42 | call to URL.init(string:) | UnsafeWebViewFetch.swift:153:85:153:94 | ...! |
-| UnsafeWebViewFetch.swift:131:18:131:42 | call to URL.init(string:) | UnsafeWebViewFetch.swift:154:86:154:95 | ...! |
| UnsafeWebViewFetch.swift:131:18:131:42 | call to URL.init(string:) [some:0] | UnsafeWebViewFetch.swift:138:47:138:47 | remoteURL [some:0] |
| UnsafeWebViewFetch.swift:131:18:131:42 | call to URL.init(string:) [some:0] | UnsafeWebViewFetch.swift:139:48:139:48 | remoteURL [some:0] |
| UnsafeWebViewFetch.swift:131:18:131:42 | call to URL.init(string:) [some:0] | UnsafeWebViewFetch.swift:153:85:153:85 | remoteURL [some:0] |
| UnsafeWebViewFetch.swift:131:18:131:42 | call to URL.init(string:) [some:0] | UnsafeWebViewFetch.swift:154:86:154:86 | remoteURL [some:0] |
-| UnsafeWebViewFetch.swift:131:30:131:30 | remoteString | UnsafeWebViewFetch.swift:131:18:131:42 | call to URL.init(string:) |
-| UnsafeWebViewFetch.swift:132:19:132:61 | call to URL.init(string:relativeTo:) | UnsafeWebViewFetch.swift:132:19:132:61 | call to URL.init(string:relativeTo:) [some:0] |
-| UnsafeWebViewFetch.swift:132:19:132:61 | call to URL.init(string:relativeTo:) | UnsafeWebViewFetch.swift:140:47:140:57 | ...! |
-| UnsafeWebViewFetch.swift:132:19:132:61 | call to URL.init(string:relativeTo:) | UnsafeWebViewFetch.swift:141:48:141:58 | ...! |
-| UnsafeWebViewFetch.swift:132:19:132:61 | call to URL.init(string:relativeTo:) [some:0] | UnsafeWebViewFetch.swift:140:47:140:47 | remoteURL2 [some:0] |
-| UnsafeWebViewFetch.swift:132:19:132:61 | call to URL.init(string:relativeTo:) [some:0] | UnsafeWebViewFetch.swift:141:48:141:48 | remoteURL2 [some:0] |
-| UnsafeWebViewFetch.swift:132:52:132:52 | remoteURL | UnsafeWebViewFetch.swift:132:19:132:61 | call to URL.init(string:relativeTo:) |
+| UnsafeWebViewFetch.swift:131:30:131:30 | remoteString | UnsafeWebViewFetch.swift:131:18:131:42 | call to URL.init(string:) [some:0] |
| UnsafeWebViewFetch.swift:138:47:138:47 | remoteURL [some:0] | UnsafeWebViewFetch.swift:138:47:138:56 | ...! |
| UnsafeWebViewFetch.swift:139:48:139:48 | remoteURL [some:0] | UnsafeWebViewFetch.swift:139:48:139:57 | ...! |
-| UnsafeWebViewFetch.swift:140:47:140:47 | remoteURL2 [some:0] | UnsafeWebViewFetch.swift:140:47:140:57 | ...! |
-| UnsafeWebViewFetch.swift:141:48:141:48 | remoteURL2 [some:0] | UnsafeWebViewFetch.swift:141:48:141:58 | ...! |
| UnsafeWebViewFetch.swift:150:19:150:41 | call to Data.init(_:) | UnsafeWebViewFetch.swift:152:15:152:15 | remoteData |
| UnsafeWebViewFetch.swift:150:19:150:41 | call to Data.init(_:) | UnsafeWebViewFetch.swift:154:15:154:15 | remoteData |
| UnsafeWebViewFetch.swift:150:24:150:37 | .utf8 | UnsafeWebViewFetch.swift:150:19:150:41 | call to Data.init(_:) |
@@ -52,27 +38,13 @@ edges
| UnsafeWebViewFetch.swift:164:21:164:35 | call to getRemoteData() | UnsafeWebViewFetch.swift:186:25:186:25 | remoteString |
| UnsafeWebViewFetch.swift:164:21:164:35 | call to getRemoteData() | UnsafeWebViewFetch.swift:188:25:188:25 | remoteString |
| UnsafeWebViewFetch.swift:164:21:164:35 | call to getRemoteData() | UnsafeWebViewFetch.swift:197:24:197:37 | .utf8 |
-| UnsafeWebViewFetch.swift:178:18:178:42 | call to URL.init(string:) | UnsafeWebViewFetch.swift:178:18:178:42 | call to URL.init(string:) [some:0] |
-| UnsafeWebViewFetch.swift:178:18:178:42 | call to URL.init(string:) | UnsafeWebViewFetch.swift:179:52:179:52 | remoteURL |
-| UnsafeWebViewFetch.swift:178:18:178:42 | call to URL.init(string:) | UnsafeWebViewFetch.swift:185:47:185:56 | ...! |
-| UnsafeWebViewFetch.swift:178:18:178:42 | call to URL.init(string:) | UnsafeWebViewFetch.swift:186:48:186:57 | ...! |
-| UnsafeWebViewFetch.swift:178:18:178:42 | call to URL.init(string:) | UnsafeWebViewFetch.swift:200:90:200:99 | ...! |
-| UnsafeWebViewFetch.swift:178:18:178:42 | call to URL.init(string:) | UnsafeWebViewFetch.swift:201:91:201:100 | ...! |
| UnsafeWebViewFetch.swift:178:18:178:42 | call to URL.init(string:) [some:0] | UnsafeWebViewFetch.swift:185:47:185:47 | remoteURL [some:0] |
| UnsafeWebViewFetch.swift:178:18:178:42 | call to URL.init(string:) [some:0] | UnsafeWebViewFetch.swift:186:48:186:48 | remoteURL [some:0] |
| UnsafeWebViewFetch.swift:178:18:178:42 | call to URL.init(string:) [some:0] | UnsafeWebViewFetch.swift:200:90:200:90 | remoteURL [some:0] |
| UnsafeWebViewFetch.swift:178:18:178:42 | call to URL.init(string:) [some:0] | UnsafeWebViewFetch.swift:201:91:201:91 | remoteURL [some:0] |
-| UnsafeWebViewFetch.swift:178:30:178:30 | remoteString | UnsafeWebViewFetch.swift:178:18:178:42 | call to URL.init(string:) |
-| UnsafeWebViewFetch.swift:179:19:179:61 | call to URL.init(string:relativeTo:) | UnsafeWebViewFetch.swift:179:19:179:61 | call to URL.init(string:relativeTo:) [some:0] |
-| UnsafeWebViewFetch.swift:179:19:179:61 | call to URL.init(string:relativeTo:) | UnsafeWebViewFetch.swift:187:47:187:57 | ...! |
-| UnsafeWebViewFetch.swift:179:19:179:61 | call to URL.init(string:relativeTo:) | UnsafeWebViewFetch.swift:188:48:188:58 | ...! |
-| UnsafeWebViewFetch.swift:179:19:179:61 | call to URL.init(string:relativeTo:) [some:0] | UnsafeWebViewFetch.swift:187:47:187:47 | remoteURL2 [some:0] |
-| UnsafeWebViewFetch.swift:179:19:179:61 | call to URL.init(string:relativeTo:) [some:0] | UnsafeWebViewFetch.swift:188:48:188:48 | remoteURL2 [some:0] |
-| UnsafeWebViewFetch.swift:179:52:179:52 | remoteURL | UnsafeWebViewFetch.swift:179:19:179:61 | call to URL.init(string:relativeTo:) |
+| UnsafeWebViewFetch.swift:178:30:178:30 | remoteString | UnsafeWebViewFetch.swift:178:18:178:42 | call to URL.init(string:) [some:0] |
| UnsafeWebViewFetch.swift:185:47:185:47 | remoteURL [some:0] | UnsafeWebViewFetch.swift:185:47:185:56 | ...! |
| UnsafeWebViewFetch.swift:186:48:186:48 | remoteURL [some:0] | UnsafeWebViewFetch.swift:186:48:186:57 | ...! |
-| UnsafeWebViewFetch.swift:187:47:187:47 | remoteURL2 [some:0] | UnsafeWebViewFetch.swift:187:47:187:57 | ...! |
-| UnsafeWebViewFetch.swift:188:48:188:48 | remoteURL2 [some:0] | UnsafeWebViewFetch.swift:188:48:188:58 | ...! |
| UnsafeWebViewFetch.swift:197:19:197:41 | call to Data.init(_:) | UnsafeWebViewFetch.swift:199:15:199:15 | remoteData |
| UnsafeWebViewFetch.swift:197:19:197:41 | call to Data.init(_:) | UnsafeWebViewFetch.swift:201:15:201:15 | remoteData |
| UnsafeWebViewFetch.swift:197:24:197:37 | .utf8 | UnsafeWebViewFetch.swift:197:19:197:41 | call to Data.init(_:) |
@@ -94,12 +66,8 @@ nodes
| UnsafeWebViewFetch.swift:121:25:121:25 | remoteString | semmle.label | remoteString |
| UnsafeWebViewFetch.swift:124:25:124:51 | ... .+(_:_:) ... | semmle.label | ... .+(_:_:) ... |
| UnsafeWebViewFetch.swift:127:25:127:25 | "..." | semmle.label | "..." |
-| UnsafeWebViewFetch.swift:131:18:131:42 | call to URL.init(string:) | semmle.label | call to URL.init(string:) |
| UnsafeWebViewFetch.swift:131:18:131:42 | call to URL.init(string:) [some:0] | semmle.label | call to URL.init(string:) [some:0] |
| UnsafeWebViewFetch.swift:131:30:131:30 | remoteString | semmle.label | remoteString |
-| UnsafeWebViewFetch.swift:132:19:132:61 | call to URL.init(string:relativeTo:) | semmle.label | call to URL.init(string:relativeTo:) |
-| UnsafeWebViewFetch.swift:132:19:132:61 | call to URL.init(string:relativeTo:) [some:0] | semmle.label | call to URL.init(string:relativeTo:) [some:0] |
-| UnsafeWebViewFetch.swift:132:52:132:52 | remoteURL | semmle.label | remoteURL |
| UnsafeWebViewFetch.swift:135:25:135:25 | remoteString | semmle.label | remoteString |
| UnsafeWebViewFetch.swift:137:25:137:25 | remoteString | semmle.label | remoteString |
| UnsafeWebViewFetch.swift:138:47:138:47 | remoteURL [some:0] | semmle.label | remoteURL [some:0] |
@@ -107,11 +75,7 @@ nodes
| UnsafeWebViewFetch.swift:139:25:139:25 | remoteString | semmle.label | remoteString |
| UnsafeWebViewFetch.swift:139:48:139:48 | remoteURL [some:0] | semmle.label | remoteURL [some:0] |
| UnsafeWebViewFetch.swift:139:48:139:57 | ...! | semmle.label | ...! |
-| UnsafeWebViewFetch.swift:140:47:140:47 | remoteURL2 [some:0] | semmle.label | remoteURL2 [some:0] |
-| UnsafeWebViewFetch.swift:140:47:140:57 | ...! | semmle.label | ...! |
| UnsafeWebViewFetch.swift:141:25:141:25 | remoteString | semmle.label | remoteString |
-| UnsafeWebViewFetch.swift:141:48:141:48 | remoteURL2 [some:0] | semmle.label | remoteURL2 [some:0] |
-| UnsafeWebViewFetch.swift:141:48:141:58 | ...! | semmle.label | ...! |
| UnsafeWebViewFetch.swift:150:19:150:41 | call to Data.init(_:) | semmle.label | call to Data.init(_:) |
| UnsafeWebViewFetch.swift:150:24:150:37 | .utf8 | semmle.label | .utf8 |
| UnsafeWebViewFetch.swift:152:15:152:15 | remoteData | semmle.label | remoteData |
@@ -125,12 +89,8 @@ nodes
| UnsafeWebViewFetch.swift:168:25:168:25 | remoteString | semmle.label | remoteString |
| UnsafeWebViewFetch.swift:171:25:171:51 | ... .+(_:_:) ... | semmle.label | ... .+(_:_:) ... |
| UnsafeWebViewFetch.swift:174:25:174:25 | "..." | semmle.label | "..." |
-| UnsafeWebViewFetch.swift:178:18:178:42 | call to URL.init(string:) | semmle.label | call to URL.init(string:) |
| UnsafeWebViewFetch.swift:178:18:178:42 | call to URL.init(string:) [some:0] | semmle.label | call to URL.init(string:) [some:0] |
| UnsafeWebViewFetch.swift:178:30:178:30 | remoteString | semmle.label | remoteString |
-| UnsafeWebViewFetch.swift:179:19:179:61 | call to URL.init(string:relativeTo:) | semmle.label | call to URL.init(string:relativeTo:) |
-| UnsafeWebViewFetch.swift:179:19:179:61 | call to URL.init(string:relativeTo:) [some:0] | semmle.label | call to URL.init(string:relativeTo:) [some:0] |
-| UnsafeWebViewFetch.swift:179:52:179:52 | remoteURL | semmle.label | remoteURL |
| UnsafeWebViewFetch.swift:182:25:182:25 | remoteString | semmle.label | remoteString |
| UnsafeWebViewFetch.swift:184:25:184:25 | remoteString | semmle.label | remoteString |
| UnsafeWebViewFetch.swift:185:47:185:47 | remoteURL [some:0] | semmle.label | remoteURL [some:0] |
@@ -138,11 +98,7 @@ nodes
| UnsafeWebViewFetch.swift:186:25:186:25 | remoteString | semmle.label | remoteString |
| UnsafeWebViewFetch.swift:186:48:186:48 | remoteURL [some:0] | semmle.label | remoteURL [some:0] |
| UnsafeWebViewFetch.swift:186:48:186:57 | ...! | semmle.label | ...! |
-| UnsafeWebViewFetch.swift:187:47:187:47 | remoteURL2 [some:0] | semmle.label | remoteURL2 [some:0] |
-| UnsafeWebViewFetch.swift:187:47:187:57 | ...! | semmle.label | ...! |
| UnsafeWebViewFetch.swift:188:25:188:25 | remoteString | semmle.label | remoteString |
-| UnsafeWebViewFetch.swift:188:48:188:48 | remoteURL2 [some:0] | semmle.label | remoteURL2 [some:0] |
-| UnsafeWebViewFetch.swift:188:48:188:58 | ...! | semmle.label | ...! |
| UnsafeWebViewFetch.swift:197:19:197:41 | call to Data.init(_:) | semmle.label | call to Data.init(_:) |
| UnsafeWebViewFetch.swift:197:24:197:37 | .utf8 | semmle.label | .utf8 |
| UnsafeWebViewFetch.swift:199:15:199:15 | remoteData | semmle.label | remoteData |
@@ -164,13 +120,11 @@ subpaths
| UnsafeWebViewFetch.swift:124:25:124:51 | ... .+(_:_:) ... | UnsafeWebViewFetch.swift:94:14:94:37 | call to String.init(contentsOf:) | UnsafeWebViewFetch.swift:124:25:124:51 | ... .+(_:_:) ... | Tainted data is used in a WebView fetch without restricting the base URL. |
| UnsafeWebViewFetch.swift:127:25:127:25 | "..." | UnsafeWebViewFetch.swift:94:14:94:37 | call to String.init(contentsOf:) | UnsafeWebViewFetch.swift:127:25:127:25 | "..." | Tainted data is used in a WebView fetch without restricting the base URL. |
| UnsafeWebViewFetch.swift:139:25:139:25 | remoteString | UnsafeWebViewFetch.swift:94:14:94:37 | call to String.init(contentsOf:) | UnsafeWebViewFetch.swift:139:25:139:25 | remoteString | Tainted data is used in a WebView fetch with a tainted base URL. |
-| UnsafeWebViewFetch.swift:141:25:141:25 | remoteString | UnsafeWebViewFetch.swift:94:14:94:37 | call to String.init(contentsOf:) | UnsafeWebViewFetch.swift:141:25:141:25 | remoteString | Tainted data is used in a WebView fetch with a tainted base URL. |
| UnsafeWebViewFetch.swift:154:15:154:15 | remoteData | UnsafeWebViewFetch.swift:94:14:94:37 | call to String.init(contentsOf:) | UnsafeWebViewFetch.swift:154:15:154:15 | remoteData | Tainted data is used in a WebView fetch with a tainted base URL. |
| UnsafeWebViewFetch.swift:167:25:167:39 | call to getRemoteData() | UnsafeWebViewFetch.swift:94:14:94:37 | call to String.init(contentsOf:) | UnsafeWebViewFetch.swift:167:25:167:39 | call to getRemoteData() | Tainted data is used in a WebView fetch without restricting the base URL. |
| UnsafeWebViewFetch.swift:168:25:168:25 | remoteString | UnsafeWebViewFetch.swift:94:14:94:37 | call to String.init(contentsOf:) | UnsafeWebViewFetch.swift:168:25:168:25 | remoteString | Tainted data is used in a WebView fetch without restricting the base URL. |
| UnsafeWebViewFetch.swift:171:25:171:51 | ... .+(_:_:) ... | UnsafeWebViewFetch.swift:94:14:94:37 | call to String.init(contentsOf:) | UnsafeWebViewFetch.swift:171:25:171:51 | ... .+(_:_:) ... | Tainted data is used in a WebView fetch without restricting the base URL. |
| UnsafeWebViewFetch.swift:174:25:174:25 | "..." | UnsafeWebViewFetch.swift:94:14:94:37 | call to String.init(contentsOf:) | UnsafeWebViewFetch.swift:174:25:174:25 | "..." | Tainted data is used in a WebView fetch without restricting the base URL. |
| UnsafeWebViewFetch.swift:186:25:186:25 | remoteString | UnsafeWebViewFetch.swift:94:14:94:37 | call to String.init(contentsOf:) | UnsafeWebViewFetch.swift:186:25:186:25 | remoteString | Tainted data is used in a WebView fetch with a tainted base URL. |
-| UnsafeWebViewFetch.swift:188:25:188:25 | remoteString | UnsafeWebViewFetch.swift:94:14:94:37 | call to String.init(contentsOf:) | UnsafeWebViewFetch.swift:188:25:188:25 | remoteString | Tainted data is used in a WebView fetch with a tainted base URL. |
| UnsafeWebViewFetch.swift:201:15:201:15 | remoteData | UnsafeWebViewFetch.swift:94:14:94:37 | call to String.init(contentsOf:) | UnsafeWebViewFetch.swift:201:15:201:15 | remoteData | Tainted data is used in a WebView fetch with a tainted base URL. |
| UnsafeWebViewFetch.swift:210:25:210:25 | htmlData | UnsafeWebViewFetch.swift:94:14:94:37 | call to String.init(contentsOf:) | UnsafeWebViewFetch.swift:210:25:210:25 | htmlData | Tainted data is used in a WebView fetch without restricting the base URL. |
From b2d3d465f06958455979cf658ddd546e79875084 Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Mon, 7 Aug 2023 15:25:36 +0100
Subject: [PATCH 041/788] Swift: Add more missing details to the URL model
(along with a change from the SetContent PR, this fixes the test failures we
were getting).
---
.../swift/frameworks/StandardLibrary/Url.qll | 27 +++++++++++--------
.../CWE-079/UnsafeWebViewFetch.expected | 26 ++++++++++++++++++
2 files changed, 42 insertions(+), 11 deletions(-)
diff --git a/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/Url.qll b/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/Url.qll
index d86c004b1b2..a24a394dd0f 100644
--- a/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/Url.qll
+++ b/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/Url.qll
@@ -86,28 +86,32 @@ private class UrlSummaries extends SummaryModelCsv {
row =
[
";URL;true;init(string:);(String);;Argument[0];ReturnValue.OptionalSome;taint",
- ";URL;true;init(string:relativeTo:);(String,URL?);;Argument[0..1];ReturnValue.OptionalSome;taint",
+ ";URL;true;init(string:relativeTo:);(String,URL?);;Argument[0];ReturnValue.OptionalSome;taint",
+ ";URL;true;init(string:relativeTo:);(String,URL?);;Argument[1].OptionalSome;ReturnValue.OptionalSome;taint",
";URL;true;init(fileURLWithPath:);;;Argument[0];ReturnValue;taint",
";URL;true;init(fileURLWithPath:isDirectory:);;;Argument[0];ReturnValue;taint",
- ";URL;true;init(fileURLWithPath:relativeTo:);;;Argument[0..1];ReturnValue;taint",
+ ";URL;true;init(fileURLWithPath:relativeTo:);;;Argument[0];ReturnValue;taint",
+ ";URL;true;init(fileURLWithPath:relativeTo:);;;Argument[1].OptionalSome;ReturnValue;taint",
";URL;true;init(fileURLWithPath:isDirectory:relativeTo:);;;Argument[0];ReturnValue;taint",
- ";URL;true;init(fileURLWithPath:isDirectory:relativeTo:);;;Argument[2];ReturnValue;taint",
+ ";URL;true;init(fileURLWithPath:isDirectory:relativeTo:);;;Argument[2].OptionalSome;ReturnValue;taint",
";URL;true;init(fileURLWithFileSystemRepresentation:isDirectory:relativeTo:);;;Argument[0];ReturnValue;taint",
- ";URL;true;init(fileURLWithFileSystemRepresentation:isDirectory:relativeTo:);;;Argument[2];ReturnValue;taint",
+ ";URL;true;init(fileURLWithFileSystemRepresentation:isDirectory:relativeTo:);;;Argument[2].OptionalSome;ReturnValue;taint",
";URL;true;init(fileReferenceLiteralResourceName:);;;Argument[0];ReturnValue;taint",
";URL;true;init(_:);;;Argument[0];ReturnValue.OptionalSome;taint",
";URL;true;init(_:isDirectory:);;;Argument[0];ReturnValue.OptionalSome;taint",
";URL;true;init(resolvingBookmarkData:options:relativeTo:bookmarkDataIsStale:);;;Argument[0];ReturnValue;taint",
- ";URL;true;init(resolvingBookmarkData:options:relativeTo:bookmarkDataIsStale:);;;Argument[2];ReturnValue;taint",
+ ";URL;true;init(resolvingBookmarkData:options:relativeTo:bookmarkDataIsStale:);;;Argument[2].OptionalSome;ReturnValue;taint",
";URL;true;init(resolvingAliasFileAt:options:);;;Argument[0];ReturnValue;taint",
";URL;true;init(resource:);;;Argument[0];ReturnValue;taint",
- ";URL;true;init(dataRepresentation:relativeTo:isAbsolute:);;;Argument[0..1];ReturnValue;taint",
+ ";URL;true;init(dataRepresentation:relativeTo:isAbsolute:);;;Argument[0];ReturnValue;taint",
+ ";URL;true;init(dataRepresentation:relativeTo:isAbsolute:);;;Argument[1].OptionalSome;ReturnValue;taint",
";URL;true;init(_:strategy:);;;Argument[0];ReturnValue;taint",
- ";URL;true;init(filePath:directoryHint:);;;Argument[0];ReturnValue;taint",
+ ";URL;true;init(filePath:directoryHint:);;;Argument[0];ReturnValue.OptionalSome;taint",
";URL;true;init(filePath:directoryHint:relativeTo:);;;Argument[0];ReturnValue;taint",
- ";URL;true;init(filePath:directoryHint:relativeTo:);;;Argument[2];ReturnValue;taint",
- ";URL;true;init(for:in:appropriateFor:create:);;;Argument[0..2];ReturnValue;taint",
- ";URL;true;init(string:encodingInvalidCharacters:);;;Argument[0];ReturnValue;taint",
+ ";URL;true;init(filePath:directoryHint:relativeTo:);;;Argument[2].OptionalSome;ReturnValue;taint",
+ ";URL;true;init(for:in:appropriateFor:create:);;;Argument[0..1];ReturnValue;taint",
+ ";URL;true;init(for:in:appropriateFor:create:);;;Argument[2].OptionalSome;ReturnValue;taint",
+ ";URL;true;init(string:encodingInvalidCharacters:);;;Argument[0];ReturnValue.OptionalSome;taint",
";URL;true;resourceValues(forKeys:);;;Argument[-1];ReturnValue;taint",
";URL;true;setResourceValues(_:);;;Argument[0];Argument[-1];taint",
";URL;true;setTemporaryResourceValue(_:forKey:);;;Argument[-1..0];Argument[-1];taint",
@@ -125,7 +129,8 @@ private class UrlSummaries extends SummaryModelCsv {
";URL;true;deletingLastPathComponent();;;Argument[-1];ReturnValue;taint",
";URL;true;deletingPathExtension();;;Argument[-1];ReturnValue;taint",
";URL;true;bookmarkData(options:includingResourceValuesForKeys:relativeTo:);;;Argument[-1];ReturnValue;taint",
- ";URL;true;bookmarkData(options:includingResourceValuesForKeys:relativeTo:);;;Argument[1..2];ReturnValue;taint",
+ ";URL;true;bookmarkData(options:includingResourceValuesForKeys:relativeTo:);;;Argument[1].OptionalSome.CollectionElement;ReturnValue;taint",
+ ";URL;true;bookmarkData(options:includingResourceValuesForKeys:relativeTo:);;;Argument[2].OptionalSome;ReturnValue;taint",
";URL;true;bookmarkData(withContentsOf:);;;Argument[0];ReturnValue;taint",
";URL;true;resourceValues(forKeys:fromBookmarkData:);;;Argument[1];ReturnValue;taint",
";URL;true;promisedItemResourceValues(forKeys:);;;Argument[-1];ReturnValue;taint",
diff --git a/swift/ql/test/query-tests/Security/CWE-079/UnsafeWebViewFetch.expected b/swift/ql/test/query-tests/Security/CWE-079/UnsafeWebViewFetch.expected
index fb06adf5fb0..66356d31349 100644
--- a/swift/ql/test/query-tests/Security/CWE-079/UnsafeWebViewFetch.expected
+++ b/swift/ql/test/query-tests/Security/CWE-079/UnsafeWebViewFetch.expected
@@ -17,13 +17,19 @@ edges
| UnsafeWebViewFetch.swift:117:21:117:35 | call to getRemoteData() | UnsafeWebViewFetch.swift:139:25:139:25 | remoteString |
| UnsafeWebViewFetch.swift:117:21:117:35 | call to getRemoteData() | UnsafeWebViewFetch.swift:141:25:141:25 | remoteString |
| UnsafeWebViewFetch.swift:117:21:117:35 | call to getRemoteData() | UnsafeWebViewFetch.swift:150:24:150:37 | .utf8 |
+| UnsafeWebViewFetch.swift:131:18:131:42 | call to URL.init(string:) [some:0] | UnsafeWebViewFetch.swift:132:52:132:52 | remoteURL [some:0] |
| UnsafeWebViewFetch.swift:131:18:131:42 | call to URL.init(string:) [some:0] | UnsafeWebViewFetch.swift:138:47:138:47 | remoteURL [some:0] |
| UnsafeWebViewFetch.swift:131:18:131:42 | call to URL.init(string:) [some:0] | UnsafeWebViewFetch.swift:139:48:139:48 | remoteURL [some:0] |
| UnsafeWebViewFetch.swift:131:18:131:42 | call to URL.init(string:) [some:0] | UnsafeWebViewFetch.swift:153:85:153:85 | remoteURL [some:0] |
| UnsafeWebViewFetch.swift:131:18:131:42 | call to URL.init(string:) [some:0] | UnsafeWebViewFetch.swift:154:86:154:86 | remoteURL [some:0] |
| UnsafeWebViewFetch.swift:131:30:131:30 | remoteString | UnsafeWebViewFetch.swift:131:18:131:42 | call to URL.init(string:) [some:0] |
+| UnsafeWebViewFetch.swift:132:19:132:61 | call to URL.init(string:relativeTo:) [some:0] | UnsafeWebViewFetch.swift:140:47:140:47 | remoteURL2 [some:0] |
+| UnsafeWebViewFetch.swift:132:19:132:61 | call to URL.init(string:relativeTo:) [some:0] | UnsafeWebViewFetch.swift:141:48:141:48 | remoteURL2 [some:0] |
+| UnsafeWebViewFetch.swift:132:52:132:52 | remoteURL [some:0] | UnsafeWebViewFetch.swift:132:19:132:61 | call to URL.init(string:relativeTo:) [some:0] |
| UnsafeWebViewFetch.swift:138:47:138:47 | remoteURL [some:0] | UnsafeWebViewFetch.swift:138:47:138:56 | ...! |
| UnsafeWebViewFetch.swift:139:48:139:48 | remoteURL [some:0] | UnsafeWebViewFetch.swift:139:48:139:57 | ...! |
+| UnsafeWebViewFetch.swift:140:47:140:47 | remoteURL2 [some:0] | UnsafeWebViewFetch.swift:140:47:140:57 | ...! |
+| UnsafeWebViewFetch.swift:141:48:141:48 | remoteURL2 [some:0] | UnsafeWebViewFetch.swift:141:48:141:58 | ...! |
| UnsafeWebViewFetch.swift:150:19:150:41 | call to Data.init(_:) | UnsafeWebViewFetch.swift:152:15:152:15 | remoteData |
| UnsafeWebViewFetch.swift:150:19:150:41 | call to Data.init(_:) | UnsafeWebViewFetch.swift:154:15:154:15 | remoteData |
| UnsafeWebViewFetch.swift:150:24:150:37 | .utf8 | UnsafeWebViewFetch.swift:150:19:150:41 | call to Data.init(_:) |
@@ -38,13 +44,19 @@ edges
| UnsafeWebViewFetch.swift:164:21:164:35 | call to getRemoteData() | UnsafeWebViewFetch.swift:186:25:186:25 | remoteString |
| UnsafeWebViewFetch.swift:164:21:164:35 | call to getRemoteData() | UnsafeWebViewFetch.swift:188:25:188:25 | remoteString |
| UnsafeWebViewFetch.swift:164:21:164:35 | call to getRemoteData() | UnsafeWebViewFetch.swift:197:24:197:37 | .utf8 |
+| UnsafeWebViewFetch.swift:178:18:178:42 | call to URL.init(string:) [some:0] | UnsafeWebViewFetch.swift:179:52:179:52 | remoteURL [some:0] |
| UnsafeWebViewFetch.swift:178:18:178:42 | call to URL.init(string:) [some:0] | UnsafeWebViewFetch.swift:185:47:185:47 | remoteURL [some:0] |
| UnsafeWebViewFetch.swift:178:18:178:42 | call to URL.init(string:) [some:0] | UnsafeWebViewFetch.swift:186:48:186:48 | remoteURL [some:0] |
| UnsafeWebViewFetch.swift:178:18:178:42 | call to URL.init(string:) [some:0] | UnsafeWebViewFetch.swift:200:90:200:90 | remoteURL [some:0] |
| UnsafeWebViewFetch.swift:178:18:178:42 | call to URL.init(string:) [some:0] | UnsafeWebViewFetch.swift:201:91:201:91 | remoteURL [some:0] |
| UnsafeWebViewFetch.swift:178:30:178:30 | remoteString | UnsafeWebViewFetch.swift:178:18:178:42 | call to URL.init(string:) [some:0] |
+| UnsafeWebViewFetch.swift:179:19:179:61 | call to URL.init(string:relativeTo:) [some:0] | UnsafeWebViewFetch.swift:187:47:187:47 | remoteURL2 [some:0] |
+| UnsafeWebViewFetch.swift:179:19:179:61 | call to URL.init(string:relativeTo:) [some:0] | UnsafeWebViewFetch.swift:188:48:188:48 | remoteURL2 [some:0] |
+| UnsafeWebViewFetch.swift:179:52:179:52 | remoteURL [some:0] | UnsafeWebViewFetch.swift:179:19:179:61 | call to URL.init(string:relativeTo:) [some:0] |
| UnsafeWebViewFetch.swift:185:47:185:47 | remoteURL [some:0] | UnsafeWebViewFetch.swift:185:47:185:56 | ...! |
| UnsafeWebViewFetch.swift:186:48:186:48 | remoteURL [some:0] | UnsafeWebViewFetch.swift:186:48:186:57 | ...! |
+| UnsafeWebViewFetch.swift:187:47:187:47 | remoteURL2 [some:0] | UnsafeWebViewFetch.swift:187:47:187:57 | ...! |
+| UnsafeWebViewFetch.swift:188:48:188:48 | remoteURL2 [some:0] | UnsafeWebViewFetch.swift:188:48:188:58 | ...! |
| UnsafeWebViewFetch.swift:197:19:197:41 | call to Data.init(_:) | UnsafeWebViewFetch.swift:199:15:199:15 | remoteData |
| UnsafeWebViewFetch.swift:197:19:197:41 | call to Data.init(_:) | UnsafeWebViewFetch.swift:201:15:201:15 | remoteData |
| UnsafeWebViewFetch.swift:197:24:197:37 | .utf8 | UnsafeWebViewFetch.swift:197:19:197:41 | call to Data.init(_:) |
@@ -68,6 +80,8 @@ nodes
| UnsafeWebViewFetch.swift:127:25:127:25 | "..." | semmle.label | "..." |
| UnsafeWebViewFetch.swift:131:18:131:42 | call to URL.init(string:) [some:0] | semmle.label | call to URL.init(string:) [some:0] |
| UnsafeWebViewFetch.swift:131:30:131:30 | remoteString | semmle.label | remoteString |
+| UnsafeWebViewFetch.swift:132:19:132:61 | call to URL.init(string:relativeTo:) [some:0] | semmle.label | call to URL.init(string:relativeTo:) [some:0] |
+| UnsafeWebViewFetch.swift:132:52:132:52 | remoteURL [some:0] | semmle.label | remoteURL [some:0] |
| UnsafeWebViewFetch.swift:135:25:135:25 | remoteString | semmle.label | remoteString |
| UnsafeWebViewFetch.swift:137:25:137:25 | remoteString | semmle.label | remoteString |
| UnsafeWebViewFetch.swift:138:47:138:47 | remoteURL [some:0] | semmle.label | remoteURL [some:0] |
@@ -75,7 +89,11 @@ nodes
| UnsafeWebViewFetch.swift:139:25:139:25 | remoteString | semmle.label | remoteString |
| UnsafeWebViewFetch.swift:139:48:139:48 | remoteURL [some:0] | semmle.label | remoteURL [some:0] |
| UnsafeWebViewFetch.swift:139:48:139:57 | ...! | semmle.label | ...! |
+| UnsafeWebViewFetch.swift:140:47:140:47 | remoteURL2 [some:0] | semmle.label | remoteURL2 [some:0] |
+| UnsafeWebViewFetch.swift:140:47:140:57 | ...! | semmle.label | ...! |
| UnsafeWebViewFetch.swift:141:25:141:25 | remoteString | semmle.label | remoteString |
+| UnsafeWebViewFetch.swift:141:48:141:48 | remoteURL2 [some:0] | semmle.label | remoteURL2 [some:0] |
+| UnsafeWebViewFetch.swift:141:48:141:58 | ...! | semmle.label | ...! |
| UnsafeWebViewFetch.swift:150:19:150:41 | call to Data.init(_:) | semmle.label | call to Data.init(_:) |
| UnsafeWebViewFetch.swift:150:24:150:37 | .utf8 | semmle.label | .utf8 |
| UnsafeWebViewFetch.swift:152:15:152:15 | remoteData | semmle.label | remoteData |
@@ -91,6 +109,8 @@ nodes
| UnsafeWebViewFetch.swift:174:25:174:25 | "..." | semmle.label | "..." |
| UnsafeWebViewFetch.swift:178:18:178:42 | call to URL.init(string:) [some:0] | semmle.label | call to URL.init(string:) [some:0] |
| UnsafeWebViewFetch.swift:178:30:178:30 | remoteString | semmle.label | remoteString |
+| UnsafeWebViewFetch.swift:179:19:179:61 | call to URL.init(string:relativeTo:) [some:0] | semmle.label | call to URL.init(string:relativeTo:) [some:0] |
+| UnsafeWebViewFetch.swift:179:52:179:52 | remoteURL [some:0] | semmle.label | remoteURL [some:0] |
| UnsafeWebViewFetch.swift:182:25:182:25 | remoteString | semmle.label | remoteString |
| UnsafeWebViewFetch.swift:184:25:184:25 | remoteString | semmle.label | remoteString |
| UnsafeWebViewFetch.swift:185:47:185:47 | remoteURL [some:0] | semmle.label | remoteURL [some:0] |
@@ -98,7 +118,11 @@ nodes
| UnsafeWebViewFetch.swift:186:25:186:25 | remoteString | semmle.label | remoteString |
| UnsafeWebViewFetch.swift:186:48:186:48 | remoteURL [some:0] | semmle.label | remoteURL [some:0] |
| UnsafeWebViewFetch.swift:186:48:186:57 | ...! | semmle.label | ...! |
+| UnsafeWebViewFetch.swift:187:47:187:47 | remoteURL2 [some:0] | semmle.label | remoteURL2 [some:0] |
+| UnsafeWebViewFetch.swift:187:47:187:57 | ...! | semmle.label | ...! |
| UnsafeWebViewFetch.swift:188:25:188:25 | remoteString | semmle.label | remoteString |
+| UnsafeWebViewFetch.swift:188:48:188:48 | remoteURL2 [some:0] | semmle.label | remoteURL2 [some:0] |
+| UnsafeWebViewFetch.swift:188:48:188:58 | ...! | semmle.label | ...! |
| UnsafeWebViewFetch.swift:197:19:197:41 | call to Data.init(_:) | semmle.label | call to Data.init(_:) |
| UnsafeWebViewFetch.swift:197:24:197:37 | .utf8 | semmle.label | .utf8 |
| UnsafeWebViewFetch.swift:199:15:199:15 | remoteData | semmle.label | remoteData |
@@ -120,11 +144,13 @@ subpaths
| UnsafeWebViewFetch.swift:124:25:124:51 | ... .+(_:_:) ... | UnsafeWebViewFetch.swift:94:14:94:37 | call to String.init(contentsOf:) | UnsafeWebViewFetch.swift:124:25:124:51 | ... .+(_:_:) ... | Tainted data is used in a WebView fetch without restricting the base URL. |
| UnsafeWebViewFetch.swift:127:25:127:25 | "..." | UnsafeWebViewFetch.swift:94:14:94:37 | call to String.init(contentsOf:) | UnsafeWebViewFetch.swift:127:25:127:25 | "..." | Tainted data is used in a WebView fetch without restricting the base URL. |
| UnsafeWebViewFetch.swift:139:25:139:25 | remoteString | UnsafeWebViewFetch.swift:94:14:94:37 | call to String.init(contentsOf:) | UnsafeWebViewFetch.swift:139:25:139:25 | remoteString | Tainted data is used in a WebView fetch with a tainted base URL. |
+| UnsafeWebViewFetch.swift:141:25:141:25 | remoteString | UnsafeWebViewFetch.swift:94:14:94:37 | call to String.init(contentsOf:) | UnsafeWebViewFetch.swift:141:25:141:25 | remoteString | Tainted data is used in a WebView fetch with a tainted base URL. |
| UnsafeWebViewFetch.swift:154:15:154:15 | remoteData | UnsafeWebViewFetch.swift:94:14:94:37 | call to String.init(contentsOf:) | UnsafeWebViewFetch.swift:154:15:154:15 | remoteData | Tainted data is used in a WebView fetch with a tainted base URL. |
| UnsafeWebViewFetch.swift:167:25:167:39 | call to getRemoteData() | UnsafeWebViewFetch.swift:94:14:94:37 | call to String.init(contentsOf:) | UnsafeWebViewFetch.swift:167:25:167:39 | call to getRemoteData() | Tainted data is used in a WebView fetch without restricting the base URL. |
| UnsafeWebViewFetch.swift:168:25:168:25 | remoteString | UnsafeWebViewFetch.swift:94:14:94:37 | call to String.init(contentsOf:) | UnsafeWebViewFetch.swift:168:25:168:25 | remoteString | Tainted data is used in a WebView fetch without restricting the base URL. |
| UnsafeWebViewFetch.swift:171:25:171:51 | ... .+(_:_:) ... | UnsafeWebViewFetch.swift:94:14:94:37 | call to String.init(contentsOf:) | UnsafeWebViewFetch.swift:171:25:171:51 | ... .+(_:_:) ... | Tainted data is used in a WebView fetch without restricting the base URL. |
| UnsafeWebViewFetch.swift:174:25:174:25 | "..." | UnsafeWebViewFetch.swift:94:14:94:37 | call to String.init(contentsOf:) | UnsafeWebViewFetch.swift:174:25:174:25 | "..." | Tainted data is used in a WebView fetch without restricting the base URL. |
| UnsafeWebViewFetch.swift:186:25:186:25 | remoteString | UnsafeWebViewFetch.swift:94:14:94:37 | call to String.init(contentsOf:) | UnsafeWebViewFetch.swift:186:25:186:25 | remoteString | Tainted data is used in a WebView fetch with a tainted base URL. |
+| UnsafeWebViewFetch.swift:188:25:188:25 | remoteString | UnsafeWebViewFetch.swift:94:14:94:37 | call to String.init(contentsOf:) | UnsafeWebViewFetch.swift:188:25:188:25 | remoteString | Tainted data is used in a WebView fetch with a tainted base URL. |
| UnsafeWebViewFetch.swift:201:15:201:15 | remoteData | UnsafeWebViewFetch.swift:94:14:94:37 | call to String.init(contentsOf:) | UnsafeWebViewFetch.swift:201:15:201:15 | remoteData | Tainted data is used in a WebView fetch with a tainted base URL. |
| UnsafeWebViewFetch.swift:210:25:210:25 | htmlData | UnsafeWebViewFetch.swift:94:14:94:37 | call to String.init(contentsOf:) | UnsafeWebViewFetch.swift:210:25:210:25 | htmlData | Tainted data is used in a WebView fetch without restricting the base URL. |
From 93dd9d0aa4d6a1d23599e93fe9e3f13e2c0d797d Mon Sep 17 00:00:00 2001
From: Brandon Stewart <20469703+boveus@users.noreply.github.com>
Date: Tue, 8 Aug 2023 12:54:54 -0400
Subject: [PATCH 042/788] Update
ruby/ql/src/experimental/cwe-208/UnsafeHmacComparison.ql
Co-authored-by: Alex Ford
---
ruby/ql/src/experimental/cwe-208/UnsafeHmacComparison.ql | 6 +-----
1 file changed, 1 insertion(+), 5 deletions(-)
diff --git a/ruby/ql/src/experimental/cwe-208/UnsafeHmacComparison.ql b/ruby/ql/src/experimental/cwe-208/UnsafeHmacComparison.ql
index 253f78840fb..1893eb94ae5 100644
--- a/ruby/ql/src/experimental/cwe-208/UnsafeHmacComparison.ql
+++ b/ruby/ql/src/experimental/cwe-208/UnsafeHmacComparison.ql
@@ -54,11 +54,7 @@ class Configuration extends DataFlow::Configuration {
// Holds if a given sink is an Equality Operation (== or !=)
override predicate isSink(DataFlow::Node sink) {
- exists(EqualityOperation eqOp |
- eqOp.getLeftOperand() = sink.asExpr().getExpr()
- or
- eqOp.getRightOperand() = sink.asExpr().getExpr()
- )
+ any(EqualityOperation eqOp).getAnOperand() = sink.asExpr().getExpr()
}
}
From 26401fec7076cb6556ec9e8a21df09eb493a3b6a Mon Sep 17 00:00:00 2001
From: Brandon Stewart <20469703+boveus@users.noreply.github.com>
Date: Wed, 9 Aug 2023 18:44:42 +0000
Subject: [PATCH 043/788] address PR comments
---
.../cwe-208/UnsafeHmacComparison.ql | 87 ++++++++-----------
1 file changed, 35 insertions(+), 52 deletions(-)
diff --git a/ruby/ql/src/experimental/cwe-208/UnsafeHmacComparison.ql b/ruby/ql/src/experimental/cwe-208/UnsafeHmacComparison.ql
index 1893eb94ae5..8210eeb3c66 100644
--- a/ruby/ql/src/experimental/cwe-208/UnsafeHmacComparison.ql
+++ b/ruby/ql/src/experimental/cwe-208/UnsafeHmacComparison.ql
@@ -1,64 +1,47 @@
-private import codeql.ruby.AST
-import codeql.ruby.AST
-import codeql.ruby.DataFlow
+/**
+ * @name Unsafe HMAC Comparison
+ * @description An HMAC is being compared using the equality operator. This may be vulnerable to a cryptographic timing attack
+ * because the equality operation does not occur in constant time."
+
+ * @kind path-problem
+ * @problem.severity error
+ * @security-severity 6.0
+ * @precision high
+ * @id rb/unsafe-hmac-comparison
+ * @tags security
+ * external/cwe/cwe-208
+ */
+
+
+private import codeql.ruby.DataFlow
import codeql.ruby.ApiGraphs
-import codeql.ruby.dataflow.RemoteFlowSources
-import codeql.ruby.TaintTracking
import ruby
-// A call to OpenSSL::HMAC.hexdigest
-class OpenSslHmacHexdigest extends DataFlow::Node {
- OpenSslHmacHexdigest() {
- this = API::getTopLevelMember("OpenSSL").getMember("HMAC").getAMethodCall("hexdigest")
+private class OpenSslHmacSource extends DataFlow::Node {
+ OpenSslHmacSource() {
+ exists(API::Node hmacNode | hmacNode = API::getTopLevelMember("OpenSSL").getMember("HMAC") |
+ this = hmacNode.getAMethodCall(["hexdigest", "to_s", "digest", "base64digest"])
+ or
+ this = hmacNode.getAnInstantiation()
+ )
}
}
-// A call to OpenSSL::HMAC.to_s (which is an alias for OpenSSL::HMAC.hexdigest)
-class OpenSslHmactos extends DataFlow::Node {
- OpenSslHmactos() {
- this = API::getTopLevelMember("OpenSSL").getMember("HMAC").getAMethodCall("to_s")
- }
-}
-
-// A call to OpenSSL::HMAC.digest
-class OpenSslHmacdigest extends DataFlow::Node {
- OpenSslHmacdigest() {
- this = API::getTopLevelMember("OpenSSL").getMember("HMAC").getAMethodCall("digest")
- }
-}
-
-// A call to OpenSSL::HMAC.new
-class OpenSslnewHmac extends DataFlow::Node {
- OpenSslnewHmac() {
- this = API::getTopLevelMember("OpenSSL").getMember("HMAC").getAnInstantiation()
- }
-}
-
-// A call to OpenSSL::HMAC.base64digest
-class OpenSslHmacbase64digest extends DataFlow::Node {
- OpenSslHmacbase64digest() {
- this = API::getTopLevelMember("OpenSSL").getMember("HMAC").getAMethodCall("base64digest")
- }
-}
-
-class Configuration extends DataFlow::Configuration {
- Configuration() { this = "UnsafeHmacComparison" }
-
- override predicate isSource(DataFlow::Node source) {
- source instanceof OpenSslHmacHexdigest or
- source instanceof OpenSslnewHmac or
- source instanceof OpenSslHmacbase64digest or
- source instanceof OpenSslHmacdigest or
- source instanceof OpenSslHmactos
- }
+private module UnsafeHmacComparison {
+ private module Config implements DataFlow::ConfigSig {
+ predicate isSource(DataFlow::Node source) {
+ source instanceof OpenSslHmacSource
+ }
// Holds if a given sink is an Equality Operation (== or !=)
- override predicate isSink(DataFlow::Node sink) {
+ predicate isSink(DataFlow::Node sink) {
any(EqualityOperation eqOp).getAnOperand() = sink.asExpr().getExpr()
}
+ }
+
+ import DataFlow::Global
}
-from DataFlow::Node source, DataFlow::Node sink, Configuration config
-where config.hasFlow(source, sink)
-select sink,
- "An HMAC is being compared using the equality operator. This may be vulnerable to a cryptographic timing attack because the equality operation does not occur in constant time."
+from UnsafeHmacComparison::PathNode source, UnsafeHmacComparison::PathNode sink
+where UnsafeHmacComparison::flowPath(source, sink)
+select sink.getNode(), source, sink, "This comparison is potentially vulnerable to a timing attack."
\ No newline at end of file
From 07d5beca343727db38486fb930d9d018d33f0693 Mon Sep 17 00:00:00 2001
From: Brandon Stewart <20469703+boveus@users.noreply.github.com>
Date: Wed, 9 Aug 2023 18:51:55 +0000
Subject: [PATCH 044/788] run format document
---
.../cwe-208/UnsafeHmacComparison.ql | 17 +++++++----------
1 file changed, 7 insertions(+), 10 deletions(-)
diff --git a/ruby/ql/src/experimental/cwe-208/UnsafeHmacComparison.ql b/ruby/ql/src/experimental/cwe-208/UnsafeHmacComparison.ql
index 8210eeb3c66..48f379ddcdc 100644
--- a/ruby/ql/src/experimental/cwe-208/UnsafeHmacComparison.ql
+++ b/ruby/ql/src/experimental/cwe-208/UnsafeHmacComparison.ql
@@ -2,7 +2,6 @@
* @name Unsafe HMAC Comparison
* @description An HMAC is being compared using the equality operator. This may be vulnerable to a cryptographic timing attack
* because the equality operation does not occur in constant time."
-
* @kind path-problem
* @problem.severity error
* @security-severity 6.0
@@ -12,7 +11,7 @@
* external/cwe/cwe-208
*/
-
+private import codeql.ruby.AST
private import codeql.ruby.DataFlow
import codeql.ruby.ApiGraphs
import ruby
@@ -29,14 +28,12 @@ private class OpenSslHmacSource extends DataFlow::Node {
private module UnsafeHmacComparison {
private module Config implements DataFlow::ConfigSig {
- predicate isSource(DataFlow::Node source) {
- source instanceof OpenSslHmacSource
- }
+ predicate isSource(DataFlow::Node source) { source instanceof OpenSslHmacSource }
- // Holds if a given sink is an Equality Operation (== or !=)
- predicate isSink(DataFlow::Node sink) {
- any(EqualityOperation eqOp).getAnOperand() = sink.asExpr().getExpr()
- }
+ // Holds if a given sink is an Equality Operation (== or !=)
+ predicate isSink(DataFlow::Node sink) {
+ any(EqualityOperation eqOp).getAnOperand() = sink.asExpr().getExpr()
+ }
}
import DataFlow::Global
@@ -44,4 +41,4 @@ private module UnsafeHmacComparison {
from UnsafeHmacComparison::PathNode source, UnsafeHmacComparison::PathNode sink
where UnsafeHmacComparison::flowPath(source, sink)
-select sink.getNode(), source, sink, "This comparison is potentially vulnerable to a timing attack."
\ No newline at end of file
+select sink.getNode(), source, sink, "This comparison is potentially vulnerable to a timing attack."
From cca4c35cf8326c84fba56ea74a46f578af7e36e9 Mon Sep 17 00:00:00 2001
From: Brandon Stewart <20469703+boveus@users.noreply.github.com>
Date: Wed, 9 Aug 2023 19:23:21 +0000
Subject: [PATCH 045/788] add pathgraph
---
ruby/ql/src/experimental/cwe-208/UnsafeHmacComparison.ql | 1 +
1 file changed, 1 insertion(+)
diff --git a/ruby/ql/src/experimental/cwe-208/UnsafeHmacComparison.ql b/ruby/ql/src/experimental/cwe-208/UnsafeHmacComparison.ql
index 48f379ddcdc..7dace03c671 100644
--- a/ruby/ql/src/experimental/cwe-208/UnsafeHmacComparison.ql
+++ b/ruby/ql/src/experimental/cwe-208/UnsafeHmacComparison.ql
@@ -13,6 +13,7 @@
private import codeql.ruby.AST
private import codeql.ruby.DataFlow
+import DataFlow::PathGraph
import codeql.ruby.ApiGraphs
import ruby
From 74567041a74b3ff0331349a98b5472fbbd7be36c Mon Sep 17 00:00:00 2001
From: Brandon Stewart <20469703+boveus@users.noreply.github.com>
Date: Wed, 9 Aug 2023 19:51:07 +0000
Subject: [PATCH 046/788] remove pathgraph
---
ruby/ql/src/experimental/cwe-208/UnsafeHmacComparison.ql | 1 -
1 file changed, 1 deletion(-)
diff --git a/ruby/ql/src/experimental/cwe-208/UnsafeHmacComparison.ql b/ruby/ql/src/experimental/cwe-208/UnsafeHmacComparison.ql
index 7dace03c671..48f379ddcdc 100644
--- a/ruby/ql/src/experimental/cwe-208/UnsafeHmacComparison.ql
+++ b/ruby/ql/src/experimental/cwe-208/UnsafeHmacComparison.ql
@@ -13,7 +13,6 @@
private import codeql.ruby.AST
private import codeql.ruby.DataFlow
-import DataFlow::PathGraph
import codeql.ruby.ApiGraphs
import ruby
From e86ccf8498e7ff40e610da1dfe33c33e4676a985 Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Wed, 9 Aug 2023 17:06:15 +0100
Subject: [PATCH 047/788] Swift: Test flow through various conversions.
---
.../dataflow/taint/core/LocalTaint.expected | 79 ++++++++++++++
.../dataflow/taint/core/Taint.expected | 37 +++++++
.../dataflow/taint/core/conversions.swift | 101 ++++++++++++++++++
3 files changed, 217 insertions(+)
create mode 100644 swift/ql/test/library-tests/dataflow/taint/core/conversions.swift
diff --git a/swift/ql/test/library-tests/dataflow/taint/core/LocalTaint.expected b/swift/ql/test/library-tests/dataflow/taint/core/LocalTaint.expected
index b7408d1f57e..65fe7171c3f 100644
--- a/swift/ql/test/library-tests/dataflow/taint/core/LocalTaint.expected
+++ b/swift/ql/test/library-tests/dataflow/taint/core/LocalTaint.expected
@@ -1,3 +1,82 @@
+| conversions.swift:9:7:9:7 | SSA def(self) | conversions.swift:9:7:9:7 | self[return] |
+| conversions.swift:9:7:9:7 | SSA def(self) | conversions.swift:9:7:9:7 | self[return] |
+| conversions.swift:9:7:9:7 | self | conversions.swift:9:7:9:7 | SSA def(self) |
+| conversions.swift:9:7:9:7 | self | conversions.swift:9:7:9:7 | SSA def(self) |
+| conversions.swift:12:7:12:7 | SSA def(self) | conversions.swift:12:7:12:7 | self[return] |
+| conversions.swift:12:7:12:7 | self | conversions.swift:12:7:12:7 | SSA def(self) |
+| conversions.swift:12:36:12:36 | SSA def(self) | conversions.swift:12:36:12:36 | self[return] |
+| conversions.swift:12:36:12:36 | self | conversions.swift:12:36:12:36 | SSA def(self) |
+| conversions.swift:15:7:15:7 | SSA def(self) | conversions.swift:15:7:15:7 | self[return] |
+| conversions.swift:15:7:15:7 | self | conversions.swift:15:7:15:7 | SSA def(self) |
+| conversions.swift:16:11:16:11 | SSA def(self) | conversions.swift:16:11:16:42 | self[return] |
+| conversions.swift:16:11:16:11 | self | conversions.swift:16:11:16:11 | SSA def(self) |
+| conversions.swift:18:28:18:28 | SSA def(self) | conversions.swift:18:28:18:44 | self[return] |
+| conversions.swift:18:28:18:28 | self | conversions.swift:18:28:18:28 | SSA def(self) |
+| conversions.swift:19:33:19:33 | SSA def(self) | conversions.swift:19:33:19:49 | self[return] |
+| conversions.swift:19:33:19:33 | self | conversions.swift:19:33:19:33 | SSA def(self) |
+| conversions.swift:20:22:20:22 | SSA def(self) | conversions.swift:20:22:20:38 | self[return] |
+| conversions.swift:20:22:20:22 | self | conversions.swift:20:22:20:22 | SSA def(self) |
+| conversions.swift:28:19:28:29 | call to sourceInt() | conversions.swift:28:12:28:30 | call to String.init(_:) |
+| conversions.swift:29:12:29:30 | call to String.init(_:) | conversions.swift:29:12:29:32 | .utf8 |
+| conversions.swift:29:19:29:29 | call to sourceInt() | conversions.swift:29:12:29:30 | call to String.init(_:) |
+| conversions.swift:30:20:30:33 | call to sourceString() | conversions.swift:30:20:30:35 | .utf8 |
+| conversions.swift:32:9:32:9 | SSA def(v) | conversions.swift:33:13:33:13 | v |
+| conversions.swift:32:9:32:9 | v | conversions.swift:32:9:32:9 | SSA def(v) |
+| conversions.swift:32:13:32:23 | call to sourceInt() | conversions.swift:32:5:32:9 | let ...? |
+| conversions.swift:36:6:36:6 | SSA def(v2) | conversions.swift:37:12:37:12 | v2 |
+| conversions.swift:36:6:36:6 | v2 | conversions.swift:36:6:36:6 | SSA def(v2) |
+| conversions.swift:36:6:36:10 | ... as ... | conversions.swift:36:6:36:6 | v2 |
+| conversions.swift:36:18:36:41 | call to numericCast(_:) | conversions.swift:36:6:36:10 | ... as ... |
+| conversions.swift:39:6:39:6 | SSA def(v4) | conversions.swift:40:12:40:12 | v4 |
+| conversions.swift:39:6:39:6 | v4 | conversions.swift:39:6:39:6 | SSA def(v4) |
+| conversions.swift:39:6:39:10 | ... as ... | conversions.swift:39:6:39:6 | v4 |
+| conversions.swift:39:17:39:57 | call to unsafeBitCast(_:to:) | conversions.swift:39:6:39:10 | ... as ... |
+| conversions.swift:42:6:42:6 | SSA def(v5) | conversions.swift:43:12:43:12 | v5 |
+| conversions.swift:42:6:42:6 | v5 | conversions.swift:42:6:42:6 | SSA def(v5) |
+| conversions.swift:42:11:42:47 | call to Self.init(truncatingIfNeeded:) | conversions.swift:42:6:42:6 | v5 |
+| conversions.swift:45:6:45:6 | SSA def(v6) | conversions.swift:46:12:46:12 | v6 |
+| conversions.swift:45:6:45:6 | v6 | conversions.swift:45:6:45:6 | SSA def(v6) |
+| conversions.swift:45:11:45:39 | call to UInt.init(bitPattern:) | conversions.swift:45:6:45:6 | v6 |
+| conversions.swift:48:12:48:36 | call to Self.init(exactly:) | conversions.swift:48:12:48:37 | ...! |
+| conversions.swift:51:12:51:41 | call to Self.init(_:radix:) | conversions.swift:51:12:51:42 | ...! |
+| conversions.swift:63:19:63:31 | call to sourceFloat() | conversions.swift:63:12:63:32 | call to String.init(_:) |
+| conversions.swift:64:12:64:32 | call to String.init(_:) | conversions.swift:64:12:64:34 | .utf8 |
+| conversions.swift:64:19:64:31 | call to sourceFloat() | conversions.swift:64:12:64:32 | call to String.init(_:) |
+| conversions.swift:78:19:78:32 | call to sourceString() | conversions.swift:78:12:78:33 | call to String.init(_:) |
+| conversions.swift:80:6:80:6 | SSA def(ms1) | conversions.swift:81:12:81:12 | ms1 |
+| conversions.swift:80:6:80:6 | ms1 | conversions.swift:80:6:80:6 | SSA def(ms1) |
+| conversions.swift:80:12:80:26 | call to MyString.init(_:) | conversions.swift:80:12:80:27 | ...! |
+| conversions.swift:80:12:80:27 | ...! | conversions.swift:80:6:80:6 | ms1 |
+| conversions.swift:81:12:81:12 | [post] ms1 | conversions.swift:82:12:82:12 | ms1 |
+| conversions.swift:81:12:81:12 | ms1 | conversions.swift:82:12:82:12 | ms1 |
+| conversions.swift:82:12:82:12 | [post] ms1 | conversions.swift:83:12:83:12 | ms1 |
+| conversions.swift:82:12:82:12 | ms1 | conversions.swift:83:12:83:12 | ms1 |
+| conversions.swift:83:12:83:12 | [post] ms1 | conversions.swift:84:12:84:12 | ms1 |
+| conversions.swift:83:12:83:12 | ms1 | conversions.swift:84:12:84:12 | ms1 |
+| conversions.swift:86:6:86:6 | SSA def(ms2) | conversions.swift:87:12:87:12 | ms2 |
+| conversions.swift:86:6:86:6 | ms2 | conversions.swift:86:6:86:6 | SSA def(ms2) |
+| conversions.swift:86:12:86:35 | call to MyString.init(_:) | conversions.swift:86:12:86:36 | ...! |
+| conversions.swift:86:12:86:36 | ...! | conversions.swift:86:6:86:6 | ms2 |
+| conversions.swift:87:12:87:12 | [post] ms2 | conversions.swift:88:12:88:12 | ms2 |
+| conversions.swift:87:12:87:12 | ms2 | conversions.swift:88:12:88:12 | ms2 |
+| conversions.swift:88:12:88:12 | [post] ms2 | conversions.swift:89:12:89:12 | ms2 |
+| conversions.swift:88:12:88:12 | ms2 | conversions.swift:89:12:89:12 | ms2 |
+| conversions.swift:89:12:89:12 | [post] ms2 | conversions.swift:90:12:90:12 | ms2 |
+| conversions.swift:89:12:89:12 | ms2 | conversions.swift:90:12:90:12 | ms2 |
+| conversions.swift:94:6:94:6 | SSA def(parent) | conversions.swift:95:12:95:12 | parent |
+| conversions.swift:94:6:94:6 | parent | conversions.swift:94:6:94:6 | SSA def(parent) |
+| conversions.swift:94:6:94:15 | ... as ... | conversions.swift:94:6:94:6 | parent |
+| conversions.swift:94:31:94:44 | call to sourceString() | conversions.swift:94:6:94:15 | ... as ... |
+| conversions.swift:95:12:95:12 | [post] parent | conversions.swift:96:12:96:12 | parent |
+| conversions.swift:95:12:95:12 | parent | conversions.swift:96:12:96:12 | parent |
+| conversions.swift:96:12:96:12 | [post] parent | conversions.swift:98:40:98:40 | parent |
+| conversions.swift:96:12:96:12 | parent | conversions.swift:98:40:98:40 | parent |
+| conversions.swift:98:6:98:6 | SSA def(v3) | conversions.swift:99:12:99:12 | v3 |
+| conversions.swift:98:6:98:6 | v3 | conversions.swift:98:6:98:6 | SSA def(v3) |
+| conversions.swift:98:6:98:10 | ... as ... | conversions.swift:98:6:98:6 | v3 |
+| conversions.swift:98:25:98:69 | call to unsafeDowncast(_:to:) | conversions.swift:98:6:98:10 | ... as ... |
+| conversions.swift:99:12:99:12 | [post] v3 | conversions.swift:100:12:100:12 | v3 |
+| conversions.swift:99:12:99:12 | v3 | conversions.swift:100:12:100:12 | v3 |
| simple.swift:12:13:12:13 | 1 | simple.swift:12:13:12:24 | ... .+(_:_:) ... |
| simple.swift:12:17:12:24 | call to source() | simple.swift:12:13:12:24 | ... .+(_:_:) ... |
| simple.swift:13:13:13:20 | call to source() | simple.swift:13:13:13:24 | ... .+(_:_:) ... |
diff --git a/swift/ql/test/library-tests/dataflow/taint/core/Taint.expected b/swift/ql/test/library-tests/dataflow/taint/core/Taint.expected
index 3438ed3afeb..6923c1e8ec1 100644
--- a/swift/ql/test/library-tests/dataflow/taint/core/Taint.expected
+++ b/swift/ql/test/library-tests/dataflow/taint/core/Taint.expected
@@ -1,4 +1,13 @@
edges
+| conversions.swift:28:19:28:29 | call to sourceInt() | conversions.swift:28:12:28:30 | call to String.init(_:) |
+| conversions.swift:29:12:29:30 | call to String.init(_:) | conversions.swift:29:12:29:32 | .utf8 |
+| conversions.swift:29:19:29:29 | call to sourceInt() | conversions.swift:29:12:29:30 | call to String.init(_:) |
+| conversions.swift:63:19:63:31 | call to sourceFloat() | conversions.swift:63:12:63:32 | call to String.init(_:) |
+| conversions.swift:64:12:64:32 | call to String.init(_:) | conversions.swift:64:12:64:34 | .utf8 |
+| conversions.swift:64:19:64:31 | call to sourceFloat() | conversions.swift:64:12:64:32 | call to String.init(_:) |
+| conversions.swift:78:19:78:32 | call to sourceString() | conversions.swift:78:12:78:33 | call to String.init(_:) |
+| conversions.swift:94:31:94:44 | call to sourceString() | conversions.swift:95:12:95:12 | parent |
+| conversions.swift:94:31:94:44 | call to sourceString() | conversions.swift:96:12:96:12 | parent |
| file://:0:0:0:0 | self [first] | file://:0:0:0:0 | .first |
| file://:0:0:0:0 | self [second] | file://:0:0:0:0 | .second |
| file://:0:0:0:0 | value | file://:0:0:0:0 | [post] self [first] |
@@ -77,6 +86,24 @@ edges
| try.swift:18:18:18:25 | call to source() | try.swift:18:18:18:25 | call to source() [some:0] |
| try.swift:18:18:18:25 | call to source() [some:0] | try.swift:18:13:18:25 | try? ... [some:0] |
nodes
+| conversions.swift:24:12:24:22 | call to sourceInt() | semmle.label | call to sourceInt() |
+| conversions.swift:28:12:28:30 | call to String.init(_:) | semmle.label | call to String.init(_:) |
+| conversions.swift:28:19:28:29 | call to sourceInt() | semmle.label | call to sourceInt() |
+| conversions.swift:29:12:29:30 | call to String.init(_:) | semmle.label | call to String.init(_:) |
+| conversions.swift:29:12:29:32 | .utf8 | semmle.label | .utf8 |
+| conversions.swift:29:19:29:29 | call to sourceInt() | semmle.label | call to sourceInt() |
+| conversions.swift:60:12:60:24 | call to sourceFloat() | semmle.label | call to sourceFloat() |
+| conversions.swift:63:12:63:32 | call to String.init(_:) | semmle.label | call to String.init(_:) |
+| conversions.swift:63:19:63:31 | call to sourceFloat() | semmle.label | call to sourceFloat() |
+| conversions.swift:64:12:64:32 | call to String.init(_:) | semmle.label | call to String.init(_:) |
+| conversions.swift:64:12:64:34 | .utf8 | semmle.label | .utf8 |
+| conversions.swift:64:19:64:31 | call to sourceFloat() | semmle.label | call to sourceFloat() |
+| conversions.swift:77:12:77:25 | call to sourceString() | semmle.label | call to sourceString() |
+| conversions.swift:78:12:78:33 | call to String.init(_:) | semmle.label | call to String.init(_:) |
+| conversions.swift:78:19:78:32 | call to sourceString() | semmle.label | call to sourceString() |
+| conversions.swift:94:31:94:44 | call to sourceString() | semmle.label | call to sourceString() |
+| conversions.swift:95:12:95:12 | parent | semmle.label | parent |
+| conversions.swift:96:12:96:12 | parent | semmle.label | parent |
| file://:0:0:0:0 | .first | semmle.label | .first |
| file://:0:0:0:0 | .second | semmle.label | .second |
| file://:0:0:0:0 | [post] self [first] | semmle.label | [post] self [first] |
@@ -200,6 +227,16 @@ subpaths
| stringinterpolation.swift:28:14:28:21 | call to source() | stringinterpolation.swift:7:6:7:6 | value | file://:0:0:0:0 | [post] self [second] | stringinterpolation.swift:28:2:28:2 | [post] p2 [second] |
| stringinterpolation.swift:31:21:31:21 | p2 [second] | stringinterpolation.swift:7:6:7:6 | self [second] | file://:0:0:0:0 | .second | stringinterpolation.swift:31:21:31:24 | .second |
#select
+| conversions.swift:24:12:24:22 | call to sourceInt() | conversions.swift:24:12:24:22 | call to sourceInt() | conversions.swift:24:12:24:22 | call to sourceInt() | result |
+| conversions.swift:28:12:28:30 | call to String.init(_:) | conversions.swift:28:19:28:29 | call to sourceInt() | conversions.swift:28:12:28:30 | call to String.init(_:) | result |
+| conversions.swift:29:12:29:32 | .utf8 | conversions.swift:29:19:29:29 | call to sourceInt() | conversions.swift:29:12:29:32 | .utf8 | result |
+| conversions.swift:60:12:60:24 | call to sourceFloat() | conversions.swift:60:12:60:24 | call to sourceFloat() | conversions.swift:60:12:60:24 | call to sourceFloat() | result |
+| conversions.swift:63:12:63:32 | call to String.init(_:) | conversions.swift:63:19:63:31 | call to sourceFloat() | conversions.swift:63:12:63:32 | call to String.init(_:) | result |
+| conversions.swift:64:12:64:34 | .utf8 | conversions.swift:64:19:64:31 | call to sourceFloat() | conversions.swift:64:12:64:34 | .utf8 | result |
+| conversions.swift:77:12:77:25 | call to sourceString() | conversions.swift:77:12:77:25 | call to sourceString() | conversions.swift:77:12:77:25 | call to sourceString() | result |
+| conversions.swift:78:12:78:33 | call to String.init(_:) | conversions.swift:78:19:78:32 | call to sourceString() | conversions.swift:78:12:78:33 | call to String.init(_:) | result |
+| conversions.swift:95:12:95:12 | parent | conversions.swift:94:31:94:44 | call to sourceString() | conversions.swift:95:12:95:12 | parent | result |
+| conversions.swift:96:12:96:12 | parent | conversions.swift:94:31:94:44 | call to sourceString() | conversions.swift:96:12:96:12 | parent | result |
| simple.swift:12:13:12:24 | ... .+(_:_:) ... | simple.swift:12:17:12:24 | call to source() | simple.swift:12:13:12:24 | ... .+(_:_:) ... | result |
| simple.swift:13:13:13:24 | ... .+(_:_:) ... | simple.swift:13:13:13:20 | call to source() | simple.swift:13:13:13:24 | ... .+(_:_:) ... | result |
| simple.swift:14:13:14:24 | ... .-(_:_:) ... | simple.swift:14:17:14:24 | call to source() | simple.swift:14:13:14:24 | ... .-(_:_:) ... | result |
diff --git a/swift/ql/test/library-tests/dataflow/taint/core/conversions.swift b/swift/ql/test/library-tests/dataflow/taint/core/conversions.swift
new file mode 100644
index 00000000000..4789486ad45
--- /dev/null
+++ b/swift/ql/test/library-tests/dataflow/taint/core/conversions.swift
@@ -0,0 +1,101 @@
+
+func sourceInt() -> Int { 0 }
+func sourceFloat() -> Float { 0.0 }
+func sourceString() -> String { "" }
+func sink(arg: Any) { }
+
+// ---
+
+class MyParentClass {
+}
+
+class MyChildClass : MyParentClass {
+}
+
+class MyString : LosslessStringConvertible, CustomStringConvertible, CustomDebugStringConvertible {
+ required init?(_ description: String) { }
+
+ var description: String { get { return "" } }
+ var debugDescription: String { get { return "" } }
+ var clean: String { get { return "" } }
+}
+
+func testConversions() {
+ sink(arg: sourceInt()) // $ tainted=24
+ sink(arg: Int(sourceInt())) // $ MISSING: tainted=
+ sink(arg: UInt8(sourceInt())) // $ MISSING: tainted=
+ sink(arg: Float(sourceInt())) // $ MISSING: tainted=
+ sink(arg: String(sourceInt())) // $ tainted=28
+ sink(arg: String(sourceInt()).utf8) // $ tainted=29
+ sink(arg: [UInt8](sourceString().utf8)) // $ MISSING: tainted=
+
+ if let v = sourceInt() as? UInt {
+ sink(arg: v) // $ MISSING: tainted=
+ }
+
+ let v2: UInt8 = numericCast(sourceInt())
+ sink(arg: v2) // $ MISSING: tainted=
+
+ let v4: UInt = unsafeBitCast(sourceInt(), to: UInt.self)
+ sink(arg: v4) // $ MISSING: tainted=
+
+ let v5 = UInt(truncatingIfNeeded: sourceInt())
+ sink(arg: v5) // $ MISSING: tainted=
+
+ let v6 = UInt(bitPattern: sourceInt())
+ sink(arg: v6) // $ MISSING: tainted=
+
+ sink(arg: Int(exactly: sourceInt())!) // $ MISSING: tainted=
+ sink(arg: Int(clamping: sourceInt())) // $ MISSING: tainted=
+ sink(arg: Int(truncatingIfNeeded: sourceInt())) // $ MISSING: tainted=
+ sink(arg: Int(sourceString(), radix: 10)!) // $ MISSING: tainted=
+
+ sink(arg: Int(littleEndian: sourceInt())) // $ MISSING: tainted=
+ sink(arg: Int(bigEndian: sourceInt())) // $ MISSING: tainted=
+ sink(arg: sourceInt().littleEndian) // $ MISSING: tainted=
+ sink(arg: sourceInt().bigEndian) // $ MISSING: tainted=
+
+ // ---
+
+ sink(arg: sourceFloat()) // $ tainted=60
+ sink(arg: Float(sourceFloat())) // $ MISSING: tainted=
+ sink(arg: UInt8(sourceFloat())) // $ MISSING: tainted=
+ sink(arg: String(sourceFloat())) // $ tainted=63
+ sink(arg: String(sourceFloat()).utf8) // $ tainted=64
+
+ sink(arg: Float(sourceFloat())) // MISSING: tainted=
+ sink(arg: Float(sign: .plus, exponent: sourceInt(), significand: 0.0)) // MISSING: tainted=
+ sink(arg: Float(sign: .plus, exponent: 0, significand: sourceFloat())) // MISSING: tainted=
+ sink(arg: Float(signOf: sourceFloat(), magnitudeOf: 0.0)) // (good)
+ sink(arg: Float(signOf: 0.0, magnitudeOf: sourceFloat())) // MISSING: tainted=
+
+ sink(arg: sourceFloat().exponent) // $ MISSING: tainted=
+ sink(arg: sourceFloat().significand) // $ MISSING: tainted=
+
+ // ---
+
+ sink(arg: sourceString()) // $ tainted=77
+ sink(arg: String(sourceString())) // $ tainted=78
+
+ let ms1 = MyString("abc")!
+ sink(arg: ms1)
+ sink(arg: ms1.description)
+ sink(arg: ms1.debugDescription)
+ sink(arg: ms1.clean)
+
+ let ms2 = MyString(sourceString())!
+ sink(arg: ms2) // $ MISSING: tainted=
+ sink(arg: ms2.description) // $ MISSING: tainted=
+ sink(arg: ms2.debugDescription) // $ MISSING: tainted=
+ sink(arg: ms2.clean)
+
+ // ---
+
+ let parent : MyParentClass = sourceString() as! MyChildClass
+ sink(arg: parent) // $ tainted=94
+ sink(arg: parent as! MyChildClass) // $ tainted=94
+
+ let v3: MyChildClass = unsafeDowncast(parent, to: MyChildClass.self)
+ sink(arg: v3) // $ MISSING: tainted=
+ sink(arg: v3 as! MyParentClass) // $ MISSING: tainted=
+}
From aa2e79b6da4c1d53efe12c2970703104d9cd99b1 Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Wed, 9 Aug 2023 20:57:43 +0100
Subject: [PATCH 048/788] Swift: Model numeric conversions.
---
.../frameworks/StandardLibrary/Numeric.qll | 51 ++++++++
.../StandardLibrary/StandardLibrary.qll | 1 +
.../dataflow/taint/core/LocalTaint.expected | 26 ++++
.../dataflow/taint/core/Taint.expected | 114 ++++++++++++++++++
.../dataflow/taint/core/conversions.swift | 50 ++++----
5 files changed, 217 insertions(+), 25 deletions(-)
create mode 100644 swift/ql/lib/codeql/swift/frameworks/StandardLibrary/Numeric.qll
diff --git a/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/Numeric.qll b/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/Numeric.qll
new file mode 100644
index 00000000000..a985bb7f0ed
--- /dev/null
+++ b/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/Numeric.qll
@@ -0,0 +1,51 @@
+/**
+ * Provides models for `Numeric` and related Swift classes (such as `Int` and `Float`).
+ */
+
+import swift
+private import codeql.swift.dataflow.DataFlow
+private import codeql.swift.dataflow.ExternalFlow
+private import codeql.swift.dataflow.FlowSteps
+
+/**
+ * A model for `Numeric` and related class members and functions that permit taint flow.
+ */
+private class NumericSummaries extends SummaryModelCsv {
+ override predicate row(string row) {
+ row =
+ [
+ ";;false;numericCast(_:);;;Argument[0];ReturnValue;taint",
+ ";;false;unsafeDowncast(_:to:);;;Argument[0];ReturnValue;taint",
+ ";;false;unsafeBitCast(_:to:);;;Argument[0];ReturnValue;taint",
+ ";Numeric;true;init(exactly:);;;Argument[0];ReturnValue.OptionalSome;value",
+ ";Numeric;true;init(bitPattern:);;;Argument[0];ReturnValue;taint",
+ ";BinaryInteger;true;init(_:);;;Argument[0];ReturnValue;taint",
+ ";BinaryInteger;true;init(clamping:);;;Argument[0];ReturnValue;taint",
+ ";BinaryInteger;true;init(truncatingIfNeeded:);;;Argument[0];ReturnValue;taint",
+ ";BinaryInteger;true;init(_:format:lenient:);;;Argument[0];ReturnValue;taint",
+ ";BinaryInteger;true;init(_:strategy:);;;Argument[0];ReturnValue;taint",
+ ";BinaryInteger;true;formatted();;;Argument[-1];ReturnValue;taint",
+ ";BinaryInteger;true;formatted(_:);;;Argument[-1];ReturnValue;taint",
+ ";FixedWidthInteger;true;init(_:radix:);;;Argument[0];ReturnValue;taint",
+ ";FixedWidthInteger;true;init(littleEndian:);;;Argument[0];ReturnValue;taint",
+ ";FixedWidthInteger;true;init(bigEndian:);;;Argument[0];ReturnValue;taint",
+ ";FloatingPoint;true;init(_:);;;Argument[0];ReturnValue;taint",
+ ";FloatingPoint;true;init(sign:exponent:significand:);;;Argument[1..2];ReturnValue;taint",
+ ";FloatingPoint;true;init(signOf:magnitudeOf:);;;Argument[1];ReturnValue;taint",
+ ]
+ }
+}
+
+/**
+ * A content implying that, if a `Numeric` is tainted, then some of its fields are
+ * tainted.
+ */
+private class NumericFieldsInheritTaint extends TaintInheritingContent,
+ DataFlow::Content::FieldContent
+{
+ NumericFieldsInheritTaint() {
+ this.getField().hasQualifiedName("FixedWidthInteger", ["littleEndian", "bigEndian"])
+ or
+ this.getField().hasQualifiedName(["Double", "Float", "Float80", "FloatingPoint"], ["exponent", "significand"])
+ }
+}
diff --git a/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/StandardLibrary.qll b/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/StandardLibrary.qll
index 93d60dba092..775c6afcea0 100644
--- a/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/StandardLibrary.qll
+++ b/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/StandardLibrary.qll
@@ -14,6 +14,7 @@ private import NsData
private import NsObject
private import NsString
private import NsUrl
+private import Numeric
private import Sequence
private import Set
private import String
diff --git a/swift/ql/test/library-tests/dataflow/taint/core/LocalTaint.expected b/swift/ql/test/library-tests/dataflow/taint/core/LocalTaint.expected
index 65fe7171c3f..1ff797add87 100644
--- a/swift/ql/test/library-tests/dataflow/taint/core/LocalTaint.expected
+++ b/swift/ql/test/library-tests/dataflow/taint/core/LocalTaint.expected
@@ -16,6 +16,9 @@
| conversions.swift:19:33:19:33 | self | conversions.swift:19:33:19:33 | SSA def(self) |
| conversions.swift:20:22:20:22 | SSA def(self) | conversions.swift:20:22:20:38 | self[return] |
| conversions.swift:20:22:20:22 | self | conversions.swift:20:22:20:22 | SSA def(self) |
+| conversions.swift:25:16:25:26 | call to sourceInt() | conversions.swift:25:12:25:27 | call to Self.init(_:) |
+| conversions.swift:26:18:26:28 | call to sourceInt() | conversions.swift:26:12:26:29 | call to Self.init(_:) |
+| conversions.swift:27:18:27:28 | call to sourceInt() | conversions.swift:27:12:27:29 | call to Float.init(_:) |
| conversions.swift:28:19:28:29 | call to sourceInt() | conversions.swift:28:12:28:30 | call to String.init(_:) |
| conversions.swift:29:12:29:30 | call to String.init(_:) | conversions.swift:29:12:29:32 | .utf8 |
| conversions.swift:29:19:29:29 | call to sourceInt() | conversions.swift:29:12:29:30 | call to String.init(_:) |
@@ -27,21 +30,43 @@
| conversions.swift:36:6:36:6 | v2 | conversions.swift:36:6:36:6 | SSA def(v2) |
| conversions.swift:36:6:36:10 | ... as ... | conversions.swift:36:6:36:6 | v2 |
| conversions.swift:36:18:36:41 | call to numericCast(_:) | conversions.swift:36:6:36:10 | ... as ... |
+| conversions.swift:36:30:36:40 | call to sourceInt() | conversions.swift:36:18:36:41 | call to numericCast(_:) |
| conversions.swift:39:6:39:6 | SSA def(v4) | conversions.swift:40:12:40:12 | v4 |
| conversions.swift:39:6:39:6 | v4 | conversions.swift:39:6:39:6 | SSA def(v4) |
| conversions.swift:39:6:39:10 | ... as ... | conversions.swift:39:6:39:6 | v4 |
| conversions.swift:39:17:39:57 | call to unsafeBitCast(_:to:) | conversions.swift:39:6:39:10 | ... as ... |
+| conversions.swift:39:31:39:41 | call to sourceInt() | conversions.swift:39:17:39:57 | call to unsafeBitCast(_:to:) |
| conversions.swift:42:6:42:6 | SSA def(v5) | conversions.swift:43:12:43:12 | v5 |
| conversions.swift:42:6:42:6 | v5 | conversions.swift:42:6:42:6 | SSA def(v5) |
| conversions.swift:42:11:42:47 | call to Self.init(truncatingIfNeeded:) | conversions.swift:42:6:42:6 | v5 |
+| conversions.swift:42:36:42:46 | call to sourceInt() | conversions.swift:42:11:42:47 | call to Self.init(truncatingIfNeeded:) |
| conversions.swift:45:6:45:6 | SSA def(v6) | conversions.swift:46:12:46:12 | v6 |
| conversions.swift:45:6:45:6 | v6 | conversions.swift:45:6:45:6 | SSA def(v6) |
| conversions.swift:45:11:45:39 | call to UInt.init(bitPattern:) | conversions.swift:45:6:45:6 | v6 |
+| conversions.swift:45:28:45:38 | call to sourceInt() | conversions.swift:45:11:45:39 | call to UInt.init(bitPattern:) |
| conversions.swift:48:12:48:36 | call to Self.init(exactly:) | conversions.swift:48:12:48:37 | ...! |
+| conversions.swift:49:26:49:36 | call to sourceInt() | conversions.swift:49:12:49:37 | call to Self.init(clamping:) |
+| conversions.swift:50:36:50:46 | call to sourceInt() | conversions.swift:50:12:50:47 | call to Self.init(truncatingIfNeeded:) |
| conversions.swift:51:12:51:41 | call to Self.init(_:radix:) | conversions.swift:51:12:51:42 | ...! |
+| conversions.swift:51:16:51:29 | call to sourceString() | conversions.swift:51:12:51:41 | call to Self.init(_:radix:) |
+| conversions.swift:53:30:53:40 | call to sourceInt() | conversions.swift:53:12:53:41 | call to Self.init(littleEndian:) |
+| conversions.swift:54:27:54:37 | call to sourceInt() | conversions.swift:54:12:54:38 | call to Self.init(bigEndian:) |
+| conversions.swift:55:12:55:22 | call to sourceInt() | conversions.swift:55:12:55:24 | .littleEndian |
+| conversions.swift:56:12:56:22 | call to sourceInt() | conversions.swift:56:12:56:24 | .bigEndian |
+| conversions.swift:61:18:61:30 | call to sourceFloat() | conversions.swift:61:12:61:31 | call to Float.init(_:) |
+| conversions.swift:62:18:62:30 | call to sourceFloat() | conversions.swift:62:12:62:31 | call to UInt8.init(_:) |
| conversions.swift:63:19:63:31 | call to sourceFloat() | conversions.swift:63:12:63:32 | call to String.init(_:) |
| conversions.swift:64:12:64:32 | call to String.init(_:) | conversions.swift:64:12:64:34 | .utf8 |
| conversions.swift:64:19:64:31 | call to sourceFloat() | conversions.swift:64:12:64:32 | call to String.init(_:) |
+| conversions.swift:66:18:66:30 | call to sourceFloat() | conversions.swift:66:12:66:31 | call to Float.init(_:) |
+| conversions.swift:67:41:67:51 | call to sourceInt() | conversions.swift:67:12:67:70 | call to Float.init(sign:exponent:significand:) |
+| conversions.swift:67:67:67:67 | 0.0 | conversions.swift:67:12:67:70 | call to Float.init(sign:exponent:significand:) |
+| conversions.swift:68:41:68:41 | 0 | conversions.swift:68:12:68:70 | call to Float.init(sign:exponent:significand:) |
+| conversions.swift:68:57:68:69 | call to sourceFloat() | conversions.swift:68:12:68:70 | call to Float.init(sign:exponent:significand:) |
+| conversions.swift:69:54:69:54 | 0.0 | conversions.swift:69:12:69:57 | call to Float.init(signOf:magnitudeOf:) |
+| conversions.swift:70:44:70:56 | call to sourceFloat() | conversions.swift:70:12:70:57 | call to Float.init(signOf:magnitudeOf:) |
+| conversions.swift:72:12:72:24 | call to sourceFloat() | conversions.swift:72:12:72:26 | .exponent |
+| conversions.swift:73:12:73:24 | call to sourceFloat() | conversions.swift:73:12:73:26 | .significand |
| conversions.swift:78:19:78:32 | call to sourceString() | conversions.swift:78:12:78:33 | call to String.init(_:) |
| conversions.swift:80:6:80:6 | SSA def(ms1) | conversions.swift:81:12:81:12 | ms1 |
| conversions.swift:80:6:80:6 | ms1 | conversions.swift:80:6:80:6 | SSA def(ms1) |
@@ -75,6 +100,7 @@
| conversions.swift:98:6:98:6 | v3 | conversions.swift:98:6:98:6 | SSA def(v3) |
| conversions.swift:98:6:98:10 | ... as ... | conversions.swift:98:6:98:6 | v3 |
| conversions.swift:98:25:98:69 | call to unsafeDowncast(_:to:) | conversions.swift:98:6:98:10 | ... as ... |
+| conversions.swift:98:40:98:40 | parent | conversions.swift:98:25:98:69 | call to unsafeDowncast(_:to:) |
| conversions.swift:99:12:99:12 | [post] v3 | conversions.swift:100:12:100:12 | v3 |
| conversions.swift:99:12:99:12 | v3 | conversions.swift:100:12:100:12 | v3 |
| simple.swift:12:13:12:13 | 1 | simple.swift:12:13:12:24 | ... .+(_:_:) ... |
diff --git a/swift/ql/test/library-tests/dataflow/taint/core/Taint.expected b/swift/ql/test/library-tests/dataflow/taint/core/Taint.expected
index 6923c1e8ec1..48ef4ada925 100644
--- a/swift/ql/test/library-tests/dataflow/taint/core/Taint.expected
+++ b/swift/ql/test/library-tests/dataflow/taint/core/Taint.expected
@@ -1,13 +1,46 @@
edges
+| conversions.swift:25:16:25:26 | call to sourceInt() | conversions.swift:25:12:25:27 | call to Self.init(_:) |
+| conversions.swift:26:18:26:28 | call to sourceInt() | conversions.swift:26:12:26:29 | call to Self.init(_:) |
+| conversions.swift:27:18:27:28 | call to sourceInt() | conversions.swift:27:12:27:29 | call to Float.init(_:) |
| conversions.swift:28:19:28:29 | call to sourceInt() | conversions.swift:28:12:28:30 | call to String.init(_:) |
| conversions.swift:29:12:29:30 | call to String.init(_:) | conversions.swift:29:12:29:32 | .utf8 |
| conversions.swift:29:19:29:29 | call to sourceInt() | conversions.swift:29:12:29:30 | call to String.init(_:) |
+| conversions.swift:36:18:36:41 | call to numericCast(_:) | conversions.swift:37:12:37:12 | v2 |
+| conversions.swift:36:30:36:40 | call to sourceInt() | conversions.swift:36:18:36:41 | call to numericCast(_:) |
+| conversions.swift:39:17:39:57 | call to unsafeBitCast(_:to:) | conversions.swift:40:12:40:12 | v4 |
+| conversions.swift:39:31:39:41 | call to sourceInt() | conversions.swift:39:17:39:57 | call to unsafeBitCast(_:to:) |
+| conversions.swift:42:11:42:47 | call to Self.init(truncatingIfNeeded:) | conversions.swift:43:12:43:12 | v5 |
+| conversions.swift:42:36:42:46 | call to sourceInt() | conversions.swift:42:11:42:47 | call to Self.init(truncatingIfNeeded:) |
+| conversions.swift:45:11:45:39 | call to UInt.init(bitPattern:) | conversions.swift:46:12:46:12 | v6 |
+| conversions.swift:45:28:45:38 | call to sourceInt() | conversions.swift:45:11:45:39 | call to UInt.init(bitPattern:) |
+| conversions.swift:48:12:48:36 | call to Self.init(exactly:) [some:0] | conversions.swift:48:12:48:37 | ...! |
+| conversions.swift:48:25:48:35 | call to sourceInt() | conversions.swift:48:12:48:36 | call to Self.init(exactly:) [some:0] |
+| conversions.swift:49:26:49:36 | call to sourceInt() | conversions.swift:49:12:49:37 | call to Self.init(clamping:) |
+| conversions.swift:50:36:50:46 | call to sourceInt() | conversions.swift:50:12:50:47 | call to Self.init(truncatingIfNeeded:) |
+| conversions.swift:51:12:51:41 | call to Self.init(_:radix:) | conversions.swift:51:12:51:42 | ...! |
+| conversions.swift:51:16:51:29 | call to sourceString() | conversions.swift:51:12:51:41 | call to Self.init(_:radix:) |
+| conversions.swift:53:30:53:40 | call to sourceInt() | conversions.swift:53:12:53:41 | call to Self.init(littleEndian:) |
+| conversions.swift:54:27:54:37 | call to sourceInt() | conversions.swift:54:12:54:38 | call to Self.init(bigEndian:) |
+| conversions.swift:55:12:55:22 | call to sourceInt() | conversions.swift:55:12:55:24 | .littleEndian |
+| conversions.swift:56:12:56:22 | call to sourceInt() | conversions.swift:56:12:56:24 | .bigEndian |
+| conversions.swift:61:18:61:30 | call to sourceFloat() | conversions.swift:61:12:61:31 | call to Float.init(_:) |
+| conversions.swift:62:18:62:30 | call to sourceFloat() | conversions.swift:62:12:62:31 | call to UInt8.init(_:) |
| conversions.swift:63:19:63:31 | call to sourceFloat() | conversions.swift:63:12:63:32 | call to String.init(_:) |
| conversions.swift:64:12:64:32 | call to String.init(_:) | conversions.swift:64:12:64:34 | .utf8 |
| conversions.swift:64:19:64:31 | call to sourceFloat() | conversions.swift:64:12:64:32 | call to String.init(_:) |
+| conversions.swift:66:18:66:30 | call to sourceFloat() | conversions.swift:66:12:66:31 | call to Float.init(_:) |
+| conversions.swift:67:41:67:51 | call to sourceInt() | conversions.swift:67:12:67:70 | call to Float.init(sign:exponent:significand:) |
+| conversions.swift:68:57:68:69 | call to sourceFloat() | conversions.swift:68:12:68:70 | call to Float.init(sign:exponent:significand:) |
+| conversions.swift:70:44:70:56 | call to sourceFloat() | conversions.swift:70:12:70:57 | call to Float.init(signOf:magnitudeOf:) |
+| conversions.swift:72:12:72:24 | call to sourceFloat() | conversions.swift:72:12:72:26 | .exponent |
+| conversions.swift:73:12:73:24 | call to sourceFloat() | conversions.swift:73:12:73:26 | .significand |
| conversions.swift:78:19:78:32 | call to sourceString() | conversions.swift:78:12:78:33 | call to String.init(_:) |
| conversions.swift:94:31:94:44 | call to sourceString() | conversions.swift:95:12:95:12 | parent |
| conversions.swift:94:31:94:44 | call to sourceString() | conversions.swift:96:12:96:12 | parent |
+| conversions.swift:94:31:94:44 | call to sourceString() | conversions.swift:98:40:98:40 | parent |
+| conversions.swift:98:25:98:69 | call to unsafeDowncast(_:to:) | conversions.swift:99:12:99:12 | v3 |
+| conversions.swift:98:25:98:69 | call to unsafeDowncast(_:to:) | conversions.swift:100:12:100:12 | v3 |
+| conversions.swift:98:40:98:40 | parent | conversions.swift:98:25:98:69 | call to unsafeDowncast(_:to:) |
| file://:0:0:0:0 | self [first] | file://:0:0:0:0 | .first |
| file://:0:0:0:0 | self [second] | file://:0:0:0:0 | .second |
| file://:0:0:0:0 | value | file://:0:0:0:0 | [post] self [first] |
@@ -87,23 +120,79 @@ edges
| try.swift:18:18:18:25 | call to source() [some:0] | try.swift:18:13:18:25 | try? ... [some:0] |
nodes
| conversions.swift:24:12:24:22 | call to sourceInt() | semmle.label | call to sourceInt() |
+| conversions.swift:25:12:25:27 | call to Self.init(_:) | semmle.label | call to Self.init(_:) |
+| conversions.swift:25:16:25:26 | call to sourceInt() | semmle.label | call to sourceInt() |
+| conversions.swift:26:12:26:29 | call to Self.init(_:) | semmle.label | call to Self.init(_:) |
+| conversions.swift:26:18:26:28 | call to sourceInt() | semmle.label | call to sourceInt() |
+| conversions.swift:27:12:27:29 | call to Float.init(_:) | semmle.label | call to Float.init(_:) |
+| conversions.swift:27:18:27:28 | call to sourceInt() | semmle.label | call to sourceInt() |
| conversions.swift:28:12:28:30 | call to String.init(_:) | semmle.label | call to String.init(_:) |
| conversions.swift:28:19:28:29 | call to sourceInt() | semmle.label | call to sourceInt() |
| conversions.swift:29:12:29:30 | call to String.init(_:) | semmle.label | call to String.init(_:) |
| conversions.swift:29:12:29:32 | .utf8 | semmle.label | .utf8 |
| conversions.swift:29:19:29:29 | call to sourceInt() | semmle.label | call to sourceInt() |
+| conversions.swift:36:18:36:41 | call to numericCast(_:) | semmle.label | call to numericCast(_:) |
+| conversions.swift:36:30:36:40 | call to sourceInt() | semmle.label | call to sourceInt() |
+| conversions.swift:37:12:37:12 | v2 | semmle.label | v2 |
+| conversions.swift:39:17:39:57 | call to unsafeBitCast(_:to:) | semmle.label | call to unsafeBitCast(_:to:) |
+| conversions.swift:39:31:39:41 | call to sourceInt() | semmle.label | call to sourceInt() |
+| conversions.swift:40:12:40:12 | v4 | semmle.label | v4 |
+| conversions.swift:42:11:42:47 | call to Self.init(truncatingIfNeeded:) | semmle.label | call to Self.init(truncatingIfNeeded:) |
+| conversions.swift:42:36:42:46 | call to sourceInt() | semmle.label | call to sourceInt() |
+| conversions.swift:43:12:43:12 | v5 | semmle.label | v5 |
+| conversions.swift:45:11:45:39 | call to UInt.init(bitPattern:) | semmle.label | call to UInt.init(bitPattern:) |
+| conversions.swift:45:28:45:38 | call to sourceInt() | semmle.label | call to sourceInt() |
+| conversions.swift:46:12:46:12 | v6 | semmle.label | v6 |
+| conversions.swift:48:12:48:36 | call to Self.init(exactly:) [some:0] | semmle.label | call to Self.init(exactly:) [some:0] |
+| conversions.swift:48:12:48:37 | ...! | semmle.label | ...! |
+| conversions.swift:48:25:48:35 | call to sourceInt() | semmle.label | call to sourceInt() |
+| conversions.swift:49:12:49:37 | call to Self.init(clamping:) | semmle.label | call to Self.init(clamping:) |
+| conversions.swift:49:26:49:36 | call to sourceInt() | semmle.label | call to sourceInt() |
+| conversions.swift:50:12:50:47 | call to Self.init(truncatingIfNeeded:) | semmle.label | call to Self.init(truncatingIfNeeded:) |
+| conversions.swift:50:36:50:46 | call to sourceInt() | semmle.label | call to sourceInt() |
+| conversions.swift:51:12:51:41 | call to Self.init(_:radix:) | semmle.label | call to Self.init(_:radix:) |
+| conversions.swift:51:12:51:42 | ...! | semmle.label | ...! |
+| conversions.swift:51:16:51:29 | call to sourceString() | semmle.label | call to sourceString() |
+| conversions.swift:53:12:53:41 | call to Self.init(littleEndian:) | semmle.label | call to Self.init(littleEndian:) |
+| conversions.swift:53:30:53:40 | call to sourceInt() | semmle.label | call to sourceInt() |
+| conversions.swift:54:12:54:38 | call to Self.init(bigEndian:) | semmle.label | call to Self.init(bigEndian:) |
+| conversions.swift:54:27:54:37 | call to sourceInt() | semmle.label | call to sourceInt() |
+| conversions.swift:55:12:55:22 | call to sourceInt() | semmle.label | call to sourceInt() |
+| conversions.swift:55:12:55:24 | .littleEndian | semmle.label | .littleEndian |
+| conversions.swift:56:12:56:22 | call to sourceInt() | semmle.label | call to sourceInt() |
+| conversions.swift:56:12:56:24 | .bigEndian | semmle.label | .bigEndian |
| conversions.swift:60:12:60:24 | call to sourceFloat() | semmle.label | call to sourceFloat() |
+| conversions.swift:61:12:61:31 | call to Float.init(_:) | semmle.label | call to Float.init(_:) |
+| conversions.swift:61:18:61:30 | call to sourceFloat() | semmle.label | call to sourceFloat() |
+| conversions.swift:62:12:62:31 | call to UInt8.init(_:) | semmle.label | call to UInt8.init(_:) |
+| conversions.swift:62:18:62:30 | call to sourceFloat() | semmle.label | call to sourceFloat() |
| conversions.swift:63:12:63:32 | call to String.init(_:) | semmle.label | call to String.init(_:) |
| conversions.swift:63:19:63:31 | call to sourceFloat() | semmle.label | call to sourceFloat() |
| conversions.swift:64:12:64:32 | call to String.init(_:) | semmle.label | call to String.init(_:) |
| conversions.swift:64:12:64:34 | .utf8 | semmle.label | .utf8 |
| conversions.swift:64:19:64:31 | call to sourceFloat() | semmle.label | call to sourceFloat() |
+| conversions.swift:66:12:66:31 | call to Float.init(_:) | semmle.label | call to Float.init(_:) |
+| conversions.swift:66:18:66:30 | call to sourceFloat() | semmle.label | call to sourceFloat() |
+| conversions.swift:67:12:67:70 | call to Float.init(sign:exponent:significand:) | semmle.label | call to Float.init(sign:exponent:significand:) |
+| conversions.swift:67:41:67:51 | call to sourceInt() | semmle.label | call to sourceInt() |
+| conversions.swift:68:12:68:70 | call to Float.init(sign:exponent:significand:) | semmle.label | call to Float.init(sign:exponent:significand:) |
+| conversions.swift:68:57:68:69 | call to sourceFloat() | semmle.label | call to sourceFloat() |
+| conversions.swift:70:12:70:57 | call to Float.init(signOf:magnitudeOf:) | semmle.label | call to Float.init(signOf:magnitudeOf:) |
+| conversions.swift:70:44:70:56 | call to sourceFloat() | semmle.label | call to sourceFloat() |
+| conversions.swift:72:12:72:24 | call to sourceFloat() | semmle.label | call to sourceFloat() |
+| conversions.swift:72:12:72:26 | .exponent | semmle.label | .exponent |
+| conversions.swift:73:12:73:24 | call to sourceFloat() | semmle.label | call to sourceFloat() |
+| conversions.swift:73:12:73:26 | .significand | semmle.label | .significand |
| conversions.swift:77:12:77:25 | call to sourceString() | semmle.label | call to sourceString() |
| conversions.swift:78:12:78:33 | call to String.init(_:) | semmle.label | call to String.init(_:) |
| conversions.swift:78:19:78:32 | call to sourceString() | semmle.label | call to sourceString() |
| conversions.swift:94:31:94:44 | call to sourceString() | semmle.label | call to sourceString() |
| conversions.swift:95:12:95:12 | parent | semmle.label | parent |
| conversions.swift:96:12:96:12 | parent | semmle.label | parent |
+| conversions.swift:98:25:98:69 | call to unsafeDowncast(_:to:) | semmle.label | call to unsafeDowncast(_:to:) |
+| conversions.swift:98:40:98:40 | parent | semmle.label | parent |
+| conversions.swift:99:12:99:12 | v3 | semmle.label | v3 |
+| conversions.swift:100:12:100:12 | v3 | semmle.label | v3 |
| file://:0:0:0:0 | .first | semmle.label | .first |
| file://:0:0:0:0 | .second | semmle.label | .second |
| file://:0:0:0:0 | [post] self [first] | semmle.label | [post] self [first] |
@@ -228,15 +317,40 @@ subpaths
| stringinterpolation.swift:31:21:31:21 | p2 [second] | stringinterpolation.swift:7:6:7:6 | self [second] | file://:0:0:0:0 | .second | stringinterpolation.swift:31:21:31:24 | .second |
#select
| conversions.swift:24:12:24:22 | call to sourceInt() | conversions.swift:24:12:24:22 | call to sourceInt() | conversions.swift:24:12:24:22 | call to sourceInt() | result |
+| conversions.swift:25:12:25:27 | call to Self.init(_:) | conversions.swift:25:16:25:26 | call to sourceInt() | conversions.swift:25:12:25:27 | call to Self.init(_:) | result |
+| conversions.swift:26:12:26:29 | call to Self.init(_:) | conversions.swift:26:18:26:28 | call to sourceInt() | conversions.swift:26:12:26:29 | call to Self.init(_:) | result |
+| conversions.swift:27:12:27:29 | call to Float.init(_:) | conversions.swift:27:18:27:28 | call to sourceInt() | conversions.swift:27:12:27:29 | call to Float.init(_:) | result |
| conversions.swift:28:12:28:30 | call to String.init(_:) | conversions.swift:28:19:28:29 | call to sourceInt() | conversions.swift:28:12:28:30 | call to String.init(_:) | result |
| conversions.swift:29:12:29:32 | .utf8 | conversions.swift:29:19:29:29 | call to sourceInt() | conversions.swift:29:12:29:32 | .utf8 | result |
+| conversions.swift:37:12:37:12 | v2 | conversions.swift:36:30:36:40 | call to sourceInt() | conversions.swift:37:12:37:12 | v2 | result |
+| conversions.swift:40:12:40:12 | v4 | conversions.swift:39:31:39:41 | call to sourceInt() | conversions.swift:40:12:40:12 | v4 | result |
+| conversions.swift:43:12:43:12 | v5 | conversions.swift:42:36:42:46 | call to sourceInt() | conversions.swift:43:12:43:12 | v5 | result |
+| conversions.swift:46:12:46:12 | v6 | conversions.swift:45:28:45:38 | call to sourceInt() | conversions.swift:46:12:46:12 | v6 | result |
+| conversions.swift:48:12:48:37 | ...! | conversions.swift:48:25:48:35 | call to sourceInt() | conversions.swift:48:12:48:37 | ...! | result |
+| conversions.swift:49:12:49:37 | call to Self.init(clamping:) | conversions.swift:49:26:49:36 | call to sourceInt() | conversions.swift:49:12:49:37 | call to Self.init(clamping:) | result |
+| conversions.swift:50:12:50:47 | call to Self.init(truncatingIfNeeded:) | conversions.swift:50:36:50:46 | call to sourceInt() | conversions.swift:50:12:50:47 | call to Self.init(truncatingIfNeeded:) | result |
+| conversions.swift:51:12:51:42 | ...! | conversions.swift:51:16:51:29 | call to sourceString() | conversions.swift:51:12:51:42 | ...! | result |
+| conversions.swift:53:12:53:41 | call to Self.init(littleEndian:) | conversions.swift:53:30:53:40 | call to sourceInt() | conversions.swift:53:12:53:41 | call to Self.init(littleEndian:) | result |
+| conversions.swift:54:12:54:38 | call to Self.init(bigEndian:) | conversions.swift:54:27:54:37 | call to sourceInt() | conversions.swift:54:12:54:38 | call to Self.init(bigEndian:) | result |
+| conversions.swift:55:12:55:24 | .littleEndian | conversions.swift:55:12:55:22 | call to sourceInt() | conversions.swift:55:12:55:24 | .littleEndian | result |
+| conversions.swift:56:12:56:24 | .bigEndian | conversions.swift:56:12:56:22 | call to sourceInt() | conversions.swift:56:12:56:24 | .bigEndian | result |
| conversions.swift:60:12:60:24 | call to sourceFloat() | conversions.swift:60:12:60:24 | call to sourceFloat() | conversions.swift:60:12:60:24 | call to sourceFloat() | result |
+| conversions.swift:61:12:61:31 | call to Float.init(_:) | conversions.swift:61:18:61:30 | call to sourceFloat() | conversions.swift:61:12:61:31 | call to Float.init(_:) | result |
+| conversions.swift:62:12:62:31 | call to UInt8.init(_:) | conversions.swift:62:18:62:30 | call to sourceFloat() | conversions.swift:62:12:62:31 | call to UInt8.init(_:) | result |
| conversions.swift:63:12:63:32 | call to String.init(_:) | conversions.swift:63:19:63:31 | call to sourceFloat() | conversions.swift:63:12:63:32 | call to String.init(_:) | result |
| conversions.swift:64:12:64:34 | .utf8 | conversions.swift:64:19:64:31 | call to sourceFloat() | conversions.swift:64:12:64:34 | .utf8 | result |
+| conversions.swift:66:12:66:31 | call to Float.init(_:) | conversions.swift:66:18:66:30 | call to sourceFloat() | conversions.swift:66:12:66:31 | call to Float.init(_:) | result |
+| conversions.swift:67:12:67:70 | call to Float.init(sign:exponent:significand:) | conversions.swift:67:41:67:51 | call to sourceInt() | conversions.swift:67:12:67:70 | call to Float.init(sign:exponent:significand:) | result |
+| conversions.swift:68:12:68:70 | call to Float.init(sign:exponent:significand:) | conversions.swift:68:57:68:69 | call to sourceFloat() | conversions.swift:68:12:68:70 | call to Float.init(sign:exponent:significand:) | result |
+| conversions.swift:70:12:70:57 | call to Float.init(signOf:magnitudeOf:) | conversions.swift:70:44:70:56 | call to sourceFloat() | conversions.swift:70:12:70:57 | call to Float.init(signOf:magnitudeOf:) | result |
+| conversions.swift:72:12:72:26 | .exponent | conversions.swift:72:12:72:24 | call to sourceFloat() | conversions.swift:72:12:72:26 | .exponent | result |
+| conversions.swift:73:12:73:26 | .significand | conversions.swift:73:12:73:24 | call to sourceFloat() | conversions.swift:73:12:73:26 | .significand | result |
| conversions.swift:77:12:77:25 | call to sourceString() | conversions.swift:77:12:77:25 | call to sourceString() | conversions.swift:77:12:77:25 | call to sourceString() | result |
| conversions.swift:78:12:78:33 | call to String.init(_:) | conversions.swift:78:19:78:32 | call to sourceString() | conversions.swift:78:12:78:33 | call to String.init(_:) | result |
| conversions.swift:95:12:95:12 | parent | conversions.swift:94:31:94:44 | call to sourceString() | conversions.swift:95:12:95:12 | parent | result |
| conversions.swift:96:12:96:12 | parent | conversions.swift:94:31:94:44 | call to sourceString() | conversions.swift:96:12:96:12 | parent | result |
+| conversions.swift:99:12:99:12 | v3 | conversions.swift:94:31:94:44 | call to sourceString() | conversions.swift:99:12:99:12 | v3 | result |
+| conversions.swift:100:12:100:12 | v3 | conversions.swift:94:31:94:44 | call to sourceString() | conversions.swift:100:12:100:12 | v3 | result |
| simple.swift:12:13:12:24 | ... .+(_:_:) ... | simple.swift:12:17:12:24 | call to source() | simple.swift:12:13:12:24 | ... .+(_:_:) ... | result |
| simple.swift:13:13:13:24 | ... .+(_:_:) ... | simple.swift:13:13:13:20 | call to source() | simple.swift:13:13:13:24 | ... .+(_:_:) ... | result |
| simple.swift:14:13:14:24 | ... .-(_:_:) ... | simple.swift:14:17:14:24 | call to source() | simple.swift:14:13:14:24 | ... .-(_:_:) ... | result |
diff --git a/swift/ql/test/library-tests/dataflow/taint/core/conversions.swift b/swift/ql/test/library-tests/dataflow/taint/core/conversions.swift
index 4789486ad45..a4d8956dff1 100644
--- a/swift/ql/test/library-tests/dataflow/taint/core/conversions.swift
+++ b/swift/ql/test/library-tests/dataflow/taint/core/conversions.swift
@@ -22,9 +22,9 @@ class MyString : LosslessStringConvertible, CustomStringConvertible, CustomDebug
func testConversions() {
sink(arg: sourceInt()) // $ tainted=24
- sink(arg: Int(sourceInt())) // $ MISSING: tainted=
- sink(arg: UInt8(sourceInt())) // $ MISSING: tainted=
- sink(arg: Float(sourceInt())) // $ MISSING: tainted=
+ sink(arg: Int(sourceInt())) // $ tainted=25
+ sink(arg: UInt8(sourceInt())) // $ tainted=26
+ sink(arg: Float(sourceInt())) // $ tainted=27
sink(arg: String(sourceInt())) // $ tainted=28
sink(arg: String(sourceInt()).utf8) // $ tainted=29
sink(arg: [UInt8](sourceString().utf8)) // $ MISSING: tainted=
@@ -34,43 +34,43 @@ func testConversions() {
}
let v2: UInt8 = numericCast(sourceInt())
- sink(arg: v2) // $ MISSING: tainted=
+ sink(arg: v2) // $ tainted=36
let v4: UInt = unsafeBitCast(sourceInt(), to: UInt.self)
- sink(arg: v4) // $ MISSING: tainted=
+ sink(arg: v4) // $ tainted=39
let v5 = UInt(truncatingIfNeeded: sourceInt())
- sink(arg: v5) // $ MISSING: tainted=
+ sink(arg: v5) // $ tainted=42
let v6 = UInt(bitPattern: sourceInt())
- sink(arg: v6) // $ MISSING: tainted=
+ sink(arg: v6) // $ tainted=45
- sink(arg: Int(exactly: sourceInt())!) // $ MISSING: tainted=
- sink(arg: Int(clamping: sourceInt())) // $ MISSING: tainted=
- sink(arg: Int(truncatingIfNeeded: sourceInt())) // $ MISSING: tainted=
- sink(arg: Int(sourceString(), radix: 10)!) // $ MISSING: tainted=
+ sink(arg: Int(exactly: sourceInt())!) // $ tainted=48
+ sink(arg: Int(clamping: sourceInt())) // $ tainted=49
+ sink(arg: Int(truncatingIfNeeded: sourceInt())) // $ tainted=50
+ sink(arg: Int(sourceString(), radix: 10)!) // $ tainted=51
- sink(arg: Int(littleEndian: sourceInt())) // $ MISSING: tainted=
- sink(arg: Int(bigEndian: sourceInt())) // $ MISSING: tainted=
- sink(arg: sourceInt().littleEndian) // $ MISSING: tainted=
- sink(arg: sourceInt().bigEndian) // $ MISSING: tainted=
+ sink(arg: Int(littleEndian: sourceInt())) // $ tainted=53
+ sink(arg: Int(bigEndian: sourceInt())) // $ tainted=54
+ sink(arg: sourceInt().littleEndian) // $ tainted=55
+ sink(arg: sourceInt().bigEndian) // $ tainted=56
// ---
sink(arg: sourceFloat()) // $ tainted=60
- sink(arg: Float(sourceFloat())) // $ MISSING: tainted=
- sink(arg: UInt8(sourceFloat())) // $ MISSING: tainted=
+ sink(arg: Float(sourceFloat())) // $ tainted=61
+ sink(arg: UInt8(sourceFloat())) // $ tainted=62
sink(arg: String(sourceFloat())) // $ tainted=63
sink(arg: String(sourceFloat()).utf8) // $ tainted=64
- sink(arg: Float(sourceFloat())) // MISSING: tainted=
- sink(arg: Float(sign: .plus, exponent: sourceInt(), significand: 0.0)) // MISSING: tainted=
- sink(arg: Float(sign: .plus, exponent: 0, significand: sourceFloat())) // MISSING: tainted=
+ sink(arg: Float(sourceFloat())) // $ tainted=66
+ sink(arg: Float(sign: .plus, exponent: sourceInt(), significand: 0.0)) // $ tainted=67
+ sink(arg: Float(sign: .plus, exponent: 0, significand: sourceFloat())) // $ tainted=68
sink(arg: Float(signOf: sourceFloat(), magnitudeOf: 0.0)) // (good)
- sink(arg: Float(signOf: 0.0, magnitudeOf: sourceFloat())) // MISSING: tainted=
+ sink(arg: Float(signOf: 0.0, magnitudeOf: sourceFloat())) // $ tainted=70
- sink(arg: sourceFloat().exponent) // $ MISSING: tainted=
- sink(arg: sourceFloat().significand) // $ MISSING: tainted=
+ sink(arg: sourceFloat().exponent) // $ tainted=72
+ sink(arg: sourceFloat().significand) // $ tainted=73
// ---
@@ -96,6 +96,6 @@ func testConversions() {
sink(arg: parent as! MyChildClass) // $ tainted=94
let v3: MyChildClass = unsafeDowncast(parent, to: MyChildClass.self)
- sink(arg: v3) // $ MISSING: tainted=
- sink(arg: v3 as! MyParentClass) // $ MISSING: tainted=
+ sink(arg: v3) // $ tainted=94
+ sink(arg: v3 as! MyParentClass) // $ tainted=94
}
From effe3762b8cf0cbcd326d742bd885655d0197538 Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Wed, 9 Aug 2023 17:25:56 +0100
Subject: [PATCH 049/788] Swift: More robust OptionalSomePattern flow.
---
.../lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll | 5 +++++
.../library-tests/dataflow/taint/core/LocalTaint.expected | 1 +
.../ql/test/library-tests/dataflow/taint/core/Taint.expected | 4 ++++
.../test/library-tests/dataflow/taint/core/conversions.swift | 2 +-
4 files changed, 11 insertions(+), 1 deletion(-)
diff --git a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll
index 145ac20573b..0ddd5728e52 100644
--- a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll
+++ b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll
@@ -182,6 +182,11 @@ private module Cached {
// retaining this case increases robustness of flow).
nodeFrom.asExpr() = nodeTo.asExpr().(ForceValueExpr).getSubExpr()
or
+ // read of an optional .some member via `let x: T = y: T?` pattern matching
+ // note: similar to `ForceValueExpr` this is ideally a content `readStep` but
+ // in practice we sometimes have taint on the optional itself.
+ nodeTo.asPattern() = nodeFrom.asPattern().(OptionalSomePattern).getSubPattern()
+ or
// flow through `?` and `?.`
nodeFrom.asExpr() = nodeTo.asExpr().(BindOptionalExpr).getSubExpr()
or
diff --git a/swift/ql/test/library-tests/dataflow/taint/core/LocalTaint.expected b/swift/ql/test/library-tests/dataflow/taint/core/LocalTaint.expected
index 1ff797add87..40862be951d 100644
--- a/swift/ql/test/library-tests/dataflow/taint/core/LocalTaint.expected
+++ b/swift/ql/test/library-tests/dataflow/taint/core/LocalTaint.expected
@@ -23,6 +23,7 @@
| conversions.swift:29:12:29:30 | call to String.init(_:) | conversions.swift:29:12:29:32 | .utf8 |
| conversions.swift:29:19:29:29 | call to sourceInt() | conversions.swift:29:12:29:30 | call to String.init(_:) |
| conversions.swift:30:20:30:33 | call to sourceString() | conversions.swift:30:20:30:35 | .utf8 |
+| conversions.swift:32:5:32:9 | let ...? | conversions.swift:32:9:32:9 | v |
| conversions.swift:32:9:32:9 | SSA def(v) | conversions.swift:33:13:33:13 | v |
| conversions.swift:32:9:32:9 | v | conversions.swift:32:9:32:9 | SSA def(v) |
| conversions.swift:32:13:32:23 | call to sourceInt() | conversions.swift:32:5:32:9 | let ...? |
diff --git a/swift/ql/test/library-tests/dataflow/taint/core/Taint.expected b/swift/ql/test/library-tests/dataflow/taint/core/Taint.expected
index 48ef4ada925..e2c7100da5c 100644
--- a/swift/ql/test/library-tests/dataflow/taint/core/Taint.expected
+++ b/swift/ql/test/library-tests/dataflow/taint/core/Taint.expected
@@ -5,6 +5,7 @@ edges
| conversions.swift:28:19:28:29 | call to sourceInt() | conversions.swift:28:12:28:30 | call to String.init(_:) |
| conversions.swift:29:12:29:30 | call to String.init(_:) | conversions.swift:29:12:29:32 | .utf8 |
| conversions.swift:29:19:29:29 | call to sourceInt() | conversions.swift:29:12:29:30 | call to String.init(_:) |
+| conversions.swift:32:13:32:23 | call to sourceInt() | conversions.swift:33:13:33:13 | v |
| conversions.swift:36:18:36:41 | call to numericCast(_:) | conversions.swift:37:12:37:12 | v2 |
| conversions.swift:36:30:36:40 | call to sourceInt() | conversions.swift:36:18:36:41 | call to numericCast(_:) |
| conversions.swift:39:17:39:57 | call to unsafeBitCast(_:to:) | conversions.swift:40:12:40:12 | v4 |
@@ -131,6 +132,8 @@ nodes
| conversions.swift:29:12:29:30 | call to String.init(_:) | semmle.label | call to String.init(_:) |
| conversions.swift:29:12:29:32 | .utf8 | semmle.label | .utf8 |
| conversions.swift:29:19:29:29 | call to sourceInt() | semmle.label | call to sourceInt() |
+| conversions.swift:32:13:32:23 | call to sourceInt() | semmle.label | call to sourceInt() |
+| conversions.swift:33:13:33:13 | v | semmle.label | v |
| conversions.swift:36:18:36:41 | call to numericCast(_:) | semmle.label | call to numericCast(_:) |
| conversions.swift:36:30:36:40 | call to sourceInt() | semmle.label | call to sourceInt() |
| conversions.swift:37:12:37:12 | v2 | semmle.label | v2 |
@@ -322,6 +325,7 @@ subpaths
| conversions.swift:27:12:27:29 | call to Float.init(_:) | conversions.swift:27:18:27:28 | call to sourceInt() | conversions.swift:27:12:27:29 | call to Float.init(_:) | result |
| conversions.swift:28:12:28:30 | call to String.init(_:) | conversions.swift:28:19:28:29 | call to sourceInt() | conversions.swift:28:12:28:30 | call to String.init(_:) | result |
| conversions.swift:29:12:29:32 | .utf8 | conversions.swift:29:19:29:29 | call to sourceInt() | conversions.swift:29:12:29:32 | .utf8 | result |
+| conversions.swift:33:13:33:13 | v | conversions.swift:32:13:32:23 | call to sourceInt() | conversions.swift:33:13:33:13 | v | result |
| conversions.swift:37:12:37:12 | v2 | conversions.swift:36:30:36:40 | call to sourceInt() | conversions.swift:37:12:37:12 | v2 | result |
| conversions.swift:40:12:40:12 | v4 | conversions.swift:39:31:39:41 | call to sourceInt() | conversions.swift:40:12:40:12 | v4 | result |
| conversions.swift:43:12:43:12 | v5 | conversions.swift:42:36:42:46 | call to sourceInt() | conversions.swift:43:12:43:12 | v5 | result |
diff --git a/swift/ql/test/library-tests/dataflow/taint/core/conversions.swift b/swift/ql/test/library-tests/dataflow/taint/core/conversions.swift
index a4d8956dff1..b9a7ad6ad5c 100644
--- a/swift/ql/test/library-tests/dataflow/taint/core/conversions.swift
+++ b/swift/ql/test/library-tests/dataflow/taint/core/conversions.swift
@@ -30,7 +30,7 @@ func testConversions() {
sink(arg: [UInt8](sourceString().utf8)) // $ MISSING: tainted=
if let v = sourceInt() as? UInt {
- sink(arg: v) // $ MISSING: tainted=
+ sink(arg: v) // $ tainted=32
}
let v2: UInt8 = numericCast(sourceInt())
From 376479325de840bb4665994256ccb936fcd3f9ba Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Thu, 10 Aug 2023 09:27:05 +0100
Subject: [PATCH 050/788] Swift: Model LosslessStringConvertible.
---
.../swift/frameworks/StandardLibrary/String.qll | 5 +++--
.../dataflow/taint/core/LocalTaint.expected | 3 +++
.../library-tests/dataflow/taint/core/Taint.expected | 11 +++++++++++
.../dataflow/taint/core/conversions.swift | 2 +-
4 files changed, 18 insertions(+), 3 deletions(-)
diff --git a/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/String.qll b/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/String.qll
index 4768521322f..65b1f23ad94 100644
--- a/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/String.qll
+++ b/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/String.qll
@@ -27,7 +27,7 @@ private class StringSource extends SourceModelCsv {
}
/**
- * A model for `String` and `StringProtocol` members that permit taint flow.
+ * A model for members of `String`, `StringProtocol` and similar classes that permit taint flow.
*/
private class StringSummaries extends SummaryModelCsv {
override predicate row(string row) {
@@ -111,7 +111,8 @@ private class StringSummaries extends SummaryModelCsv {
";String;true;randomElement();;;Argument[-1];ReturnValue;taint",
";String;true;randomElement(using:);;;Argument[-1];ReturnValue;taint",
";String;true;enumerated();;;Argument[-1];ReturnValue;taint",
- ";String;true;encode(to:);;;Argument[-1];Argument[0];taint"
+ ";String;true;encode(to:);;;Argument[-1];Argument[0];taint",
+ ";LosslessStringConvertible;true;init(_:);;;Argument[0];ReturnValue;taint",
]
}
}
diff --git a/swift/ql/test/library-tests/dataflow/taint/core/LocalTaint.expected b/swift/ql/test/library-tests/dataflow/taint/core/LocalTaint.expected
index 40862be951d..6fd724f31ad 100644
--- a/swift/ql/test/library-tests/dataflow/taint/core/LocalTaint.expected
+++ b/swift/ql/test/library-tests/dataflow/taint/core/LocalTaint.expected
@@ -10,6 +10,7 @@
| conversions.swift:15:7:15:7 | self | conversions.swift:15:7:15:7 | SSA def(self) |
| conversions.swift:16:11:16:11 | SSA def(self) | conversions.swift:16:11:16:42 | self[return] |
| conversions.swift:16:11:16:11 | self | conversions.swift:16:11:16:11 | SSA def(self) |
+| conversions.swift:16:11:16:42 | [summary param] 0 in MyString.init(_:) | conversions.swift:16:11:16:42 | [summary] to write: ReturnValue in MyString.init(_:) |
| conversions.swift:18:28:18:28 | SSA def(self) | conversions.swift:18:28:18:44 | self[return] |
| conversions.swift:18:28:18:28 | self | conversions.swift:18:28:18:28 | SSA def(self) |
| conversions.swift:19:33:19:33 | SSA def(self) | conversions.swift:19:33:19:49 | self[return] |
@@ -73,6 +74,7 @@
| conversions.swift:80:6:80:6 | ms1 | conversions.swift:80:6:80:6 | SSA def(ms1) |
| conversions.swift:80:12:80:26 | call to MyString.init(_:) | conversions.swift:80:12:80:27 | ...! |
| conversions.swift:80:12:80:27 | ...! | conversions.swift:80:6:80:6 | ms1 |
+| conversions.swift:80:21:80:21 | abc | conversions.swift:80:12:80:26 | call to MyString.init(_:) |
| conversions.swift:81:12:81:12 | [post] ms1 | conversions.swift:82:12:82:12 | ms1 |
| conversions.swift:81:12:81:12 | ms1 | conversions.swift:82:12:82:12 | ms1 |
| conversions.swift:82:12:82:12 | [post] ms1 | conversions.swift:83:12:83:12 | ms1 |
@@ -83,6 +85,7 @@
| conversions.swift:86:6:86:6 | ms2 | conversions.swift:86:6:86:6 | SSA def(ms2) |
| conversions.swift:86:12:86:35 | call to MyString.init(_:) | conversions.swift:86:12:86:36 | ...! |
| conversions.swift:86:12:86:36 | ...! | conversions.swift:86:6:86:6 | ms2 |
+| conversions.swift:86:21:86:34 | call to sourceString() | conversions.swift:86:12:86:35 | call to MyString.init(_:) |
| conversions.swift:87:12:87:12 | [post] ms2 | conversions.swift:88:12:88:12 | ms2 |
| conversions.swift:87:12:87:12 | ms2 | conversions.swift:88:12:88:12 | ms2 |
| conversions.swift:88:12:88:12 | [post] ms2 | conversions.swift:89:12:89:12 | ms2 |
diff --git a/swift/ql/test/library-tests/dataflow/taint/core/Taint.expected b/swift/ql/test/library-tests/dataflow/taint/core/Taint.expected
index e2c7100da5c..25b8d79aa68 100644
--- a/swift/ql/test/library-tests/dataflow/taint/core/Taint.expected
+++ b/swift/ql/test/library-tests/dataflow/taint/core/Taint.expected
@@ -36,6 +36,11 @@ edges
| conversions.swift:72:12:72:24 | call to sourceFloat() | conversions.swift:72:12:72:26 | .exponent |
| conversions.swift:73:12:73:24 | call to sourceFloat() | conversions.swift:73:12:73:26 | .significand |
| conversions.swift:78:19:78:32 | call to sourceString() | conversions.swift:78:12:78:33 | call to String.init(_:) |
+| conversions.swift:86:12:86:35 | call to MyString.init(_:) | conversions.swift:86:12:86:35 | call to MyString.init(_:) [some:0] |
+| conversions.swift:86:12:86:35 | call to MyString.init(_:) | conversions.swift:87:12:87:12 | ms2 |
+| conversions.swift:86:12:86:35 | call to MyString.init(_:) [some:0] | conversions.swift:86:12:86:36 | ...! |
+| conversions.swift:86:12:86:36 | ...! | conversions.swift:87:12:87:12 | ms2 |
+| conversions.swift:86:21:86:34 | call to sourceString() | conversions.swift:86:12:86:35 | call to MyString.init(_:) |
| conversions.swift:94:31:94:44 | call to sourceString() | conversions.swift:95:12:95:12 | parent |
| conversions.swift:94:31:94:44 | call to sourceString() | conversions.swift:96:12:96:12 | parent |
| conversions.swift:94:31:94:44 | call to sourceString() | conversions.swift:98:40:98:40 | parent |
@@ -189,6 +194,11 @@ nodes
| conversions.swift:77:12:77:25 | call to sourceString() | semmle.label | call to sourceString() |
| conversions.swift:78:12:78:33 | call to String.init(_:) | semmle.label | call to String.init(_:) |
| conversions.swift:78:19:78:32 | call to sourceString() | semmle.label | call to sourceString() |
+| conversions.swift:86:12:86:35 | call to MyString.init(_:) | semmle.label | call to MyString.init(_:) |
+| conversions.swift:86:12:86:35 | call to MyString.init(_:) [some:0] | semmle.label | call to MyString.init(_:) [some:0] |
+| conversions.swift:86:12:86:36 | ...! | semmle.label | ...! |
+| conversions.swift:86:21:86:34 | call to sourceString() | semmle.label | call to sourceString() |
+| conversions.swift:87:12:87:12 | ms2 | semmle.label | ms2 |
| conversions.swift:94:31:94:44 | call to sourceString() | semmle.label | call to sourceString() |
| conversions.swift:95:12:95:12 | parent | semmle.label | parent |
| conversions.swift:96:12:96:12 | parent | semmle.label | parent |
@@ -351,6 +361,7 @@ subpaths
| conversions.swift:73:12:73:26 | .significand | conversions.swift:73:12:73:24 | call to sourceFloat() | conversions.swift:73:12:73:26 | .significand | result |
| conversions.swift:77:12:77:25 | call to sourceString() | conversions.swift:77:12:77:25 | call to sourceString() | conversions.swift:77:12:77:25 | call to sourceString() | result |
| conversions.swift:78:12:78:33 | call to String.init(_:) | conversions.swift:78:19:78:32 | call to sourceString() | conversions.swift:78:12:78:33 | call to String.init(_:) | result |
+| conversions.swift:87:12:87:12 | ms2 | conversions.swift:86:21:86:34 | call to sourceString() | conversions.swift:87:12:87:12 | ms2 | result |
| conversions.swift:95:12:95:12 | parent | conversions.swift:94:31:94:44 | call to sourceString() | conversions.swift:95:12:95:12 | parent | result |
| conversions.swift:96:12:96:12 | parent | conversions.swift:94:31:94:44 | call to sourceString() | conversions.swift:96:12:96:12 | parent | result |
| conversions.swift:99:12:99:12 | v3 | conversions.swift:94:31:94:44 | call to sourceString() | conversions.swift:99:12:99:12 | v3 | result |
diff --git a/swift/ql/test/library-tests/dataflow/taint/core/conversions.swift b/swift/ql/test/library-tests/dataflow/taint/core/conversions.swift
index b9a7ad6ad5c..499ec8dcfe2 100644
--- a/swift/ql/test/library-tests/dataflow/taint/core/conversions.swift
+++ b/swift/ql/test/library-tests/dataflow/taint/core/conversions.swift
@@ -84,7 +84,7 @@ func testConversions() {
sink(arg: ms1.clean)
let ms2 = MyString(sourceString())!
- sink(arg: ms2) // $ MISSING: tainted=
+ sink(arg: ms2) // $ tainted=86
sink(arg: ms2.description) // $ MISSING: tainted=
sink(arg: ms2.debugDescription) // $ MISSING: tainted=
sink(arg: ms2.clean)
From 7882cf0bf0e93c99713fe1d8b01324cf5c8e4ca9 Mon Sep 17 00:00:00 2001
From: Brandon Stewart <20469703+boveus@users.noreply.github.com>
Date: Thu, 10 Aug 2023 09:21:02 -0400
Subject: [PATCH 051/788] Update
ruby/ql/src/experimental/cwe-208/UnsafeHmacComparison.ql
Co-authored-by: Alex Ford
---
ruby/ql/src/experimental/cwe-208/UnsafeHmacComparison.ql | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/ruby/ql/src/experimental/cwe-208/UnsafeHmacComparison.ql b/ruby/ql/src/experimental/cwe-208/UnsafeHmacComparison.ql
index 48f379ddcdc..9c7de85ebc8 100644
--- a/ruby/ql/src/experimental/cwe-208/UnsafeHmacComparison.ql
+++ b/ruby/ql/src/experimental/cwe-208/UnsafeHmacComparison.ql
@@ -13,8 +13,7 @@
private import codeql.ruby.AST
private import codeql.ruby.DataFlow
-import codeql.ruby.ApiGraphs
-import ruby
+private import codeql.ruby.ApiGraphs
private class OpenSslHmacSource extends DataFlow::Node {
OpenSslHmacSource() {
From b899b648e5a24b536d3bedea69c5c37d2977b2dc Mon Sep 17 00:00:00 2001
From: Brandon Stewart <20469703+boveus@users.noreply.github.com>
Date: Thu, 10 Aug 2023 09:21:16 -0400
Subject: [PATCH 052/788] Update
ruby/ql/src/experimental/cwe-208/UnsafeHmacComparison.ql
Co-authored-by: Alex Ford
---
ruby/ql/src/experimental/cwe-208/UnsafeHmacComparison.ql | 1 +
1 file changed, 1 insertion(+)
diff --git a/ruby/ql/src/experimental/cwe-208/UnsafeHmacComparison.ql b/ruby/ql/src/experimental/cwe-208/UnsafeHmacComparison.ql
index 9c7de85ebc8..e32c534d213 100644
--- a/ruby/ql/src/experimental/cwe-208/UnsafeHmacComparison.ql
+++ b/ruby/ql/src/experimental/cwe-208/UnsafeHmacComparison.ql
@@ -38,6 +38,7 @@ private module UnsafeHmacComparison {
import DataFlow::Global
}
+private import UnsafeHmacComparison::PathGraph
from UnsafeHmacComparison::PathNode source, UnsafeHmacComparison::PathNode sink
where UnsafeHmacComparison::flowPath(source, sink)
select sink.getNode(), source, sink, "This comparison is potentially vulnerable to a timing attack."
From 01577dac3221a205ec4e82084fc25c4ec20f4de7 Mon Sep 17 00:00:00 2001
From: Brandon Stewart <20469703+boveus@users.noreply.github.com>
Date: Thu, 10 Aug 2023 13:59:47 +0000
Subject: [PATCH 053/788] format document
---
ruby/ql/src/experimental/cwe-208/UnsafeHmacComparison.ql | 1 +
1 file changed, 1 insertion(+)
diff --git a/ruby/ql/src/experimental/cwe-208/UnsafeHmacComparison.ql b/ruby/ql/src/experimental/cwe-208/UnsafeHmacComparison.ql
index e32c534d213..65907b0f885 100644
--- a/ruby/ql/src/experimental/cwe-208/UnsafeHmacComparison.ql
+++ b/ruby/ql/src/experimental/cwe-208/UnsafeHmacComparison.ql
@@ -39,6 +39,7 @@ private module UnsafeHmacComparison {
}
private import UnsafeHmacComparison::PathGraph
+
from UnsafeHmacComparison::PathNode source, UnsafeHmacComparison::PathNode sink
where UnsafeHmacComparison::flowPath(source, sink)
select sink.getNode(), source, sink, "This comparison is potentially vulnerable to a timing attack."
From 936b1ced4d9bbc3c4404e6bbfe0b28d8f9de3102 Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Thu, 10 Aug 2023 19:24:30 +0100
Subject: [PATCH 054/788] Swift: Add one last test case (and address a
.expected change elsewhere).
---
.../library-tests/dataflow/taint/core/conversions.swift | 8 ++++++++
.../library-tests/dataflow/taint/libraries/string.swift | 2 +-
2 files changed, 9 insertions(+), 1 deletion(-)
diff --git a/swift/ql/test/library-tests/dataflow/taint/core/conversions.swift b/swift/ql/test/library-tests/dataflow/taint/core/conversions.swift
index 499ec8dcfe2..321c555e0ab 100644
--- a/swift/ql/test/library-tests/dataflow/taint/core/conversions.swift
+++ b/swift/ql/test/library-tests/dataflow/taint/core/conversions.swift
@@ -99,3 +99,11 @@ func testConversions() {
sink(arg: v3) // $ tainted=94
sink(arg: v3 as! MyParentClass) // $ tainted=94
}
+
+var myCEnumConst : Int = 0
+typealias MyCEnumType = UInt32
+
+func testCEnum() {
+ sink(arg: MyCEnumType(myCEnumConst))
+ sink(arg: MyCEnumType(sourceInt())) // $ tainted=108
+}
diff --git a/swift/ql/test/library-tests/dataflow/taint/libraries/string.swift b/swift/ql/test/library-tests/dataflow/taint/libraries/string.swift
index 9f684139fd3..919a07b6675 100644
--- a/swift/ql/test/library-tests/dataflow/taint/libraries/string.swift
+++ b/swift/ql/test/library-tests/dataflow/taint/libraries/string.swift
@@ -589,7 +589,7 @@ func taintedThroughConversion() {
sink(arg: String(describing: source())) // $ tainted=589
sink(arg: Int("123")!)
- sink(arg: Int(source2())!) // $ MISSING: tainted=592
+ sink(arg: Int(source2())!) // $ tainted=592
}
func untaintedFields() {
From 4f5d7e1b6f33ca95a2a0a69bbca84a7ac275ccd9 Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Thu, 10 Aug 2023 19:49:27 +0100
Subject: [PATCH 055/788] Swift: Accept test changes.
---
.../dataflow/dataflow/DataFlow.expected | 31 +++++++++++++++++++
.../dataflow/dataflow/LocalFlow.expected | 11 +++++++
.../dataflow/taint/core/LocalTaint.expected | 2 ++
.../dataflow/taint/core/Taint.expected | 4 +++
4 files changed, 48 insertions(+)
diff --git a/swift/ql/test/library-tests/dataflow/dataflow/DataFlow.expected b/swift/ql/test/library-tests/dataflow/dataflow/DataFlow.expected
index b0404de37ec..77530c3af28 100644
--- a/swift/ql/test/library-tests/dataflow/dataflow/DataFlow.expected
+++ b/swift/ql/test/library-tests/dataflow/dataflow/DataFlow.expected
@@ -6,9 +6,11 @@ edges
| file://:0:0:0:0 | self [v3] | file://:0:0:0:0 | .v3 |
| file://:0:0:0:0 | self [x, some:0] | file://:0:0:0:0 | .x [some:0] |
| file://:0:0:0:0 | self [x] | file://:0:0:0:0 | .x |
+| file://:0:0:0:0 | self [x] | file://:0:0:0:0 | .x |
| file://:0:0:0:0 | value | file://:0:0:0:0 | [post] self [v2] |
| file://:0:0:0:0 | value | file://:0:0:0:0 | [post] self [v3] |
| file://:0:0:0:0 | value | file://:0:0:0:0 | [post] self [x] |
+| file://:0:0:0:0 | value | file://:0:0:0:0 | [post] self [x] |
| file://:0:0:0:0 | value [some:0] | file://:0:0:0:0 | [post] self [v2, some:0] |
| file://:0:0:0:0 | value [some:0] | file://:0:0:0:0 | [post] self [x, some:0] |
| test.swift:6:19:6:26 | call to source() | test.swift:7:15:7:15 | t1 |
@@ -109,6 +111,8 @@ edges
| test.swift:225:14:225:21 | call to source() | test.swift:238:13:238:15 | .source_value |
| test.swift:259:12:259:19 | call to source() | test.swift:259:12:259:19 | call to source() [some:0] |
| test.swift:259:12:259:19 | call to source() | test.swift:263:13:263:28 | call to optionalSource() |
+| test.swift:259:12:259:19 | call to source() | test.swift:517:13:517:28 | call to optionalSource() |
+| test.swift:259:12:259:19 | call to source() | test.swift:544:13:544:28 | call to optionalSource() |
| test.swift:259:12:259:19 | call to source() [some:0] | test.swift:263:13:263:28 | call to optionalSource() [some:0] |
| test.swift:259:12:259:19 | call to source() [some:0] | test.swift:517:13:517:28 | call to optionalSource() [some:0] |
| test.swift:259:12:259:19 | call to source() [some:0] | test.swift:544:13:544:28 | call to optionalSource() [some:0] |
@@ -119,7 +123,9 @@ edges
| test.swift:263:13:263:28 | call to optionalSource() | test.swift:275:15:275:27 | ... ??(_:_:) ... |
| test.swift:263:13:263:28 | call to optionalSource() | test.swift:279:15:279:31 | ... ? ... : ... |
| test.swift:263:13:263:28 | call to optionalSource() | test.swift:280:15:280:38 | ... ? ... : ... |
+| test.swift:263:13:263:28 | call to optionalSource() | test.swift:285:19:285:19 | z |
| test.swift:263:13:263:28 | call to optionalSource() | test.swift:291:16:291:17 | ...? |
+| test.swift:263:13:263:28 | call to optionalSource() | test.swift:300:15:300:15 | z1 |
| test.swift:263:13:263:28 | call to optionalSource() | test.swift:303:15:303:16 | ...! |
| test.swift:263:13:263:28 | call to optionalSource() [some:0] | test.swift:267:15:267:15 | x [some:0] |
| test.swift:263:13:263:28 | call to optionalSource() [some:0] | test.swift:279:26:279:26 | x [some:0] |
@@ -147,6 +153,7 @@ edges
| test.swift:291:16:291:17 | ...? | test.swift:291:16:291:26 | call to signum() |
| test.swift:291:16:291:17 | ...? [some:0] | test.swift:291:16:291:26 | call to signum() [some:0] |
| test.swift:291:16:291:26 | call to signum() | test.swift:291:16:291:26 | call to signum() [some:0] |
+| test.swift:291:16:291:26 | call to signum() | test.swift:292:19:292:19 | z |
| test.swift:291:16:291:26 | call to signum() [some:0] | test.swift:291:8:291:12 | let ...? [some:0] |
| test.swift:298:11:298:15 | let ...? [some:0] | test.swift:298:15:298:15 | z1 |
| test.swift:298:15:298:15 | z1 | test.swift:300:15:300:15 | z1 |
@@ -246,6 +253,7 @@ edges
| test.swift:507:15:507:15 | e2 [some:0] | test.swift:507:15:507:17 | ...! |
| test.swift:509:15:509:15 | e4 [some:0] | test.swift:509:15:509:17 | ...! |
| test.swift:511:15:511:15 | e6 [some:0] | test.swift:511:15:511:17 | ...! |
+| test.swift:517:13:517:28 | call to optionalSource() | test.swift:520:19:520:19 | a |
| test.swift:517:13:517:28 | call to optionalSource() [some:0] | test.swift:519:8:519:12 | let ...? [some:0] |
| test.swift:517:13:517:28 | call to optionalSource() [some:0] | test.swift:524:19:524:19 | x [some:0] |
| test.swift:519:8:519:12 | let ...? [some:0] | test.swift:519:12:519:12 | a |
@@ -256,15 +264,24 @@ edges
| test.swift:526:11:526:22 | .some(...) [some:0] | test.swift:526:21:526:21 | a |
| test.swift:526:21:526:21 | a | test.swift:527:19:527:19 | a |
| test.swift:540:9:540:9 | self [x, some:0] | file://:0:0:0:0 | self [x, some:0] |
+| test.swift:540:9:540:9 | self [x] | file://:0:0:0:0 | self [x] |
+| test.swift:540:9:540:9 | value | file://:0:0:0:0 | value |
| test.swift:540:9:540:9 | value [some:0] | file://:0:0:0:0 | value [some:0] |
+| test.swift:544:13:544:28 | call to optionalSource() | test.swift:546:12:546:12 | x |
| test.swift:544:13:544:28 | call to optionalSource() [some:0] | test.swift:546:12:546:12 | x [some:0] |
| test.swift:546:5:546:5 | [post] cx [x, some:0] | test.swift:550:20:550:20 | cx [x, some:0] |
+| test.swift:546:5:546:5 | [post] cx [x] | test.swift:550:20:550:20 | cx [x] |
+| test.swift:546:12:546:12 | x | test.swift:540:9:540:9 | value |
+| test.swift:546:12:546:12 | x | test.swift:546:5:546:5 | [post] cx [x] |
| test.swift:546:12:546:12 | x [some:0] | test.swift:540:9:540:9 | value [some:0] |
| test.swift:546:12:546:12 | x [some:0] | test.swift:546:5:546:5 | [post] cx [x, some:0] |
| test.swift:550:11:550:15 | let ...? [some:0] | test.swift:550:15:550:15 | z1 |
| test.swift:550:15:550:15 | z1 | test.swift:551:15:551:15 | z1 |
| test.swift:550:20:550:20 | cx [x, some:0] | test.swift:540:9:540:9 | self [x, some:0] |
| test.swift:550:20:550:20 | cx [x, some:0] | test.swift:550:20:550:23 | .x [some:0] |
+| test.swift:550:20:550:20 | cx [x] | test.swift:540:9:540:9 | self [x] |
+| test.swift:550:20:550:20 | cx [x] | test.swift:550:20:550:23 | .x |
+| test.swift:550:20:550:23 | .x | test.swift:551:15:551:15 | z1 |
| test.swift:550:20:550:23 | .x [some:0] | test.swift:550:11:550:15 | let ...? [some:0] |
| test.swift:557:14:557:21 | call to source() | test.swift:557:13:557:21 | call to +(_:) |
| test.swift:566:9:566:9 | self [str] | file://:0:0:0:0 | self [str] |
@@ -396,12 +413,14 @@ nodes
| file://:0:0:0:0 | .v2 [some:0] | semmle.label | .v2 [some:0] |
| file://:0:0:0:0 | .v3 | semmle.label | .v3 |
| file://:0:0:0:0 | .x | semmle.label | .x |
+| file://:0:0:0:0 | .x | semmle.label | .x |
| file://:0:0:0:0 | .x [some:0] | semmle.label | .x [some:0] |
| file://:0:0:0:0 | [post] self [v2, some:0] | semmle.label | [post] self [v2, some:0] |
| file://:0:0:0:0 | [post] self [v2] | semmle.label | [post] self [v2] |
| file://:0:0:0:0 | [post] self [v3] | semmle.label | [post] self [v3] |
| file://:0:0:0:0 | [post] self [x, some:0] | semmle.label | [post] self [x, some:0] |
| file://:0:0:0:0 | [post] self [x] | semmle.label | [post] self [x] |
+| file://:0:0:0:0 | [post] self [x] | semmle.label | [post] self [x] |
| file://:0:0:0:0 | self [a, x] | semmle.label | self [a, x] |
| file://:0:0:0:0 | self [str] | semmle.label | self [str] |
| file://:0:0:0:0 | self [v2, some:0] | semmle.label | self [v2, some:0] |
@@ -409,6 +428,8 @@ nodes
| file://:0:0:0:0 | self [v3] | semmle.label | self [v3] |
| file://:0:0:0:0 | self [x, some:0] | semmle.label | self [x, some:0] |
| file://:0:0:0:0 | self [x] | semmle.label | self [x] |
+| file://:0:0:0:0 | self [x] | semmle.label | self [x] |
+| 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 | semmle.label | value |
@@ -665,6 +686,7 @@ nodes
| test.swift:509:15:509:17 | ...! | semmle.label | ...! |
| test.swift:511:15:511:15 | e6 [some:0] | semmle.label | e6 [some:0] |
| test.swift:511:15:511:17 | ...! | semmle.label | ...! |
+| test.swift:517:13:517:28 | call to optionalSource() | semmle.label | call to optionalSource() |
| test.swift:517:13:517:28 | call to optionalSource() [some:0] | semmle.label | call to optionalSource() [some:0] |
| test.swift:519:8:519:12 | let ...? [some:0] | semmle.label | let ...? [some:0] |
| test.swift:519:12:519:12 | a | semmle.label | a |
@@ -676,13 +698,20 @@ nodes
| test.swift:526:21:526:21 | a | semmle.label | a |
| test.swift:527:19:527:19 | a | semmle.label | a |
| test.swift:540:9:540:9 | self [x, some:0] | semmle.label | self [x, some:0] |
+| test.swift:540:9:540:9 | self [x] | semmle.label | self [x] |
+| test.swift:540:9:540:9 | value | semmle.label | value |
| test.swift:540:9:540:9 | value [some:0] | semmle.label | value [some:0] |
+| test.swift:544:13:544:28 | call to optionalSource() | semmle.label | call to optionalSource() |
| test.swift:544:13:544:28 | call to optionalSource() [some:0] | semmle.label | call to optionalSource() [some:0] |
| test.swift:546:5:546:5 | [post] cx [x, some:0] | semmle.label | [post] cx [x, some:0] |
+| test.swift:546:5:546:5 | [post] cx [x] | semmle.label | [post] cx [x] |
+| test.swift:546:12:546:12 | x | semmle.label | x |
| test.swift:546:12:546:12 | x [some:0] | semmle.label | x [some:0] |
| test.swift:550:11:550:15 | let ...? [some:0] | semmle.label | let ...? [some:0] |
| test.swift:550:15:550:15 | z1 | semmle.label | z1 |
| test.swift:550:20:550:20 | cx [x, some:0] | semmle.label | cx [x, some:0] |
+| test.swift:550:20:550:20 | cx [x] | semmle.label | cx [x] |
+| test.swift:550:20:550:23 | .x | semmle.label | .x |
| test.swift:550:20:550:23 | .x [some:0] | semmle.label | .x [some:0] |
| test.swift:551:15:551:15 | z1 | semmle.label | z1 |
| test.swift:557:13:557:21 | call to +(_:) | semmle.label | call to +(_:) |
@@ -846,8 +875,10 @@ subpaths
| test.swift:219:13:219:15 | .a [x] | test.swift:163:7:163:7 | self [x] | file://:0:0:0:0 | .x | test.swift:219:13:219:17 | .x |
| test.swift:490:24:490:31 | call to source() | test.swift:375:16:375:21 | v | test.swift:375:45:375:62 | call to ... [mySingle:0] | test.swift:490:14:490:32 | call to mkMyEnum1(_:) [mySingle:0] |
| test.swift:503:26:503:33 | call to source() | test.swift:377:18:377:23 | v | test.swift:377:45:377:60 | call to ... [some:0] | test.swift:503:14:503:34 | call to mkOptional1(_:) [some:0] |
+| test.swift:546:12:546:12 | x | test.swift:540:9:540:9 | value | file://:0:0:0:0 | [post] self [x] | test.swift:546:5:546:5 | [post] cx [x] |
| test.swift:546:12:546:12 | x [some:0] | test.swift:540:9:540:9 | value [some:0] | file://:0:0:0:0 | [post] self [x, some:0] | test.swift:546:5:546:5 | [post] cx [x, some:0] |
| test.swift:550:20:550:20 | cx [x, some:0] | test.swift:540:9:540:9 | self [x, some:0] | file://:0:0:0:0 | .x [some:0] | test.swift:550:20:550:23 | .x [some:0] |
+| test.swift:550:20:550:20 | cx [x] | test.swift:540:9:540:9 | self [x] | file://:0:0:0:0 | .x | test.swift:550:20:550:23 | .x |
| test.swift:574:20:574:28 | call to source3() | test.swift:567:10:567:13 | s | test.swift:568:7:568:7 | [post] self [str] | test.swift:574:7:574:7 | [post] self [str] |
| test.swift:580:13:580:33 | call to MyClass.init(s:) [str] | test.swift:566:9:566:9 | self [str] | file://:0:0:0:0 | .str | test.swift:580:13:580:35 | .str |
| test.swift:580:24:580:32 | call to source3() | test.swift:567:10:567:13 | s | test.swift:567:5:569:5 | self[return] [str] | test.swift:580:13:580:33 | call to MyClass.init(s:) [str] |
diff --git a/swift/ql/test/library-tests/dataflow/dataflow/LocalFlow.expected b/swift/ql/test/library-tests/dataflow/dataflow/LocalFlow.expected
index 6058e6e645b..b583c64cdca 100644
--- a/swift/ql/test/library-tests/dataflow/dataflow/LocalFlow.expected
+++ b/swift/ql/test/library-tests/dataflow/dataflow/LocalFlow.expected
@@ -281,30 +281,36 @@
| test.swift:282:26:282:26 | y | test.swift:287:16:287:16 | y |
| test.swift:282:26:282:27 | ...! | test.swift:282:15:282:38 | ... ? ... : ... |
| test.swift:282:31:282:38 | call to source() | test.swift:282:15:282:38 | ... ? ... : ... |
+| test.swift:284:8:284:12 | let ...? | test.swift:284:12:284:12 | z |
| test.swift:284:12:284:12 | SSA def(z) | test.swift:285:19:285:19 | z |
| test.swift:284:12:284:12 | z | test.swift:284:12:284:12 | SSA def(z) |
| test.swift:284:16:284:16 | x | test.swift:284:8:284:12 | let ...? |
| test.swift:284:16:284:16 | x | test.swift:291:16:291:16 | x |
+| test.swift:287:8:287:12 | let ...? | test.swift:287:12:287:12 | z |
| test.swift:287:12:287:12 | SSA def(z) | test.swift:288:19:288:19 | z |
| test.swift:287:12:287:12 | z | test.swift:287:12:287:12 | SSA def(z) |
| test.swift:287:16:287:16 | y | test.swift:287:8:287:12 | let ...? |
| test.swift:287:16:287:16 | y | test.swift:294:16:294:16 | y |
+| test.swift:291:8:291:12 | let ...? | test.swift:291:12:291:12 | z |
| test.swift:291:12:291:12 | SSA def(z) | test.swift:292:19:292:19 | z |
| test.swift:291:12:291:12 | z | test.swift:291:12:291:12 | SSA def(z) |
| test.swift:291:16:291:16 | x | test.swift:291:16:291:17 | ...? |
| test.swift:291:16:291:16 | x | test.swift:298:20:298:20 | x |
| test.swift:291:16:291:26 | OptionalEvaluationExpr | test.swift:291:8:291:12 | let ...? |
| test.swift:291:16:291:26 | call to signum() | test.swift:291:16:291:26 | OptionalEvaluationExpr |
+| test.swift:294:8:294:12 | let ...? | test.swift:294:12:294:12 | z |
| test.swift:294:12:294:12 | SSA def(z) | test.swift:295:19:295:19 | z |
| test.swift:294:12:294:12 | z | test.swift:294:12:294:12 | SSA def(z) |
| test.swift:294:16:294:16 | y | test.swift:294:16:294:17 | ...? |
| test.swift:294:16:294:16 | y | test.swift:299:20:299:20 | y |
| test.swift:294:16:294:26 | OptionalEvaluationExpr | test.swift:294:8:294:12 | let ...? |
| test.swift:294:16:294:26 | call to signum() | test.swift:294:16:294:26 | OptionalEvaluationExpr |
+| test.swift:298:11:298:15 | let ...? | test.swift:298:15:298:15 | z1 |
| test.swift:298:15:298:15 | SSA def(z1) | test.swift:300:15:300:15 | z1 |
| test.swift:298:15:298:15 | z1 | test.swift:298:15:298:15 | SSA def(z1) |
| test.swift:298:20:298:20 | x | test.swift:298:11:298:15 | let ...? |
| test.swift:298:20:298:20 | x | test.swift:303:15:303:15 | x |
+| test.swift:299:11:299:15 | let ...? | test.swift:299:15:299:15 | z2 |
| test.swift:299:15:299:15 | SSA def(z2) | test.swift:301:15:301:15 | z2 |
| test.swift:299:15:299:15 | z2 | test.swift:299:15:299:15 | SSA def(z2) |
| test.swift:299:20:299:20 | y | test.swift:299:11:299:15 | let ...? |
@@ -582,10 +588,12 @@
| test.swift:517:9:517:9 | SSA def(x) | test.swift:519:16:519:16 | x |
| test.swift:517:9:517:9 | x | test.swift:517:9:517:9 | SSA def(x) |
| test.swift:517:13:517:28 | call to optionalSource() | test.swift:517:9:517:9 | x |
+| test.swift:519:8:519:12 | let ...? | test.swift:519:12:519:12 | a |
| test.swift:519:12:519:12 | SSA def(a) | test.swift:519:27:519:27 | SSA phi(a) |
| test.swift:519:12:519:12 | a | test.swift:519:12:519:12 | SSA def(a) |
| test.swift:519:16:519:16 | x | test.swift:519:8:519:12 | let ...? |
| test.swift:519:16:519:16 | x | test.swift:524:19:524:19 | x |
+| test.swift:519:19:519:23 | let ...? | test.swift:519:23:519:23 | b |
| test.swift:519:23:519:23 | SSA def(b) | test.swift:521:19:521:19 | b |
| test.swift:519:23:519:23 | b | test.swift:519:23:519:23 | SSA def(b) |
| test.swift:519:27:519:27 | SSA phi(a) | test.swift:520:19:520:19 | a |
@@ -600,6 +608,7 @@
| test.swift:526:21:526:21 | a | test.swift:526:21:526:21 | SSA def(a) |
| test.swift:526:35:526:35 | SSA def(b) | test.swift:528:19:528:19 | b |
| test.swift:526:35:526:35 | b | test.swift:526:35:526:35 | SSA def(b) |
+| test.swift:533:8:533:17 | let ...? | test.swift:533:12:533:17 | (...) |
| test.swift:533:13:533:13 | SSA def(x) | test.swift:534:19:534:19 | x |
| test.swift:533:13:533:13 | x | test.swift:533:13:533:13 | SSA def(x) |
| test.swift:533:16:533:16 | SSA def(y) | test.swift:535:19:535:19 | y |
@@ -628,9 +637,11 @@
| test.swift:547:14:547:16 | call to C.init() | test.swift:547:9:547:9 | cy |
| test.swift:548:5:548:5 | [post] cy | test.swift:552:20:552:20 | cy |
| test.swift:548:5:548:5 | cy | test.swift:552:20:552:20 | cy |
+| test.swift:550:11:550:15 | let ...? | test.swift:550:15:550:15 | z1 |
| test.swift:550:15:550:15 | SSA def(z1) | test.swift:551:15:551:15 | z1 |
| test.swift:550:15:550:15 | z1 | test.swift:550:15:550:15 | SSA def(z1) |
| test.swift:550:20:550:23 | .x | test.swift:550:11:550:15 | let ...? |
+| test.swift:552:11:552:15 | let ...? | test.swift:552:15:552:15 | z2 |
| test.swift:552:15:552:15 | SSA def(z2) | test.swift:553:15:553:15 | z2 |
| test.swift:552:15:552:15 | z2 | test.swift:552:15:552:15 | SSA def(z2) |
| test.swift:552:20:552:23 | .x | test.swift:552:11:552:15 | let ...? |
diff --git a/swift/ql/test/library-tests/dataflow/taint/core/LocalTaint.expected b/swift/ql/test/library-tests/dataflow/taint/core/LocalTaint.expected
index 6fd724f31ad..cb5fc364e9f 100644
--- a/swift/ql/test/library-tests/dataflow/taint/core/LocalTaint.expected
+++ b/swift/ql/test/library-tests/dataflow/taint/core/LocalTaint.expected
@@ -107,6 +107,8 @@
| conversions.swift:98:40:98:40 | parent | conversions.swift:98:25:98:69 | call to unsafeDowncast(_:to:) |
| conversions.swift:99:12:99:12 | [post] v3 | conversions.swift:100:12:100:12 | v3 |
| conversions.swift:99:12:99:12 | v3 | conversions.swift:100:12:100:12 | v3 |
+| conversions.swift:107:24:107:24 | myCEnumConst | conversions.swift:107:12:107:36 | call to Self.init(_:) |
+| conversions.swift:108:24:108:34 | call to sourceInt() | conversions.swift:108:12:108:35 | call to Self.init(_:) |
| simple.swift:12:13:12:13 | 1 | simple.swift:12:13:12:24 | ... .+(_:_:) ... |
| simple.swift:12:17:12:24 | call to source() | simple.swift:12:13:12:24 | ... .+(_:_:) ... |
| simple.swift:13:13:13:20 | call to source() | simple.swift:13:13:13:24 | ... .+(_:_:) ... |
diff --git a/swift/ql/test/library-tests/dataflow/taint/core/Taint.expected b/swift/ql/test/library-tests/dataflow/taint/core/Taint.expected
index 25b8d79aa68..427040adc40 100644
--- a/swift/ql/test/library-tests/dataflow/taint/core/Taint.expected
+++ b/swift/ql/test/library-tests/dataflow/taint/core/Taint.expected
@@ -47,6 +47,7 @@ edges
| conversions.swift:98:25:98:69 | call to unsafeDowncast(_:to:) | conversions.swift:99:12:99:12 | v3 |
| conversions.swift:98:25:98:69 | call to unsafeDowncast(_:to:) | conversions.swift:100:12:100:12 | v3 |
| conversions.swift:98:40:98:40 | parent | conversions.swift:98:25:98:69 | call to unsafeDowncast(_:to:) |
+| conversions.swift:108:24:108:34 | call to sourceInt() | conversions.swift:108:12:108:35 | call to Self.init(_:) |
| file://:0:0:0:0 | self [first] | file://:0:0:0:0 | .first |
| file://:0:0:0:0 | self [second] | file://:0:0:0:0 | .second |
| file://:0:0:0:0 | value | file://:0:0:0:0 | [post] self [first] |
@@ -206,6 +207,8 @@ nodes
| conversions.swift:98:40:98:40 | parent | semmle.label | parent |
| conversions.swift:99:12:99:12 | v3 | semmle.label | v3 |
| conversions.swift:100:12:100:12 | v3 | semmle.label | v3 |
+| conversions.swift:108:12:108:35 | call to Self.init(_:) | semmle.label | call to Self.init(_:) |
+| conversions.swift:108:24:108:34 | call to sourceInt() | semmle.label | call to sourceInt() |
| file://:0:0:0:0 | .first | semmle.label | .first |
| file://:0:0:0:0 | .second | semmle.label | .second |
| file://:0:0:0:0 | [post] self [first] | semmle.label | [post] self [first] |
@@ -366,6 +369,7 @@ subpaths
| conversions.swift:96:12:96:12 | parent | conversions.swift:94:31:94:44 | call to sourceString() | conversions.swift:96:12:96:12 | parent | result |
| conversions.swift:99:12:99:12 | v3 | conversions.swift:94:31:94:44 | call to sourceString() | conversions.swift:99:12:99:12 | v3 | result |
| conversions.swift:100:12:100:12 | v3 | conversions.swift:94:31:94:44 | call to sourceString() | conversions.swift:100:12:100:12 | v3 | result |
+| conversions.swift:108:12:108:35 | call to Self.init(_:) | conversions.swift:108:24:108:34 | call to sourceInt() | conversions.swift:108:12:108:35 | call to Self.init(_:) | result |
| simple.swift:12:13:12:24 | ... .+(_:_:) ... | simple.swift:12:17:12:24 | call to source() | simple.swift:12:13:12:24 | ... .+(_:_:) ... | result |
| simple.swift:13:13:13:24 | ... .+(_:_:) ... | simple.swift:13:13:13:20 | call to source() | simple.swift:13:13:13:24 | ... .+(_:_:) ... | result |
| simple.swift:14:13:14:24 | ... .-(_:_:) ... | simple.swift:14:17:14:24 | call to source() | simple.swift:14:13:14:24 | ... .-(_:_:) ... | result |
From 0a2e4def8e925b5a3c62b429443124982a3c95eb Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Thu, 10 Aug 2023 19:53:24 +0100
Subject: [PATCH 056/788] Swift: Change note.
---
swift/ql/lib/change-notes/2023-08-10-numeric-models.md | 5 +++++
1 file changed, 5 insertions(+)
create mode 100644 swift/ql/lib/change-notes/2023-08-10-numeric-models.md
diff --git a/swift/ql/lib/change-notes/2023-08-10-numeric-models.md b/swift/ql/lib/change-notes/2023-08-10-numeric-models.md
new file mode 100644
index 00000000000..85812d99c10
--- /dev/null
+++ b/swift/ql/lib/change-notes/2023-08-10-numeric-models.md
@@ -0,0 +1,5 @@
+---
+category: minorAnalysis
+---
+
+* Added taint models for `Numeric` conversions.
From 70c2ef599a8ea7adc777336a34abbfafd6c2b555 Mon Sep 17 00:00:00 2001
From: Robert Marsh
Date: Thu, 10 Aug 2023 20:24:01 +0000
Subject: [PATCH 057/788] Swift: collection/tuple content for dictionary flow
---
.../dataflow/internal/DataFlowPrivate.qll | 62 +++++++++++++++++++
.../frameworks/StandardLibrary/Dictionary.qll | 9 +++
.../dataflow/dataflow/DataFlow.expected | 34 ++++++++++
.../dataflow/dataflow/LocalFlow.expected | 53 ++++++++++++++++
.../dataflow/dataflow/test.swift | 35 +++++++++++
5 files changed, 193 insertions(+)
create mode 100644 swift/ql/lib/codeql/swift/frameworks/StandardLibrary/Dictionary.qll
diff --git a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll
index 145ac20573b..e5ea5ad0034 100644
--- a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll
+++ b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll
@@ -9,6 +9,7 @@ private import codeql.swift.dataflow.FlowSummary as FlowSummary
private import codeql.swift.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl
private import codeql.swift.frameworks.StandardLibrary.PointerTypes
private import codeql.swift.frameworks.StandardLibrary.Array
+private import codeql.swift.frameworks.StandardLibrary.Dictionary
/** Gets the callable in which this node occurs. */
DataFlowCallable nodeGetEnclosingCallable(Node n) { result = n.(NodeImpl).getEnclosingCallable() }
@@ -114,6 +115,9 @@ private module Cached {
any(ApplyExpr apply).getQualifier(), any(TupleElementExpr te).getSubExpr(),
any(SubscriptExpr se).getBase()
])
+ } or
+ TDictionarySubscriptNode(SubscriptExpr e) {
+ e.getBase().getType().getCanonicalType() instanceof CanonicalDictionaryType
}
private predicate localSsaFlowStepUseUse(Ssa::Definition def, Node nodeFrom, Node nodeTo) {
@@ -296,6 +300,29 @@ import Cached
/** Holds if `n` should be hidden from path explanations. */
predicate nodeIsHidden(Node n) { n instanceof FlowSummaryNode }
+private class DictionarySubscriptNode extends NodeImpl, TDictionarySubscriptNode {
+ SubscriptExpr expr;
+ DictionarySubscriptNode() {
+ this = TDictionarySubscriptNode(expr)
+ }
+
+ override DataFlowCallable getEnclosingCallable() {
+ result.asSourceCallable() = expr.getEnclosingCallable()
+ }
+
+ override string toStringImpl() {
+ result = "DictionarySubscriptNode"
+ }
+
+ override Location getLocationImpl() {
+ result = expr.getLocation()
+ }
+
+ SubscriptExpr getExpr() {
+ result = expr
+ }
+}
+
private module ParameterNodes {
abstract class ParameterNodeImpl extends NodeImpl {
predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) { none() }
@@ -727,6 +754,30 @@ predicate storeStep(Node node1, ContentSet c, Node node2) {
c.isSingleton(any(Content::ArrayContent ac))
)
or
+ // read of a dictionary value via subscript operator, with intermediate step
+ exists(AssignExpr assign, SubscriptExpr subscript |
+ subscript = assign.getDest() and
+ (
+ subscript.getArgument(0).getExpr() = node1.asExpr() and
+ node2.(DictionarySubscriptNode).getExpr() = subscript and
+ c.isSingleton(any(Content::TupleContent tc | tc.getIndex() = 1))
+ or
+ assign.getSource() = node1.asExpr() and
+ node2.(DictionarySubscriptNode).getExpr() = subscript and
+ c.isSingleton(any(Content::TupleContent tc | tc.getIndex() = 1))
+ or
+ node1.(DictionarySubscriptNode) = node1 and
+ node2.asExpr() = subscript and
+ c.isSingleton(any(Content::CollectionContent cc))
+ )
+ )
+ or
+ exists(DictionaryExpr dict |
+ node1.asExpr() = dict.getAnElement() and
+ node2.asExpr() = dict and
+ c.isSingleton(any(Content::CollectionContent cc))
+ )
+ or
FlowSummaryImpl::Private::Steps::summaryStoreStep(node1.(FlowSummaryNode).getSummaryNode(), c,
node2.(FlowSummaryNode).getSummaryNode())
}
@@ -807,6 +858,17 @@ predicate readStep(Node node1, ContentSet c, Node node2) {
c.isSingleton(any(Content::ArrayContent ac))
)
or
+ // read of a dictionary value via subscript operator
+ exists(SubscriptExpr subscript |
+ subscript.getBase() = node1.asExpr() and
+ node2.(DictionarySubscriptNode).getExpr() = subscript and
+ c.isSingleton(any(Content::CollectionContent cc))
+ or
+ subscript = node2.asExpr() and
+ node1.(DictionarySubscriptNode).getExpr() = subscript and
+ c.isSingleton(any(Content::TupleContent tc | tc.getIndex() = 1))
+ )
+ or
FlowSummaryImpl::Private::Steps::summaryReadStep(node1.(FlowSummaryNode).getSummaryNode(), c,
node2.(FlowSummaryNode).getSummaryNode())
}
diff --git a/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/Dictionary.qll b/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/Dictionary.qll
new file mode 100644
index 00000000000..42d8d8ff55b
--- /dev/null
+++ b/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/Dictionary.qll
@@ -0,0 +1,9 @@
+import swift
+private import codeql.swift.dataflow.ExternalFlow
+
+/**
+ * An instance of the `Dictionary` type.
+ */
+class CanonicalDictionaryType extends BoundGenericType {
+ CanonicalDictionaryType() { this.getName().matches("Dictionary<%") }
+}
diff --git a/swift/ql/test/library-tests/dataflow/dataflow/DataFlow.expected b/swift/ql/test/library-tests/dataflow/dataflow/DataFlow.expected
index c638ea8e344..fe5b804c71a 100644
--- a/swift/ql/test/library-tests/dataflow/dataflow/DataFlow.expected
+++ b/swift/ql/test/library-tests/dataflow/dataflow/DataFlow.expected
@@ -404,6 +404,20 @@ edges
| test.swift:756:15:756:19 | .v2 [some:0] | test.swift:756:15:756:21 | ...! |
| test.swift:757:15:757:15 | mo1 [v3] | test.swift:732:9:732:9 | self [v3] |
| test.swift:757:15:757:15 | mo1 [v3] | test.swift:757:15:757:19 | .v3 |
+| test.swift:767:5:767:5 | [post] dict1 [Array element] | test.swift:769:15:769:15 | dict1 [Array element] |
+| test.swift:767:16:767:23 | call to source() | test.swift:767:5:767:5 | [post] dict1 [Array element] |
+| test.swift:769:15:769:15 | dict1 [Array element] | test.swift:769:15:769:22 | ...[...] |
+| test.swift:779:17:779:29 | [...] [Collection element, Tuple element at index 1] | test.swift:780:15:780:15 | dict3 [Collection element, Tuple element at index 1] |
+| test.swift:779:18:779:28 | (...) [Tuple element at index 1] | test.swift:779:17:779:29 | [...] [Collection element, Tuple element at index 1] |
+| test.swift:779:21:779:28 | call to source() | test.swift:779:18:779:28 | (...) [Tuple element at index 1] |
+| test.swift:780:15:780:15 | dict3 [Collection element, Tuple element at index 1] | test.swift:780:15:780:22 | DictionarySubscriptNode [Tuple element at index 1] |
+| test.swift:780:15:780:22 | DictionarySubscriptNode [Tuple element at index 1] | test.swift:780:15:780:22 | ...[...] |
+| test.swift:789:17:789:28 | [...] [Collection element, Tuple element at index 1] | test.swift:793:15:793:15 | dict4 [Collection element, Tuple element at index 1] |
+| test.swift:789:18:789:27 | (...) [Tuple element at index 1] | test.swift:789:17:789:28 | [...] [Collection element, Tuple element at index 1] |
+| test.swift:789:20:789:27 | call to source() | test.swift:789:18:789:27 | (...) [Tuple element at index 1] |
+| test.swift:793:15:793:15 | dict4 [Collection element, Tuple element at index 1] | test.swift:793:15:793:35 | call to randomElement() [some:0, Tuple element at index 1] |
+| test.swift:793:15:793:35 | call to randomElement() [some:0, Tuple element at index 1] | test.swift:793:15:793:36 | ...! [Tuple element at index 1] |
+| test.swift:793:15:793:36 | ...! [Tuple element at index 1] | test.swift:793:15:793:38 | .1 |
nodes
| file://:0:0:0:0 | .a [x] | semmle.label | .a [x] |
| file://:0:0:0:0 | .str | semmle.label | .str |
@@ -849,6 +863,23 @@ nodes
| test.swift:756:15:756:21 | ...! | semmle.label | ...! |
| test.swift:757:15:757:15 | mo1 [v3] | semmle.label | mo1 [v3] |
| test.swift:757:15:757:19 | .v3 | semmle.label | .v3 |
+| test.swift:767:5:767:5 | [post] dict1 [Array element] | semmle.label | [post] dict1 [Array element] |
+| test.swift:767:16:767:23 | call to source() | semmle.label | call to source() |
+| test.swift:769:15:769:15 | dict1 [Array element] | semmle.label | dict1 [Array element] |
+| test.swift:769:15:769:22 | ...[...] | semmle.label | ...[...] |
+| test.swift:779:17:779:29 | [...] [Collection element, Tuple element at index 1] | semmle.label | [...] [Collection element, Tuple element at index 1] |
+| test.swift:779:18:779:28 | (...) [Tuple element at index 1] | semmle.label | (...) [Tuple element at index 1] |
+| test.swift:779:21:779:28 | call to source() | semmle.label | call to source() |
+| test.swift:780:15:780:15 | dict3 [Collection element, Tuple element at index 1] | semmle.label | dict3 [Collection element, Tuple element at index 1] |
+| test.swift:780:15:780:22 | ...[...] | semmle.label | ...[...] |
+| test.swift:780:15:780:22 | DictionarySubscriptNode [Tuple element at index 1] | semmle.label | DictionarySubscriptNode [Tuple element at index 1] |
+| test.swift:789:17:789:28 | [...] [Collection element, Tuple element at index 1] | semmle.label | [...] [Collection element, Tuple element at index 1] |
+| test.swift:789:18:789:27 | (...) [Tuple element at index 1] | semmle.label | (...) [Tuple element at index 1] |
+| test.swift:789:20:789:27 | call to source() | semmle.label | call to source() |
+| test.swift:793:15:793:15 | dict4 [Collection element, Tuple element at index 1] | semmle.label | dict4 [Collection element, Tuple element at index 1] |
+| test.swift:793:15:793:35 | call to randomElement() [some:0, Tuple element at index 1] | semmle.label | call to randomElement() [some:0, Tuple element at index 1] |
+| test.swift:793:15:793:36 | ...! [Tuple element at index 1] | semmle.label | ...! [Tuple element at index 1] |
+| test.swift:793:15:793:38 | .1 | semmle.label | .1 |
subpaths
| test.swift:75:22:75:22 | x | test.swift:65:16:65:28 | arg1 | test.swift:65:1:70:1 | arg2[return] | test.swift:75:32:75:32 | [post] y |
| test.swift:114:19:114:19 | arg | test.swift:109:9:109:14 | arg | test.swift:110:12:110:12 | arg | test.swift:114:12:114:22 | call to ... |
@@ -996,3 +1027,6 @@ subpaths
| test.swift:754:15:754:15 | v3 | test.swift:744:10:744:17 | call to source() | test.swift:754:15:754:15 | v3 | result |
| test.swift:756:15:756:21 | ...! | test.swift:746:14:746:21 | call to source() | test.swift:756:15:756:21 | ...! | result |
| test.swift:757:15:757:19 | .v3 | test.swift:747:14:747:21 | call to source() | test.swift:757:15:757:19 | .v3 | result |
+| test.swift:769:15:769:22 | ...[...] | test.swift:767:16:767:23 | call to source() | test.swift:769:15:769:22 | ...[...] | result |
+| test.swift:780:15:780:22 | ...[...] | test.swift:779:21:779:28 | call to source() | test.swift:780:15:780:22 | ...[...] | result |
+| test.swift:793:15:793:38 | .1 | test.swift:789:20:789:27 | call to source() | test.swift:793:15:793:38 | .1 | result |
diff --git a/swift/ql/test/library-tests/dataflow/dataflow/LocalFlow.expected b/swift/ql/test/library-tests/dataflow/dataflow/LocalFlow.expected
index 18e5d25010d..ff1643d6018 100644
--- a/swift/ql/test/library-tests/dataflow/dataflow/LocalFlow.expected
+++ b/swift/ql/test/library-tests/dataflow/dataflow/LocalFlow.expected
@@ -913,3 +913,56 @@
| test.swift:759:15:759:15 | mo2 | test.swift:760:15:760:15 | mo2 |
| test.swift:759:15:759:20 | .v2 | test.swift:759:15:759:22 | ...! |
| test.swift:760:15:760:15 | mo2 | test.swift:760:15:760:18 | ...! |
+| test.swift:764:9:764:9 | SSA def(dict1) | test.swift:765:15:765:15 | dict1 |
+| test.swift:764:9:764:9 | dict1 | test.swift:764:9:764:9 | SSA def(dict1) |
+| test.swift:764:17:764:31 | [...] | test.swift:764:9:764:9 | dict1 |
+| test.swift:765:15:765:15 | &... | test.swift:767:5:767:5 | dict1 |
+| test.swift:765:15:765:15 | [post] dict1 | test.swift:765:15:765:15 | &... |
+| test.swift:765:15:765:15 | dict1 | test.swift:765:15:765:15 | &... |
+| test.swift:767:5:767:5 | &... | test.swift:769:15:769:15 | dict1 |
+| test.swift:767:5:767:5 | [post] dict1 | test.swift:767:5:767:5 | &... |
+| test.swift:767:5:767:5 | dict1 | test.swift:767:5:767:5 | &... |
+| test.swift:769:15:769:15 | [post] dict1 | test.swift:769:15:769:15 | &... |
+| test.swift:769:15:769:15 | dict1 | test.swift:769:15:769:15 | &... |
+| test.swift:771:9:771:9 | SSA def(dict2) | test.swift:772:15:772:15 | dict2 |
+| test.swift:771:9:771:9 | dict2 | test.swift:771:9:771:9 | SSA def(dict2) |
+| test.swift:771:17:771:29 | [...] | test.swift:771:9:771:9 | dict2 |
+| test.swift:772:15:772:15 | &... | test.swift:774:25:774:25 | dict2 |
+| test.swift:772:15:772:15 | [post] dict2 | test.swift:772:15:772:15 | &... |
+| test.swift:772:15:772:15 | dict2 | test.swift:772:15:772:15 | &... |
+| test.swift:774:10:774:10 | SSA def(key) | test.swift:775:19:775:19 | key |
+| test.swift:774:10:774:10 | key | test.swift:774:10:774:10 | SSA def(key) |
+| test.swift:774:15:774:15 | SSA def(value) | test.swift:776:19:776:19 | value |
+| test.swift:774:15:774:15 | value | test.swift:774:15:774:15 | SSA def(value) |
+| test.swift:779:9:779:9 | SSA def(dict3) | test.swift:780:15:780:15 | dict3 |
+| test.swift:779:9:779:9 | dict3 | test.swift:779:9:779:9 | SSA def(dict3) |
+| test.swift:779:17:779:29 | [...] | test.swift:779:9:779:9 | dict3 |
+| test.swift:780:15:780:15 | &... | test.swift:782:5:782:5 | dict3 |
+| test.swift:780:15:780:15 | [post] dict3 | test.swift:780:15:780:15 | &... |
+| test.swift:780:15:780:15 | dict3 | test.swift:780:15:780:15 | &... |
+| test.swift:782:5:782:5 | &... | test.swift:784:25:784:25 | dict3 |
+| test.swift:782:5:782:5 | [post] dict3 | test.swift:782:5:782:5 | &... |
+| test.swift:782:5:782:5 | dict3 | test.swift:782:5:782:5 | &... |
+| test.swift:784:10:784:10 | SSA def(key) | test.swift:785:19:785:19 | key |
+| test.swift:784:10:784:10 | key | test.swift:784:10:784:10 | SSA def(key) |
+| test.swift:784:15:784:15 | SSA def(value) | test.swift:786:19:786:19 | value |
+| test.swift:784:15:784:15 | value | test.swift:784:15:784:15 | SSA def(value) |
+| test.swift:789:9:789:9 | SSA def(dict4) | test.swift:790:15:790:15 | dict4 |
+| test.swift:789:9:789:9 | dict4 | test.swift:789:9:789:9 | SSA def(dict4) |
+| test.swift:789:17:789:28 | [...] | test.swift:789:9:789:9 | dict4 |
+| test.swift:790:15:790:15 | &... | test.swift:791:15:791:15 | dict4 |
+| test.swift:790:15:790:15 | [post] dict4 | test.swift:790:15:790:15 | &... |
+| test.swift:790:15:790:15 | dict4 | test.swift:790:15:790:15 | &... |
+| test.swift:790:15:790:52 | call to updateValue(_:forKey:) | test.swift:790:15:790:53 | ...! |
+| test.swift:791:15:791:15 | &... | test.swift:792:15:792:15 | dict4 |
+| test.swift:791:15:791:15 | [post] dict4 | test.swift:791:15:791:15 | &... |
+| test.swift:791:15:791:15 | dict4 | test.swift:791:15:791:15 | &... |
+| test.swift:791:15:791:52 | call to updateValue(_:forKey:) | test.swift:791:15:791:53 | ...! |
+| test.swift:792:15:792:15 | [post] dict4 | test.swift:793:15:793:15 | dict4 |
+| test.swift:792:15:792:15 | dict4 | test.swift:793:15:793:15 | dict4 |
+| test.swift:792:15:792:35 | call to randomElement() | test.swift:792:15:792:36 | ...! |
+| test.swift:793:15:793:15 | [post] dict4 | test.swift:794:15:794:15 | dict4 |
+| test.swift:793:15:793:15 | dict4 | test.swift:794:15:794:15 | dict4 |
+| test.swift:793:15:793:35 | call to randomElement() | test.swift:793:15:793:36 | ...! |
+| test.swift:794:15:794:15 | [post] dict4 | test.swift:795:15:795:15 | dict4 |
+| test.swift:794:15:794:15 | dict4 | test.swift:795:15:795:15 | dict4 |
diff --git a/swift/ql/test/library-tests/dataflow/dataflow/test.swift b/swift/ql/test/library-tests/dataflow/dataflow/test.swift
index 44001572dbd..2621fa4c4f4 100644
--- a/swift/ql/test/library-tests/dataflow/dataflow/test.swift
+++ b/swift/ql/test/library-tests/dataflow/dataflow/test.swift
@@ -759,3 +759,38 @@ func testWriteOptional() {
sink(arg: mo2!.v2!) // $ MISSING:flow=749
sink(arg: mo2!.v3) // $ MISSING:flow=750
}
+
+func testDictionary() {
+ var dict1 = [1:2, 3:4, 5:6]
+ sink(arg: dict1[1])
+
+ dict1[1] = source()
+
+ sink(arg: dict1[1]) // $ flow=767
+
+ var dict2 = [source(): 1]
+ sink(arg: dict2[1])
+
+ for (key, value) in dict2 {
+ sink(arg: key) // $ MISSING: flow=771
+ sink(arg: value)
+ }
+
+ var dict3 = [1: source()]
+ sink(arg: dict3[1]) // $ flow=779
+
+ dict3[source()] = 2
+
+ for (key, value) in dict3 {
+ sink(arg: key) // $ MISSING: flow=782
+ sink(arg: value) // $ MISSING: flow=779
+ }
+
+ var dict4 = [1:source()]
+ sink(arg: dict4.updateValue(1, forKey: source())!)
+ sink(arg: dict4.updateValue(source(), forKey: 2)!)
+ sink(arg: dict4.randomElement()!.0) // $ MISSING: flow=791
+ sink(arg: dict4.randomElement()!.1) // $ flow=789 MISSING: flow=790
+ sink(arg: dict4.keys.randomElement()) // $ MISSING: flow=791
+ sink(arg: dict4.values.randomElement()) // $ MISSING: flow=789 flow=790
+}
\ No newline at end of file
From d3c68c773a136105933967c025f015d97f457e6f Mon Sep 17 00:00:00 2001
From: Robert Marsh
Date: Thu, 10 Aug 2023 20:52:04 +0000
Subject: [PATCH 058/788] Swift: Add Dictionary models
---
.../frameworks/StandardLibrary/Dictionary.qll | 14 ++++++++++++++
.../dataflow/dataflow/DataFlow.expected | 17 +++++++++++++++++
.../library-tests/dataflow/dataflow/test.swift | 8 ++++----
3 files changed, 35 insertions(+), 4 deletions(-)
diff --git a/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/Dictionary.qll b/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/Dictionary.qll
index 42d8d8ff55b..8683faf8fc5 100644
--- a/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/Dictionary.qll
+++ b/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/Dictionary.qll
@@ -7,3 +7,17 @@ private import codeql.swift.dataflow.ExternalFlow
class CanonicalDictionaryType extends BoundGenericType {
CanonicalDictionaryType() { this.getName().matches("Dictionary<%") }
}
+
+/**
+ * A model for `Dictionary` and related class members that permit data flow.
+ */
+private class DictionarySummaries extends SummaryModelCsv {
+ override predicate row(string row) {
+ row =
+ [
+ ";Dictionary;true;updateValue(_:forKey:);;;Argument[0];Argument[-1].CollectionElement.TupleElement[1];value",
+ ";Dictionary;true;updateValue(_:forKey:);;;Argument[1];Argument[-1].CollectionElement.TupleElement[0];value",
+ ";Dictionary;true;updateValue(_:forKey:);;;Argument[-1].CollectionElement.TupleElement[1];ReturnValue.OptionalSome;value"
+ ]
+ }
+}
diff --git a/swift/ql/test/library-tests/dataflow/dataflow/DataFlow.expected b/swift/ql/test/library-tests/dataflow/dataflow/DataFlow.expected
index fe5b804c71a..32e532deea9 100644
--- a/swift/ql/test/library-tests/dataflow/dataflow/DataFlow.expected
+++ b/swift/ql/test/library-tests/dataflow/dataflow/DataFlow.expected
@@ -415,6 +415,13 @@ edges
| test.swift:789:17:789:28 | [...] [Collection element, Tuple element at index 1] | test.swift:793:15:793:15 | dict4 [Collection element, Tuple element at index 1] |
| test.swift:789:18:789:27 | (...) [Tuple element at index 1] | test.swift:789:17:789:28 | [...] [Collection element, Tuple element at index 1] |
| test.swift:789:20:789:27 | call to source() | test.swift:789:18:789:27 | (...) [Tuple element at index 1] |
+| test.swift:790:15:790:15 | [post] dict4 [Collection element, Tuple element at index 0] | test.swift:792:15:792:15 | dict4 [Collection element, Tuple element at index 0] |
+| test.swift:790:44:790:51 | call to source() | test.swift:790:15:790:15 | [post] dict4 [Collection element, Tuple element at index 0] |
+| test.swift:791:15:791:15 | [post] dict4 [Collection element, Tuple element at index 1] | test.swift:793:15:793:15 | dict4 [Collection element, Tuple element at index 1] |
+| test.swift:791:33:791:40 | call to source() | test.swift:791:15:791:15 | [post] dict4 [Collection element, Tuple element at index 1] |
+| test.swift:792:15:792:15 | dict4 [Collection element, Tuple element at index 0] | test.swift:792:15:792:35 | call to randomElement() [some:0, Tuple element at index 0] |
+| test.swift:792:15:792:35 | call to randomElement() [some:0, Tuple element at index 0] | test.swift:792:15:792:36 | ...! [Tuple element at index 0] |
+| test.swift:792:15:792:36 | ...! [Tuple element at index 0] | test.swift:792:15:792:38 | .0 |
| test.swift:793:15:793:15 | dict4 [Collection element, Tuple element at index 1] | test.swift:793:15:793:35 | call to randomElement() [some:0, Tuple element at index 1] |
| test.swift:793:15:793:35 | call to randomElement() [some:0, Tuple element at index 1] | test.swift:793:15:793:36 | ...! [Tuple element at index 1] |
| test.swift:793:15:793:36 | ...! [Tuple element at index 1] | test.swift:793:15:793:38 | .1 |
@@ -876,6 +883,14 @@ nodes
| test.swift:789:17:789:28 | [...] [Collection element, Tuple element at index 1] | semmle.label | [...] [Collection element, Tuple element at index 1] |
| test.swift:789:18:789:27 | (...) [Tuple element at index 1] | semmle.label | (...) [Tuple element at index 1] |
| test.swift:789:20:789:27 | call to source() | semmle.label | call to source() |
+| test.swift:790:15:790:15 | [post] dict4 [Collection element, Tuple element at index 0] | semmle.label | [post] dict4 [Collection element, Tuple element at index 0] |
+| test.swift:790:44:790:51 | call to source() | semmle.label | call to source() |
+| test.swift:791:15:791:15 | [post] dict4 [Collection element, Tuple element at index 1] | semmle.label | [post] dict4 [Collection element, Tuple element at index 1] |
+| test.swift:791:33:791:40 | call to source() | semmle.label | call to source() |
+| test.swift:792:15:792:15 | dict4 [Collection element, Tuple element at index 0] | semmle.label | dict4 [Collection element, Tuple element at index 0] |
+| test.swift:792:15:792:35 | call to randomElement() [some:0, Tuple element at index 0] | semmle.label | call to randomElement() [some:0, Tuple element at index 0] |
+| test.swift:792:15:792:36 | ...! [Tuple element at index 0] | semmle.label | ...! [Tuple element at index 0] |
+| test.swift:792:15:792:38 | .0 | semmle.label | .0 |
| test.swift:793:15:793:15 | dict4 [Collection element, Tuple element at index 1] | semmle.label | dict4 [Collection element, Tuple element at index 1] |
| test.swift:793:15:793:35 | call to randomElement() [some:0, Tuple element at index 1] | semmle.label | call to randomElement() [some:0, Tuple element at index 1] |
| test.swift:793:15:793:36 | ...! [Tuple element at index 1] | semmle.label | ...! [Tuple element at index 1] |
@@ -1029,4 +1044,6 @@ subpaths
| test.swift:757:15:757:19 | .v3 | test.swift:747:14:747:21 | call to source() | test.swift:757:15:757:19 | .v3 | result |
| test.swift:769:15:769:22 | ...[...] | test.swift:767:16:767:23 | call to source() | test.swift:769:15:769:22 | ...[...] | result |
| test.swift:780:15:780:22 | ...[...] | test.swift:779:21:779:28 | call to source() | test.swift:780:15:780:22 | ...[...] | result |
+| test.swift:792:15:792:38 | .0 | test.swift:790:44:790:51 | call to source() | test.swift:792:15:792:38 | .0 | result |
| test.swift:793:15:793:38 | .1 | test.swift:789:20:789:27 | call to source() | test.swift:793:15:793:38 | .1 | result |
+| test.swift:793:15:793:38 | .1 | test.swift:791:33:791:40 | call to source() | test.swift:793:15:793:38 | .1 | result |
diff --git a/swift/ql/test/library-tests/dataflow/dataflow/test.swift b/swift/ql/test/library-tests/dataflow/dataflow/test.swift
index 2621fa4c4f4..4b5d98a2e66 100644
--- a/swift/ql/test/library-tests/dataflow/dataflow/test.swift
+++ b/swift/ql/test/library-tests/dataflow/dataflow/test.swift
@@ -789,8 +789,8 @@ func testDictionary() {
var dict4 = [1:source()]
sink(arg: dict4.updateValue(1, forKey: source())!)
sink(arg: dict4.updateValue(source(), forKey: 2)!)
- sink(arg: dict4.randomElement()!.0) // $ MISSING: flow=791
- sink(arg: dict4.randomElement()!.1) // $ flow=789 MISSING: flow=790
- sink(arg: dict4.keys.randomElement()) // $ MISSING: flow=791
- sink(arg: dict4.values.randomElement()) // $ MISSING: flow=789 flow=790
+ sink(arg: dict4.randomElement()!.0) // $ flow=790
+ sink(arg: dict4.randomElement()!.1) // $ flow=789 flow=791
+ sink(arg: dict4.keys.randomElement()) // $ MISSING: flow=790
+ sink(arg: dict4.values.randomElement()) // $ MISSING: flow=789 flow=791
}
\ No newline at end of file
From f5fac66627414b8b828bb588ecbc7b59c1f2f6e0 Mon Sep 17 00:00:00 2001
From: Robert Marsh
Date: Fri, 11 Aug 2023 17:31:39 +0000
Subject: [PATCH 059/788] Swift: autoformat
---
.../dataflow/internal/DataFlowPrivate.qll | 21 +++++++------------
1 file changed, 7 insertions(+), 14 deletions(-)
diff --git a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll
index e5ea5ad0034..bdd8c528f07 100644
--- a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll
+++ b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll
@@ -302,25 +302,18 @@ predicate nodeIsHidden(Node n) { n instanceof FlowSummaryNode }
private class DictionarySubscriptNode extends NodeImpl, TDictionarySubscriptNode {
SubscriptExpr expr;
- DictionarySubscriptNode() {
- this = TDictionarySubscriptNode(expr)
- }
+
+ DictionarySubscriptNode() { this = TDictionarySubscriptNode(expr) }
override DataFlowCallable getEnclosingCallable() {
result.asSourceCallable() = expr.getEnclosingCallable()
}
- override string toStringImpl() {
- result = "DictionarySubscriptNode"
- }
+ override string toStringImpl() { result = "DictionarySubscriptNode" }
- override Location getLocationImpl() {
- result = expr.getLocation()
- }
+ override Location getLocationImpl() { result = expr.getLocation() }
- SubscriptExpr getExpr() {
- result = expr
- }
+ SubscriptExpr getExpr() { result = expr }
}
private module ParameterNodes {
@@ -755,7 +748,7 @@ predicate storeStep(Node node1, ContentSet c, Node node2) {
)
or
// read of a dictionary value via subscript operator, with intermediate step
- exists(AssignExpr assign, SubscriptExpr subscript |
+ exists(AssignExpr assign, SubscriptExpr subscript |
subscript = assign.getDest() and
(
subscript.getArgument(0).getExpr() = node1.asExpr() and
@@ -859,7 +852,7 @@ predicate readStep(Node node1, ContentSet c, Node node2) {
)
or
// read of a dictionary value via subscript operator
- exists(SubscriptExpr subscript |
+ exists(SubscriptExpr subscript |
subscript.getBase() = node1.asExpr() and
node2.(DictionarySubscriptNode).getExpr() = subscript and
c.isSingleton(any(Content::CollectionContent cc))
From 653a2294820f281a654285c5cc147bc2f05a9083 Mon Sep 17 00:00:00 2001
From: Robert Marsh
Date: Fri, 11 Aug 2023 17:32:29 +0000
Subject: [PATCH 060/788] Swift: QLDoc for Dicitonary.qll
---
.../codeql/swift/frameworks/StandardLibrary/Dictionary.qll | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/Dictionary.qll b/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/Dictionary.qll
index 8683faf8fc5..4fef7052d78 100644
--- a/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/Dictionary.qll
+++ b/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/Dictionary.qll
@@ -1,3 +1,8 @@
+/**
+ * Provides models for the Swift `Dictionary` class.
+ */
+
+
import swift
private import codeql.swift.dataflow.ExternalFlow
From f047161741d89ddf92130cf1f6aa6131769c57b7 Mon Sep 17 00:00:00 2001
From: Robert Marsh
Date: Fri, 11 Aug 2023 17:33:45 +0000
Subject: [PATCH 061/788] Swift: Change note for dictionary flow
---
swift/ql/lib/change-notes/2023-08-11-dictionary-flow.md | 4 ++++
1 file changed, 4 insertions(+)
create mode 100644 swift/ql/lib/change-notes/2023-08-11-dictionary-flow.md
diff --git a/swift/ql/lib/change-notes/2023-08-11-dictionary-flow.md b/swift/ql/lib/change-notes/2023-08-11-dictionary-flow.md
new file mode 100644
index 00000000000..6496777f9e5
--- /dev/null
+++ b/swift/ql/lib/change-notes/2023-08-11-dictionary-flow.md
@@ -0,0 +1,4 @@
+---
+category: minorAnalysis
+---
+* Added flow steps through `Dictionary` keys and values.
From 3f0a249aeae2dadcc6a91a73fc757dd2f04429d0 Mon Sep 17 00:00:00 2001
From: Robert Marsh
Date: Fri, 11 Aug 2023 18:42:37 +0000
Subject: [PATCH 062/788] Swift: Autoformat Dictionary.qll
---
.../lib/codeql/swift/frameworks/StandardLibrary/Dictionary.qll | 1 -
1 file changed, 1 deletion(-)
diff --git a/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/Dictionary.qll b/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/Dictionary.qll
index 4fef7052d78..6ad2ba09e99 100644
--- a/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/Dictionary.qll
+++ b/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/Dictionary.qll
@@ -2,7 +2,6 @@
* Provides models for the Swift `Dictionary` class.
*/
-
import swift
private import codeql.swift.dataflow.ExternalFlow
From 657642a1228170c61ed5c263332d9de2f2281e0d Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Mon, 14 Aug 2023 14:12:07 +0100
Subject: [PATCH 063/788] Java: Expose parts of the vquery message in the test.
---
.../security/CWE-730/ExpRedosTest.java | 5 +++-
.../query-tests/security/CWE-730/ReDoS.ql | 23 ++++++++++++++++++-
2 files changed, 26 insertions(+), 2 deletions(-)
diff --git a/java/ql/test/query-tests/security/CWE-730/ExpRedosTest.java b/java/ql/test/query-tests/security/CWE-730/ExpRedosTest.java
index 4a31060850b..28742c161e6 100644
--- a/java/ql/test/query-tests/security/CWE-730/ExpRedosTest.java
+++ b/java/ql/test/query-tests/security/CWE-730/ExpRedosTest.java
@@ -431,7 +431,10 @@ class ExpRedosTest {
"(a*)*b", // $ hasExpRedos
// BAD - but not detected due to the way possessive quantifiers are approximated
- "((aa|a*+)b)*c" // $ MISSING: hasExpRedos
+ "((aa|a*+)b)*c", // $ MISSING: hasExpRedos
+
+ // BAD - testsing
+ "(?is)(a|aa?)*b" // $ hasExpRedos hasPrefixMsg="starting with 'is' and " hasPump=a
};
void test() {
diff --git a/java/ql/test/query-tests/security/CWE-730/ReDoS.ql b/java/ql/test/query-tests/security/CWE-730/ReDoS.ql
index 97719364f94..4011946318e 100644
--- a/java/ql/test/query-tests/security/CWE-730/ReDoS.ql
+++ b/java/ql/test/query-tests/security/CWE-730/ReDoS.ql
@@ -4,8 +4,13 @@ private import semmle.code.java.regex.RegexTreeView::RegexTreeView as TreeView
import codeql.regex.nfa.ExponentialBackTracking::Make as ExponentialBackTracking
import semmle.code.java.regex.regex
+bindingset[s]
+string quote(string s) { if s.matches("% %") then result = "\"" + s + "\"" else result = s }
+
module HasExpRedos implements TestSig {
- string getARelevantTag() { result = ["hasExpRedos", "hasParseFailure"] }
+ string getARelevantTag() {
+ result = ["hasExpRedos", "hasParseFailure", "hasPump", "hasPrefixMsg"]
+ }
predicate hasActualResult(Location location, string element, string tag, string value) {
tag = "hasExpRedos" and
@@ -25,6 +30,22 @@ module HasExpRedos implements TestSig {
element = r.toString()
)
}
+
+ predicate hasOptionalResult(Location location, string element, string tag, string value) {
+ exists(TreeView::RegExpTerm t, Regex r, string pump, string prefixMsg |
+ ExponentialBackTracking::hasReDoSResult(t, pump, _, prefixMsg) and
+ t.occursInRegex(r, _, _) and
+ (
+ tag = "hasPrefixMsg" and
+ value = quote(prefixMsg)
+ or
+ tag = "hasPump" and
+ value = pump
+ ) and
+ location = r.getLocation() and
+ element = r.toString()
+ )
+ }
}
import MakeTest
From a9f5471e763b36bbe0d0c87a0a39681ecc7a88ff Mon Sep 17 00:00:00 2001
From: Robert Marsh
Date: Tue, 15 Aug 2023 17:58:21 +0000
Subject: [PATCH 064/788] Swift: add tests for broken dictionary flow case
---
.../dataflow/dataflow/DataFlow.expected | 73 +++++++++++--------
.../dataflow/dataflow/LocalFlow.expected | 54 ++++++++------
.../dataflow/dataflow/test.swift | 11 ++-
3 files changed, 79 insertions(+), 59 deletions(-)
diff --git a/swift/ql/test/library-tests/dataflow/dataflow/DataFlow.expected b/swift/ql/test/library-tests/dataflow/dataflow/DataFlow.expected
index 32e532deea9..b483b2b7099 100644
--- a/swift/ql/test/library-tests/dataflow/dataflow/DataFlow.expected
+++ b/swift/ql/test/library-tests/dataflow/dataflow/DataFlow.expected
@@ -408,23 +408,28 @@ edges
| test.swift:767:16:767:23 | call to source() | test.swift:767:5:767:5 | [post] dict1 [Array element] |
| test.swift:769:15:769:15 | dict1 [Array element] | test.swift:769:15:769:22 | ...[...] |
| test.swift:779:17:779:29 | [...] [Collection element, Tuple element at index 1] | test.swift:780:15:780:15 | dict3 [Collection element, Tuple element at index 1] |
+| test.swift:779:17:779:29 | [...] [Collection element, Tuple element at index 1] | test.swift:782:5:782:5 | dict3 [Collection element, Tuple element at index 1] |
| test.swift:779:18:779:28 | (...) [Tuple element at index 1] | test.swift:779:17:779:29 | [...] [Collection element, Tuple element at index 1] |
| test.swift:779:21:779:28 | call to source() | test.swift:779:18:779:28 | (...) [Tuple element at index 1] |
| test.swift:780:15:780:15 | dict3 [Collection element, Tuple element at index 1] | test.swift:780:15:780:22 | DictionarySubscriptNode [Tuple element at index 1] |
| test.swift:780:15:780:22 | DictionarySubscriptNode [Tuple element at index 1] | test.swift:780:15:780:22 | ...[...] |
-| test.swift:789:17:789:28 | [...] [Collection element, Tuple element at index 1] | test.swift:793:15:793:15 | dict4 [Collection element, Tuple element at index 1] |
-| test.swift:789:18:789:27 | (...) [Tuple element at index 1] | test.swift:789:17:789:28 | [...] [Collection element, Tuple element at index 1] |
-| test.swift:789:20:789:27 | call to source() | test.swift:789:18:789:27 | (...) [Tuple element at index 1] |
-| test.swift:790:15:790:15 | [post] dict4 [Collection element, Tuple element at index 0] | test.swift:792:15:792:15 | dict4 [Collection element, Tuple element at index 0] |
-| test.swift:790:44:790:51 | call to source() | test.swift:790:15:790:15 | [post] dict4 [Collection element, Tuple element at index 0] |
-| test.swift:791:15:791:15 | [post] dict4 [Collection element, Tuple element at index 1] | test.swift:793:15:793:15 | dict4 [Collection element, Tuple element at index 1] |
-| test.swift:791:33:791:40 | call to source() | test.swift:791:15:791:15 | [post] dict4 [Collection element, Tuple element at index 1] |
-| test.swift:792:15:792:15 | dict4 [Collection element, Tuple element at index 0] | test.swift:792:15:792:35 | call to randomElement() [some:0, Tuple element at index 0] |
-| test.swift:792:15:792:35 | call to randomElement() [some:0, Tuple element at index 0] | test.swift:792:15:792:36 | ...! [Tuple element at index 0] |
-| test.swift:792:15:792:36 | ...! [Tuple element at index 0] | test.swift:792:15:792:38 | .0 |
-| test.swift:793:15:793:15 | dict4 [Collection element, Tuple element at index 1] | test.swift:793:15:793:35 | call to randomElement() [some:0, Tuple element at index 1] |
-| test.swift:793:15:793:35 | call to randomElement() [some:0, Tuple element at index 1] | test.swift:793:15:793:36 | ...! [Tuple element at index 1] |
-| test.swift:793:15:793:36 | ...! [Tuple element at index 1] | test.swift:793:15:793:38 | .1 |
+| test.swift:782:5:782:5 | dict3 [Collection element, Tuple element at index 1] | test.swift:785:15:785:15 | dict3 [Collection element, Tuple element at index 1] |
+| test.swift:785:15:785:15 | dict3 [Collection element, Tuple element at index 1] | test.swift:785:15:785:35 | call to randomElement() [some:0, Tuple element at index 1] |
+| test.swift:785:15:785:35 | call to randomElement() [some:0, Tuple element at index 1] | test.swift:785:15:785:36 | ...! [Tuple element at index 1] |
+| test.swift:785:15:785:36 | ...! [Tuple element at index 1] | test.swift:785:15:785:38 | .1 |
+| test.swift:792:17:792:28 | [...] [Collection element, Tuple element at index 1] | test.swift:796:15:796:15 | dict4 [Collection element, Tuple element at index 1] |
+| test.swift:792:18:792:27 | (...) [Tuple element at index 1] | test.swift:792:17:792:28 | [...] [Collection element, Tuple element at index 1] |
+| test.swift:792:20:792:27 | call to source() | test.swift:792:18:792:27 | (...) [Tuple element at index 1] |
+| test.swift:793:15:793:15 | [post] dict4 [Collection element, Tuple element at index 0] | test.swift:795:15:795:15 | dict4 [Collection element, Tuple element at index 0] |
+| test.swift:793:44:793:51 | call to source() | test.swift:793:15:793:15 | [post] dict4 [Collection element, Tuple element at index 0] |
+| test.swift:794:15:794:15 | [post] dict4 [Collection element, Tuple element at index 1] | test.swift:796:15:796:15 | dict4 [Collection element, Tuple element at index 1] |
+| test.swift:794:33:794:40 | call to source() | test.swift:794:15:794:15 | [post] dict4 [Collection element, Tuple element at index 1] |
+| test.swift:795:15:795:15 | dict4 [Collection element, Tuple element at index 0] | test.swift:795:15:795:35 | call to randomElement() [some:0, Tuple element at index 0] |
+| test.swift:795:15:795:35 | call to randomElement() [some:0, Tuple element at index 0] | test.swift:795:15:795:36 | ...! [Tuple element at index 0] |
+| test.swift:795:15:795:36 | ...! [Tuple element at index 0] | test.swift:795:15:795:38 | .0 |
+| test.swift:796:15:796:15 | dict4 [Collection element, Tuple element at index 1] | test.swift:796:15:796:35 | call to randomElement() [some:0, Tuple element at index 1] |
+| test.swift:796:15:796:35 | call to randomElement() [some:0, Tuple element at index 1] | test.swift:796:15:796:36 | ...! [Tuple element at index 1] |
+| test.swift:796:15:796:36 | ...! [Tuple element at index 1] | test.swift:796:15:796:38 | .1 |
nodes
| file://:0:0:0:0 | .a [x] | semmle.label | .a [x] |
| file://:0:0:0:0 | .str | semmle.label | .str |
@@ -880,21 +885,26 @@ nodes
| test.swift:780:15:780:15 | dict3 [Collection element, Tuple element at index 1] | semmle.label | dict3 [Collection element, Tuple element at index 1] |
| test.swift:780:15:780:22 | ...[...] | semmle.label | ...[...] |
| test.swift:780:15:780:22 | DictionarySubscriptNode [Tuple element at index 1] | semmle.label | DictionarySubscriptNode [Tuple element at index 1] |
-| test.swift:789:17:789:28 | [...] [Collection element, Tuple element at index 1] | semmle.label | [...] [Collection element, Tuple element at index 1] |
-| test.swift:789:18:789:27 | (...) [Tuple element at index 1] | semmle.label | (...) [Tuple element at index 1] |
-| test.swift:789:20:789:27 | call to source() | semmle.label | call to source() |
-| test.swift:790:15:790:15 | [post] dict4 [Collection element, Tuple element at index 0] | semmle.label | [post] dict4 [Collection element, Tuple element at index 0] |
-| test.swift:790:44:790:51 | call to source() | semmle.label | call to source() |
-| test.swift:791:15:791:15 | [post] dict4 [Collection element, Tuple element at index 1] | semmle.label | [post] dict4 [Collection element, Tuple element at index 1] |
-| test.swift:791:33:791:40 | call to source() | semmle.label | call to source() |
-| test.swift:792:15:792:15 | dict4 [Collection element, Tuple element at index 0] | semmle.label | dict4 [Collection element, Tuple element at index 0] |
-| test.swift:792:15:792:35 | call to randomElement() [some:0, Tuple element at index 0] | semmle.label | call to randomElement() [some:0, Tuple element at index 0] |
-| test.swift:792:15:792:36 | ...! [Tuple element at index 0] | semmle.label | ...! [Tuple element at index 0] |
-| test.swift:792:15:792:38 | .0 | semmle.label | .0 |
-| test.swift:793:15:793:15 | dict4 [Collection element, Tuple element at index 1] | semmle.label | dict4 [Collection element, Tuple element at index 1] |
-| test.swift:793:15:793:35 | call to randomElement() [some:0, Tuple element at index 1] | semmle.label | call to randomElement() [some:0, Tuple element at index 1] |
-| test.swift:793:15:793:36 | ...! [Tuple element at index 1] | semmle.label | ...! [Tuple element at index 1] |
-| test.swift:793:15:793:38 | .1 | semmle.label | .1 |
+| test.swift:782:5:782:5 | dict3 [Collection element, Tuple element at index 1] | semmle.label | dict3 [Collection element, Tuple element at index 1] |
+| test.swift:785:15:785:15 | dict3 [Collection element, Tuple element at index 1] | semmle.label | dict3 [Collection element, Tuple element at index 1] |
+| test.swift:785:15:785:35 | call to randomElement() [some:0, Tuple element at index 1] | semmle.label | call to randomElement() [some:0, Tuple element at index 1] |
+| test.swift:785:15:785:36 | ...! [Tuple element at index 1] | semmle.label | ...! [Tuple element at index 1] |
+| test.swift:785:15:785:38 | .1 | semmle.label | .1 |
+| test.swift:792:17:792:28 | [...] [Collection element, Tuple element at index 1] | semmle.label | [...] [Collection element, Tuple element at index 1] |
+| test.swift:792:18:792:27 | (...) [Tuple element at index 1] | semmle.label | (...) [Tuple element at index 1] |
+| test.swift:792:20:792:27 | call to source() | semmle.label | call to source() |
+| test.swift:793:15:793:15 | [post] dict4 [Collection element, Tuple element at index 0] | semmle.label | [post] dict4 [Collection element, Tuple element at index 0] |
+| test.swift:793:44:793:51 | call to source() | semmle.label | call to source() |
+| test.swift:794:15:794:15 | [post] dict4 [Collection element, Tuple element at index 1] | semmle.label | [post] dict4 [Collection element, Tuple element at index 1] |
+| test.swift:794:33:794:40 | call to source() | semmle.label | call to source() |
+| test.swift:795:15:795:15 | dict4 [Collection element, Tuple element at index 0] | semmle.label | dict4 [Collection element, Tuple element at index 0] |
+| test.swift:795:15:795:35 | call to randomElement() [some:0, Tuple element at index 0] | semmle.label | call to randomElement() [some:0, Tuple element at index 0] |
+| test.swift:795:15:795:36 | ...! [Tuple element at index 0] | semmle.label | ...! [Tuple element at index 0] |
+| test.swift:795:15:795:38 | .0 | semmle.label | .0 |
+| test.swift:796:15:796:15 | dict4 [Collection element, Tuple element at index 1] | semmle.label | dict4 [Collection element, Tuple element at index 1] |
+| test.swift:796:15:796:35 | call to randomElement() [some:0, Tuple element at index 1] | semmle.label | call to randomElement() [some:0, Tuple element at index 1] |
+| test.swift:796:15:796:36 | ...! [Tuple element at index 1] | semmle.label | ...! [Tuple element at index 1] |
+| test.swift:796:15:796:38 | .1 | semmle.label | .1 |
subpaths
| test.swift:75:22:75:22 | x | test.swift:65:16:65:28 | arg1 | test.swift:65:1:70:1 | arg2[return] | test.swift:75:32:75:32 | [post] y |
| test.swift:114:19:114:19 | arg | test.swift:109:9:109:14 | arg | test.swift:110:12:110:12 | arg | test.swift:114:12:114:22 | call to ... |
@@ -1044,6 +1054,7 @@ subpaths
| test.swift:757:15:757:19 | .v3 | test.swift:747:14:747:21 | call to source() | test.swift:757:15:757:19 | .v3 | result |
| test.swift:769:15:769:22 | ...[...] | test.swift:767:16:767:23 | call to source() | test.swift:769:15:769:22 | ...[...] | result |
| test.swift:780:15:780:22 | ...[...] | test.swift:779:21:779:28 | call to source() | test.swift:780:15:780:22 | ...[...] | result |
-| test.swift:792:15:792:38 | .0 | test.swift:790:44:790:51 | call to source() | test.swift:792:15:792:38 | .0 | result |
-| test.swift:793:15:793:38 | .1 | test.swift:789:20:789:27 | call to source() | test.swift:793:15:793:38 | .1 | result |
-| test.swift:793:15:793:38 | .1 | test.swift:791:33:791:40 | call to source() | test.swift:793:15:793:38 | .1 | result |
+| test.swift:785:15:785:38 | .1 | test.swift:779:21:779:28 | call to source() | test.swift:785:15:785:38 | .1 | result |
+| test.swift:795:15:795:38 | .0 | test.swift:793:44:793:51 | call to source() | test.swift:795:15:795:38 | .0 | result |
+| test.swift:796:15:796:38 | .1 | test.swift:792:20:792:27 | call to source() | test.swift:796:15:796:38 | .1 | result |
+| test.swift:796:15:796:38 | .1 | test.swift:794:33:794:40 | call to source() | test.swift:796:15:796:38 | .1 | result |
diff --git a/swift/ql/test/library-tests/dataflow/dataflow/LocalFlow.expected b/swift/ql/test/library-tests/dataflow/dataflow/LocalFlow.expected
index ff1643d6018..cd45b14d436 100644
--- a/swift/ql/test/library-tests/dataflow/dataflow/LocalFlow.expected
+++ b/swift/ql/test/library-tests/dataflow/dataflow/LocalFlow.expected
@@ -940,29 +940,35 @@
| test.swift:780:15:780:15 | &... | test.swift:782:5:782:5 | dict3 |
| test.swift:780:15:780:15 | [post] dict3 | test.swift:780:15:780:15 | &... |
| test.swift:780:15:780:15 | dict3 | test.swift:780:15:780:15 | &... |
-| test.swift:782:5:782:5 | &... | test.swift:784:25:784:25 | dict3 |
+| test.swift:782:5:782:5 | &... | test.swift:784:15:784:15 | dict3 |
| test.swift:782:5:782:5 | [post] dict3 | test.swift:782:5:782:5 | &... |
| test.swift:782:5:782:5 | dict3 | test.swift:782:5:782:5 | &... |
-| test.swift:784:10:784:10 | SSA def(key) | test.swift:785:19:785:19 | key |
-| test.swift:784:10:784:10 | key | test.swift:784:10:784:10 | SSA def(key) |
-| test.swift:784:15:784:15 | SSA def(value) | test.swift:786:19:786:19 | value |
-| test.swift:784:15:784:15 | value | test.swift:784:15:784:15 | SSA def(value) |
-| test.swift:789:9:789:9 | SSA def(dict4) | test.swift:790:15:790:15 | dict4 |
-| test.swift:789:9:789:9 | dict4 | test.swift:789:9:789:9 | SSA def(dict4) |
-| test.swift:789:17:789:28 | [...] | test.swift:789:9:789:9 | dict4 |
-| test.swift:790:15:790:15 | &... | test.swift:791:15:791:15 | dict4 |
-| test.swift:790:15:790:15 | [post] dict4 | test.swift:790:15:790:15 | &... |
-| test.swift:790:15:790:15 | dict4 | test.swift:790:15:790:15 | &... |
-| test.swift:790:15:790:52 | call to updateValue(_:forKey:) | test.swift:790:15:790:53 | ...! |
-| test.swift:791:15:791:15 | &... | test.swift:792:15:792:15 | dict4 |
-| test.swift:791:15:791:15 | [post] dict4 | test.swift:791:15:791:15 | &... |
-| test.swift:791:15:791:15 | dict4 | test.swift:791:15:791:15 | &... |
-| test.swift:791:15:791:52 | call to updateValue(_:forKey:) | test.swift:791:15:791:53 | ...! |
-| test.swift:792:15:792:15 | [post] dict4 | test.swift:793:15:793:15 | dict4 |
-| test.swift:792:15:792:15 | dict4 | test.swift:793:15:793:15 | dict4 |
-| test.swift:792:15:792:35 | call to randomElement() | test.swift:792:15:792:36 | ...! |
-| test.swift:793:15:793:15 | [post] dict4 | test.swift:794:15:794:15 | dict4 |
-| test.swift:793:15:793:15 | dict4 | test.swift:794:15:794:15 | dict4 |
-| test.swift:793:15:793:35 | call to randomElement() | test.swift:793:15:793:36 | ...! |
-| test.swift:794:15:794:15 | [post] dict4 | test.swift:795:15:795:15 | dict4 |
-| test.swift:794:15:794:15 | dict4 | test.swift:795:15:795:15 | dict4 |
+| test.swift:784:15:784:15 | [post] dict3 | test.swift:785:15:785:15 | dict3 |
+| test.swift:784:15:784:15 | dict3 | test.swift:785:15:785:15 | dict3 |
+| test.swift:784:15:784:35 | call to randomElement() | test.swift:784:15:784:36 | ...! |
+| test.swift:785:15:785:15 | [post] dict3 | test.swift:787:25:787:25 | dict3 |
+| test.swift:785:15:785:15 | dict3 | test.swift:787:25:787:25 | dict3 |
+| test.swift:785:15:785:35 | call to randomElement() | test.swift:785:15:785:36 | ...! |
+| test.swift:787:10:787:10 | SSA def(key) | test.swift:788:19:788:19 | key |
+| test.swift:787:10:787:10 | key | test.swift:787:10:787:10 | SSA def(key) |
+| test.swift:787:15:787:15 | SSA def(value) | test.swift:789:19:789:19 | value |
+| test.swift:787:15:787:15 | value | test.swift:787:15:787:15 | SSA def(value) |
+| test.swift:792:9:792:9 | SSA def(dict4) | test.swift:793:15:793:15 | dict4 |
+| test.swift:792:9:792:9 | dict4 | test.swift:792:9:792:9 | SSA def(dict4) |
+| test.swift:792:17:792:28 | [...] | test.swift:792:9:792:9 | dict4 |
+| test.swift:793:15:793:15 | &... | test.swift:794:15:794:15 | dict4 |
+| test.swift:793:15:793:15 | [post] dict4 | test.swift:793:15:793:15 | &... |
+| test.swift:793:15:793:15 | dict4 | test.swift:793:15:793:15 | &... |
+| test.swift:793:15:793:52 | call to updateValue(_:forKey:) | test.swift:793:15:793:53 | ...! |
+| test.swift:794:15:794:15 | &... | test.swift:795:15:795:15 | dict4 |
+| test.swift:794:15:794:15 | [post] dict4 | test.swift:794:15:794:15 | &... |
+| test.swift:794:15:794:15 | dict4 | test.swift:794:15:794:15 | &... |
+| test.swift:794:15:794:52 | call to updateValue(_:forKey:) | test.swift:794:15:794:53 | ...! |
+| test.swift:795:15:795:15 | [post] dict4 | test.swift:796:15:796:15 | dict4 |
+| test.swift:795:15:795:15 | dict4 | test.swift:796:15:796:15 | dict4 |
+| test.swift:795:15:795:35 | call to randomElement() | test.swift:795:15:795:36 | ...! |
+| test.swift:796:15:796:15 | [post] dict4 | test.swift:797:15:797:15 | dict4 |
+| test.swift:796:15:796:15 | dict4 | test.swift:797:15:797:15 | dict4 |
+| test.swift:796:15:796:35 | call to randomElement() | test.swift:796:15:796:36 | ...! |
+| test.swift:797:15:797:15 | [post] dict4 | test.swift:798:15:798:15 | dict4 |
+| test.swift:797:15:797:15 | dict4 | test.swift:798:15:798:15 | dict4 |
diff --git a/swift/ql/test/library-tests/dataflow/dataflow/test.swift b/swift/ql/test/library-tests/dataflow/dataflow/test.swift
index 4b5d98a2e66..b1d6eae5e53 100644
--- a/swift/ql/test/library-tests/dataflow/dataflow/test.swift
+++ b/swift/ql/test/library-tests/dataflow/dataflow/test.swift
@@ -781,6 +781,9 @@ func testDictionary() {
dict3[source()] = 2
+ sink(arg: dict3.randomElement()!.0) // $ MISSING: flow=779
+ sink(arg: dict3.randomElement()!.1) // $ SPURIOUS: flow=779 MISSING: flow=782
+
for (key, value) in dict3 {
sink(arg: key) // $ MISSING: flow=782
sink(arg: value) // $ MISSING: flow=779
@@ -789,8 +792,8 @@ func testDictionary() {
var dict4 = [1:source()]
sink(arg: dict4.updateValue(1, forKey: source())!)
sink(arg: dict4.updateValue(source(), forKey: 2)!)
- sink(arg: dict4.randomElement()!.0) // $ flow=790
- sink(arg: dict4.randomElement()!.1) // $ flow=789 flow=791
- sink(arg: dict4.keys.randomElement()) // $ MISSING: flow=790
- sink(arg: dict4.values.randomElement()) // $ MISSING: flow=789 flow=791
+ sink(arg: dict4.randomElement()!.0) // $ flow=793
+ sink(arg: dict4.randomElement()!.1) // $ flow=792 flow=794
+ sink(arg: dict4.keys.randomElement()) // $ MISSING: flow=793
+ sink(arg: dict4.values.randomElement()) // $ MISSING: flow=792 flow=794
}
\ No newline at end of file
From 79368c187cb7dc0fc85ee6702363e2405ace529c Mon Sep 17 00:00:00 2001
From: Robert Marsh
Date: Tue, 15 Aug 2023 19:34:27 +0000
Subject: [PATCH 065/788] Swift: fixes around DictionaryContent
---
.../dataflow/internal/DataFlowPrivate.qll | 16 ++++--
.../frameworks/StandardLibrary/Array.qll | 2 +-
.../dataflow/dataflow/DataFlow.expected | 49 ++++++++++++++++---
.../dataflow/dataflow/test.swift | 8 +--
4 files changed, 59 insertions(+), 16 deletions(-)
diff --git a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll
index bdd8c528f07..998c0dd8627 100644
--- a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll
+++ b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll
@@ -747,24 +747,26 @@ predicate storeStep(Node node1, ContentSet c, Node node2) {
c.isSingleton(any(Content::ArrayContent ac))
)
or
- // read of a dictionary value via subscript operator, with intermediate step
+ // assignment to a dictionary value via subscript operator, with intermediate step
+ // `dict[key] = value`
exists(AssignExpr assign, SubscriptExpr subscript |
subscript = assign.getDest() and
(
subscript.getArgument(0).getExpr() = node1.asExpr() and
node2.(DictionarySubscriptNode).getExpr() = subscript and
- c.isSingleton(any(Content::TupleContent tc | tc.getIndex() = 1))
+ c.isSingleton(any(Content::TupleContent tc | tc.getIndex() = 0))
or
assign.getSource() = node1.asExpr() and
node2.(DictionarySubscriptNode).getExpr() = subscript and
c.isSingleton(any(Content::TupleContent tc | tc.getIndex() = 1))
or
- node1.(DictionarySubscriptNode) = node1 and
- node2.asExpr() = subscript and
+ node1.(DictionarySubscriptNode).getExpr() = subscript and
+ node2.(PostUpdateNode).getPreUpdateNode().asExpr() = subscript.getBase() and
c.isSingleton(any(Content::CollectionContent cc))
)
)
or
+ // creation of a dictionary `[key: value, ...]`
exists(DictionaryExpr dict |
node1.asExpr() = dict.getAnElement() and
node2.asExpr() = dict and
@@ -872,7 +874,11 @@ predicate readStep(Node node1, ContentSet c, Node node2) {
* in `x.f = newValue`.
*/
predicate clearsContent(Node n, ContentSet c) {
- n = any(PostUpdateNode pun | storeStep(_, c, pun)).getPreUpdateNode()
+ n = any(PostUpdateNode pun | storeStep(_, c, pun)).getPreUpdateNode() and
+ (
+ c.isSingleton(any(Content::FieldContent fc)) or
+ c.isSingleton(any(Content::TupleContent tc))
+ )
}
/**
diff --git a/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/Array.qll b/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/Array.qll
index 207d120e82e..8b7bb5c80e2 100644
--- a/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/Array.qll
+++ b/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/Array.qll
@@ -9,7 +9,7 @@ private import codeql.swift.dataflow.ExternalFlow
* An instance of the `Array` type.
*/
class ArrayType extends Type {
- ArrayType() { this.getName().matches("Array<%") or this.getName().matches("[%]") }
+ ArrayType() { this.getCanonicalType().getName().matches("Array<%") }
}
/**
diff --git a/swift/ql/test/library-tests/dataflow/dataflow/DataFlow.expected b/swift/ql/test/library-tests/dataflow/dataflow/DataFlow.expected
index b483b2b7099..8dea5ec3f62 100644
--- a/swift/ql/test/library-tests/dataflow/dataflow/DataFlow.expected
+++ b/swift/ql/test/library-tests/dataflow/dataflow/DataFlow.expected
@@ -404,25 +404,42 @@ edges
| test.swift:756:15:756:19 | .v2 [some:0] | test.swift:756:15:756:21 | ...! |
| test.swift:757:15:757:15 | mo1 [v3] | test.swift:732:9:732:9 | self [v3] |
| test.swift:757:15:757:15 | mo1 [v3] | test.swift:757:15:757:19 | .v3 |
-| test.swift:767:5:767:5 | [post] dict1 [Array element] | test.swift:769:15:769:15 | dict1 [Array element] |
-| test.swift:767:16:767:23 | call to source() | test.swift:767:5:767:5 | [post] dict1 [Array element] |
-| test.swift:769:15:769:15 | dict1 [Array element] | test.swift:769:15:769:22 | ...[...] |
+| test.swift:767:5:767:5 | [post] dict1 [Collection element, Tuple element at index 1] | test.swift:769:15:769:15 | dict1 [Collection element, Tuple element at index 1] |
+| test.swift:767:5:767:12 | DictionarySubscriptNode [Tuple element at index 1] | test.swift:767:5:767:5 | [post] dict1 [Collection element, Tuple element at index 1] |
+| test.swift:767:16:767:23 | call to source() | test.swift:767:5:767:12 | DictionarySubscriptNode [Tuple element at index 1] |
+| test.swift:769:15:769:15 | dict1 [Collection element, Tuple element at index 1] | test.swift:769:15:769:22 | DictionarySubscriptNode [Tuple element at index 1] |
+| test.swift:769:15:769:22 | DictionarySubscriptNode [Tuple element at index 1] | test.swift:769:15:769:22 | ...[...] |
| test.swift:779:17:779:29 | [...] [Collection element, Tuple element at index 1] | test.swift:780:15:780:15 | dict3 [Collection element, Tuple element at index 1] |
| test.swift:779:17:779:29 | [...] [Collection element, Tuple element at index 1] | test.swift:782:5:782:5 | dict3 [Collection element, Tuple element at index 1] |
+| test.swift:779:17:779:29 | [...] [Collection element, Tuple element at index 1] | test.swift:785:15:785:15 | dict3 [Collection element, Tuple element at index 1] |
| test.swift:779:18:779:28 | (...) [Tuple element at index 1] | test.swift:779:17:779:29 | [...] [Collection element, Tuple element at index 1] |
| test.swift:779:21:779:28 | call to source() | test.swift:779:18:779:28 | (...) [Tuple element at index 1] |
| test.swift:780:15:780:15 | dict3 [Collection element, Tuple element at index 1] | test.swift:780:15:780:22 | DictionarySubscriptNode [Tuple element at index 1] |
| test.swift:780:15:780:22 | DictionarySubscriptNode [Tuple element at index 1] | test.swift:780:15:780:22 | ...[...] |
-| test.swift:782:5:782:5 | dict3 [Collection element, Tuple element at index 1] | test.swift:785:15:785:15 | dict3 [Collection element, Tuple element at index 1] |
+| test.swift:782:5:782:5 | [post] dict3 [Collection element, Tuple element at index 0] | test.swift:784:15:784:15 | dict3 [Collection element, Tuple element at index 0] |
+| test.swift:782:5:782:5 | [post] dict3 [Collection element, Tuple element at index 1] | test.swift:785:15:785:15 | dict3 [Collection element, Tuple element at index 1] |
+| test.swift:782:5:782:5 | dict3 [Collection element, Tuple element at index 1] | test.swift:782:5:782:19 | DictionarySubscriptNode [Tuple element at index 1] |
+| test.swift:782:5:782:19 | DictionarySubscriptNode [Tuple element at index 0] | test.swift:782:5:782:5 | [post] dict3 [Collection element, Tuple element at index 0] |
+| test.swift:782:5:782:19 | DictionarySubscriptNode [Tuple element at index 1] | test.swift:782:5:782:5 | [post] dict3 [Collection element, Tuple element at index 1] |
+| test.swift:782:11:782:18 | call to source() | test.swift:782:5:782:19 | DictionarySubscriptNode [Tuple element at index 0] |
+| test.swift:784:15:784:15 | dict3 [Collection element, Tuple element at index 0] | test.swift:784:15:784:35 | call to randomElement() [some:0, Tuple element at index 0] |
+| test.swift:784:15:784:35 | call to randomElement() [some:0, Tuple element at index 0] | test.swift:784:15:784:36 | ...! [Tuple element at index 0] |
+| test.swift:784:15:784:36 | ...! [Tuple element at index 0] | test.swift:784:15:784:38 | .0 |
| test.swift:785:15:785:15 | dict3 [Collection element, Tuple element at index 1] | test.swift:785:15:785:35 | call to randomElement() [some:0, Tuple element at index 1] |
| test.swift:785:15:785:35 | call to randomElement() [some:0, Tuple element at index 1] | test.swift:785:15:785:36 | ...! [Tuple element at index 1] |
| test.swift:785:15:785:36 | ...! [Tuple element at index 1] | test.swift:785:15:785:38 | .1 |
+| test.swift:792:17:792:28 | [...] [Collection element, Tuple element at index 1] | test.swift:793:15:793:15 | dict4 [Collection element, Tuple element at index 1] |
+| test.swift:792:17:792:28 | [...] [Collection element, Tuple element at index 1] | test.swift:794:15:794:15 | dict4 [Collection element, Tuple element at index 1] |
| test.swift:792:17:792:28 | [...] [Collection element, Tuple element at index 1] | test.swift:796:15:796:15 | dict4 [Collection element, Tuple element at index 1] |
| test.swift:792:18:792:27 | (...) [Tuple element at index 1] | test.swift:792:17:792:28 | [...] [Collection element, Tuple element at index 1] |
| test.swift:792:20:792:27 | call to source() | test.swift:792:18:792:27 | (...) [Tuple element at index 1] |
| test.swift:793:15:793:15 | [post] dict4 [Collection element, Tuple element at index 0] | test.swift:795:15:795:15 | dict4 [Collection element, Tuple element at index 0] |
+| test.swift:793:15:793:15 | dict4 [Collection element, Tuple element at index 1] | test.swift:793:15:793:52 | call to updateValue(_:forKey:) [some:0] |
+| test.swift:793:15:793:52 | call to updateValue(_:forKey:) [some:0] | test.swift:793:15:793:53 | ...! |
| test.swift:793:44:793:51 | call to source() | test.swift:793:15:793:15 | [post] dict4 [Collection element, Tuple element at index 0] |
| test.swift:794:15:794:15 | [post] dict4 [Collection element, Tuple element at index 1] | test.swift:796:15:796:15 | dict4 [Collection element, Tuple element at index 1] |
+| test.swift:794:15:794:15 | dict4 [Collection element, Tuple element at index 1] | test.swift:794:15:794:52 | call to updateValue(_:forKey:) [some:0] |
+| test.swift:794:15:794:52 | call to updateValue(_:forKey:) [some:0] | test.swift:794:15:794:53 | ...! |
| test.swift:794:33:794:40 | call to source() | test.swift:794:15:794:15 | [post] dict4 [Collection element, Tuple element at index 1] |
| test.swift:795:15:795:15 | dict4 [Collection element, Tuple element at index 0] | test.swift:795:15:795:35 | call to randomElement() [some:0, Tuple element at index 0] |
| test.swift:795:15:795:35 | call to randomElement() [some:0, Tuple element at index 0] | test.swift:795:15:795:36 | ...! [Tuple element at index 0] |
@@ -875,17 +892,28 @@ nodes
| test.swift:756:15:756:21 | ...! | semmle.label | ...! |
| test.swift:757:15:757:15 | mo1 [v3] | semmle.label | mo1 [v3] |
| test.swift:757:15:757:19 | .v3 | semmle.label | .v3 |
-| test.swift:767:5:767:5 | [post] dict1 [Array element] | semmle.label | [post] dict1 [Array element] |
+| test.swift:767:5:767:5 | [post] dict1 [Collection element, Tuple element at index 1] | semmle.label | [post] dict1 [Collection element, Tuple element at index 1] |
+| test.swift:767:5:767:12 | DictionarySubscriptNode [Tuple element at index 1] | semmle.label | DictionarySubscriptNode [Tuple element at index 1] |
| test.swift:767:16:767:23 | call to source() | semmle.label | call to source() |
-| test.swift:769:15:769:15 | dict1 [Array element] | semmle.label | dict1 [Array element] |
+| test.swift:769:15:769:15 | dict1 [Collection element, Tuple element at index 1] | semmle.label | dict1 [Collection element, Tuple element at index 1] |
| test.swift:769:15:769:22 | ...[...] | semmle.label | ...[...] |
+| test.swift:769:15:769:22 | DictionarySubscriptNode [Tuple element at index 1] | semmle.label | DictionarySubscriptNode [Tuple element at index 1] |
| test.swift:779:17:779:29 | [...] [Collection element, Tuple element at index 1] | semmle.label | [...] [Collection element, Tuple element at index 1] |
| test.swift:779:18:779:28 | (...) [Tuple element at index 1] | semmle.label | (...) [Tuple element at index 1] |
| test.swift:779:21:779:28 | call to source() | semmle.label | call to source() |
| test.swift:780:15:780:15 | dict3 [Collection element, Tuple element at index 1] | semmle.label | dict3 [Collection element, Tuple element at index 1] |
| test.swift:780:15:780:22 | ...[...] | semmle.label | ...[...] |
| test.swift:780:15:780:22 | DictionarySubscriptNode [Tuple element at index 1] | semmle.label | DictionarySubscriptNode [Tuple element at index 1] |
+| test.swift:782:5:782:5 | [post] dict3 [Collection element, Tuple element at index 0] | semmle.label | [post] dict3 [Collection element, Tuple element at index 0] |
+| test.swift:782:5:782:5 | [post] dict3 [Collection element, Tuple element at index 1] | semmle.label | [post] dict3 [Collection element, Tuple element at index 1] |
| test.swift:782:5:782:5 | dict3 [Collection element, Tuple element at index 1] | semmle.label | dict3 [Collection element, Tuple element at index 1] |
+| test.swift:782:5:782:19 | DictionarySubscriptNode [Tuple element at index 0] | semmle.label | DictionarySubscriptNode [Tuple element at index 0] |
+| test.swift:782:5:782:19 | DictionarySubscriptNode [Tuple element at index 1] | semmle.label | DictionarySubscriptNode [Tuple element at index 1] |
+| test.swift:782:11:782:18 | call to source() | semmle.label | call to source() |
+| test.swift:784:15:784:15 | dict3 [Collection element, Tuple element at index 0] | semmle.label | dict3 [Collection element, Tuple element at index 0] |
+| test.swift:784:15:784:35 | call to randomElement() [some:0, Tuple element at index 0] | semmle.label | call to randomElement() [some:0, Tuple element at index 0] |
+| test.swift:784:15:784:36 | ...! [Tuple element at index 0] | semmle.label | ...! [Tuple element at index 0] |
+| test.swift:784:15:784:38 | .0 | semmle.label | .0 |
| test.swift:785:15:785:15 | dict3 [Collection element, Tuple element at index 1] | semmle.label | dict3 [Collection element, Tuple element at index 1] |
| test.swift:785:15:785:35 | call to randomElement() [some:0, Tuple element at index 1] | semmle.label | call to randomElement() [some:0, Tuple element at index 1] |
| test.swift:785:15:785:36 | ...! [Tuple element at index 1] | semmle.label | ...! [Tuple element at index 1] |
@@ -894,8 +922,14 @@ nodes
| test.swift:792:18:792:27 | (...) [Tuple element at index 1] | semmle.label | (...) [Tuple element at index 1] |
| test.swift:792:20:792:27 | call to source() | semmle.label | call to source() |
| test.swift:793:15:793:15 | [post] dict4 [Collection element, Tuple element at index 0] | semmle.label | [post] dict4 [Collection element, Tuple element at index 0] |
+| test.swift:793:15:793:15 | dict4 [Collection element, Tuple element at index 1] | semmle.label | dict4 [Collection element, Tuple element at index 1] |
+| test.swift:793:15:793:52 | call to updateValue(_:forKey:) [some:0] | semmle.label | call to updateValue(_:forKey:) [some:0] |
+| test.swift:793:15:793:53 | ...! | semmle.label | ...! |
| test.swift:793:44:793:51 | call to source() | semmle.label | call to source() |
| test.swift:794:15:794:15 | [post] dict4 [Collection element, Tuple element at index 1] | semmle.label | [post] dict4 [Collection element, Tuple element at index 1] |
+| test.swift:794:15:794:15 | dict4 [Collection element, Tuple element at index 1] | semmle.label | dict4 [Collection element, Tuple element at index 1] |
+| test.swift:794:15:794:52 | call to updateValue(_:forKey:) [some:0] | semmle.label | call to updateValue(_:forKey:) [some:0] |
+| test.swift:794:15:794:53 | ...! | semmle.label | ...! |
| test.swift:794:33:794:40 | call to source() | semmle.label | call to source() |
| test.swift:795:15:795:15 | dict4 [Collection element, Tuple element at index 0] | semmle.label | dict4 [Collection element, Tuple element at index 0] |
| test.swift:795:15:795:35 | call to randomElement() [some:0, Tuple element at index 0] | semmle.label | call to randomElement() [some:0, Tuple element at index 0] |
@@ -1054,7 +1088,10 @@ subpaths
| test.swift:757:15:757:19 | .v3 | test.swift:747:14:747:21 | call to source() | test.swift:757:15:757:19 | .v3 | result |
| test.swift:769:15:769:22 | ...[...] | test.swift:767:16:767:23 | call to source() | test.swift:769:15:769:22 | ...[...] | result |
| test.swift:780:15:780:22 | ...[...] | test.swift:779:21:779:28 | call to source() | test.swift:780:15:780:22 | ...[...] | result |
+| test.swift:784:15:784:38 | .0 | test.swift:782:11:782:18 | call to source() | test.swift:784:15:784:38 | .0 | result |
| test.swift:785:15:785:38 | .1 | test.swift:779:21:779:28 | call to source() | test.swift:785:15:785:38 | .1 | result |
+| test.swift:793:15:793:53 | ...! | test.swift:792:20:792:27 | call to source() | test.swift:793:15:793:53 | ...! | result |
+| test.swift:794:15:794:53 | ...! | test.swift:792:20:792:27 | call to source() | test.swift:794:15:794:53 | ...! | result |
| test.swift:795:15:795:38 | .0 | test.swift:793:44:793:51 | call to source() | test.swift:795:15:795:38 | .0 | result |
| test.swift:796:15:796:38 | .1 | test.swift:792:20:792:27 | call to source() | test.swift:796:15:796:38 | .1 | result |
| test.swift:796:15:796:38 | .1 | test.swift:794:33:794:40 | call to source() | test.swift:796:15:796:38 | .1 | result |
diff --git a/swift/ql/test/library-tests/dataflow/dataflow/test.swift b/swift/ql/test/library-tests/dataflow/dataflow/test.swift
index b1d6eae5e53..46087bdbb2c 100644
--- a/swift/ql/test/library-tests/dataflow/dataflow/test.swift
+++ b/swift/ql/test/library-tests/dataflow/dataflow/test.swift
@@ -781,8 +781,8 @@ func testDictionary() {
dict3[source()] = 2
- sink(arg: dict3.randomElement()!.0) // $ MISSING: flow=779
- sink(arg: dict3.randomElement()!.1) // $ SPURIOUS: flow=779 MISSING: flow=782
+ sink(arg: dict3.randomElement()!.0) // $ flow=782
+ sink(arg: dict3.randomElement()!.1) // $ flow=779
for (key, value) in dict3 {
sink(arg: key) // $ MISSING: flow=782
@@ -790,8 +790,8 @@ func testDictionary() {
}
var dict4 = [1:source()]
- sink(arg: dict4.updateValue(1, forKey: source())!)
- sink(arg: dict4.updateValue(source(), forKey: 2)!)
+ sink(arg: dict4.updateValue(1, forKey: source())!) // $ flow=792
+ sink(arg: dict4.updateValue(source(), forKey: 2)!) // $ SPURIOUS: flow=792
sink(arg: dict4.randomElement()!.0) // $ flow=793
sink(arg: dict4.randomElement()!.1) // $ flow=792 flow=794
sink(arg: dict4.keys.randomElement()) // $ MISSING: flow=793
From b4595d8b9289347fa5d08656d8c03332253b1294 Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Tue, 15 Aug 2023 13:23:19 +0100
Subject: [PATCH 066/788] Swift: Model getVaList, correct NSLogv sink for
swift/cleartext-logging.
---
.../swift/frameworks/StandardLibrary/CInterop.qll | 12 ++++++++++++
.../frameworks/StandardLibrary/StandardLibrary.qll | 1 +
.../swift/security/CleartextLoggingExtensions.qll | 2 +-
.../Security/CWE-312/cleartextLoggingTest.swift | 4 ++--
4 files changed, 16 insertions(+), 3 deletions(-)
create mode 100644 swift/ql/lib/codeql/swift/frameworks/StandardLibrary/CInterop.qll
diff --git a/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/CInterop.qll b/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/CInterop.qll
new file mode 100644
index 00000000000..ac7d5c5b67e
--- /dev/null
+++ b/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/CInterop.qll
@@ -0,0 +1,12 @@
+/**
+ * Provides models for Swift "C Interoperability" functions.
+ */
+
+import swift
+private import codeql.swift.dataflow.ExternalFlow
+
+private class CInteropSummaries extends SummaryModelCsv {
+ override predicate row(string row) {
+ row = ";;false;getVaList(_:);;;Argument[0].ArrayElement;ReturnValue;value"
+ }
+}
diff --git a/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/StandardLibrary.qll b/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/StandardLibrary.qll
index 93d60dba092..9d29277bc11 100644
--- a/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/StandardLibrary.qll
+++ b/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/StandardLibrary.qll
@@ -3,6 +3,7 @@
*/
private import Array
+private import CInterop
private import Collection
private import CustomUrlSchemes
private import Data
diff --git a/swift/ql/lib/codeql/swift/security/CleartextLoggingExtensions.qll b/swift/ql/lib/codeql/swift/security/CleartextLoggingExtensions.qll
index 21bf855d1fc..a38fdbafbdd 100644
--- a/swift/ql/lib/codeql/swift/security/CleartextLoggingExtensions.qll
+++ b/swift/ql/lib/codeql/swift/security/CleartextLoggingExtensions.qll
@@ -94,7 +94,7 @@ private class LoggingSinks extends SinkModelCsv {
";;false;NSLog(_:_:);;;Argument[0];log-injection",
";;false;NSLog(_:_:);;;Argument[1].ArrayElement;log-injection",
";;false;NSLogv(_:_:);;;Argument[0];log-injection",
- ";;false;NSLogv(_:_:);;;Argument[1].ArrayElement;log-injection",
+ ";;false;NSLogv(_:_:);;;Argument[1];log-injection",
";;false;vfprintf(_:_:_:);;;Agument[1..2];log-injection",
";Logger;true;log(_:);;;Argument[0];log-injection",
";Logger;true;log(level:_:);;;Argument[1];log-injection",
diff --git a/swift/ql/test/query-tests/Security/CWE-312/cleartextLoggingTest.swift b/swift/ql/test/query-tests/Security/CWE-312/cleartextLoggingTest.swift
index 8f8cd40c7cf..e1dd1a890cb 100644
--- a/swift/ql/test/query-tests/Security/CWE-312/cleartextLoggingTest.swift
+++ b/swift/ql/test/query-tests/Security/CWE-312/cleartextLoggingTest.swift
@@ -96,8 +96,8 @@ func test1(password: String, passwordHash : String, passphrase: String, pass_phr
NSLog("%@", password as! CVarArg) // $ MISSING: hasCleartextLogging=96
NSLog("%@ %@", "" as! CVarArg, password as! CVarArg) // $ MISSING: hasCleartextLogging=97
NSLog("\(password)") // $ hasCleartextLogging=98
- NSLogv("%@", getVaList([password as! CVarArg])) // $ MISSING: hasCleartextLogging=99
- NSLogv("%@ %@", getVaList(["" as! CVarArg, password as! CVarArg])) // $ MISSING: hasCleartextLogging=100
+ NSLogv("%@", getVaList([password as! CVarArg])) // $ hasCleartextLogging=99
+ NSLogv("%@ %@", getVaList(["" as! CVarArg, password as! CVarArg])) // $ hasCleartextLogging=100
NSLog(passwordHash) // SAfe
NSLogv("%@", getVaList([passwordHash as! CVarArg])) // Safe
From 3fe8655b6ecfe5f759bf0f449c996fa04b9e2ff8 Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Tue, 15 Aug 2023 17:57:54 +0100
Subject: [PATCH 067/788] Swift: Test data flow through varargs.
---
.../dataflow/dataflow/DataFlow.expected | 6 ++++
.../dataflow/dataflow/LocalFlow.expected | 26 +++++++++++++++
.../dataflow/dataflow/test.swift | 32 +++++++++++++++++++
3 files changed, 64 insertions(+)
diff --git a/swift/ql/test/library-tests/dataflow/dataflow/DataFlow.expected b/swift/ql/test/library-tests/dataflow/dataflow/DataFlow.expected
index c638ea8e344..25dcaf0c574 100644
--- a/swift/ql/test/library-tests/dataflow/dataflow/DataFlow.expected
+++ b/swift/ql/test/library-tests/dataflow/dataflow/DataFlow.expected
@@ -404,6 +404,8 @@ edges
| test.swift:756:15:756:19 | .v2 [some:0] | test.swift:756:15:756:21 | ...! |
| test.swift:757:15:757:15 | mo1 [v3] | test.swift:732:9:732:9 | self [v3] |
| test.swift:757:15:757:15 | mo1 [v3] | test.swift:757:15:757:19 | .v3 |
+| test.swift:768:19:768:24 | v | test.swift:769:15:769:15 | v |
+| test.swift:791:18:791:25 | call to source() | test.swift:768:19:768:24 | v |
nodes
| file://:0:0:0:0 | .a [x] | semmle.label | .a [x] |
| file://:0:0:0:0 | .str | semmle.label | .str |
@@ -849,6 +851,9 @@ nodes
| test.swift:756:15:756:21 | ...! | semmle.label | ...! |
| test.swift:757:15:757:15 | mo1 [v3] | semmle.label | mo1 [v3] |
| test.swift:757:15:757:19 | .v3 | semmle.label | .v3 |
+| test.swift:768:19:768:24 | v | semmle.label | v |
+| test.swift:769:15:769:15 | v | semmle.label | v |
+| test.swift:791:18:791:25 | call to source() | semmle.label | call to source() |
subpaths
| test.swift:75:22:75:22 | x | test.swift:65:16:65:28 | arg1 | test.swift:65:1:70:1 | arg2[return] | test.swift:75:32:75:32 | [post] y |
| test.swift:114:19:114:19 | arg | test.swift:109:9:109:14 | arg | test.swift:110:12:110:12 | arg | test.swift:114:12:114:22 | call to ... |
@@ -996,3 +1001,4 @@ subpaths
| test.swift:754:15:754:15 | v3 | test.swift:744:10:744:17 | call to source() | test.swift:754:15:754:15 | v3 | result |
| test.swift:756:15:756:21 | ...! | test.swift:746:14:746:21 | call to source() | test.swift:756:15:756:21 | ...! | result |
| test.swift:757:15:757:19 | .v3 | test.swift:747:14:747:21 | call to source() | test.swift:757:15:757:19 | .v3 | result |
+| test.swift:769:15:769:15 | v | test.swift:791:18:791:25 | call to source() | test.swift:769:15:769:15 | v | result |
diff --git a/swift/ql/test/library-tests/dataflow/dataflow/LocalFlow.expected b/swift/ql/test/library-tests/dataflow/dataflow/LocalFlow.expected
index 18e5d25010d..f48269b333e 100644
--- a/swift/ql/test/library-tests/dataflow/dataflow/LocalFlow.expected
+++ b/swift/ql/test/library-tests/dataflow/dataflow/LocalFlow.expected
@@ -913,3 +913,29 @@
| test.swift:759:15:759:15 | mo2 | test.swift:760:15:760:15 | mo2 |
| test.swift:759:15:759:20 | .v2 | test.swift:759:15:759:22 | ...! |
| test.swift:760:15:760:15 | mo2 | test.swift:760:15:760:18 | ...! |
+| test.swift:763:19:763:28 | SSA def(args) | test.swift:764:15:764:15 | args |
+| test.swift:763:19:763:28 | args | test.swift:763:19:763:28 | SSA def(args) |
+| test.swift:764:15:764:15 | args | test.swift:765:15:765:15 | args |
+| test.swift:768:19:768:24 | SSA def(v) | test.swift:769:15:769:15 | v |
+| test.swift:768:19:768:24 | v | test.swift:768:19:768:24 | SSA def(v) |
+| test.swift:768:29:768:40 | SSA def(args) | test.swift:770:15:770:15 | args |
+| test.swift:768:29:768:40 | args | test.swift:768:29:768:40 | SSA def(args) |
+| test.swift:770:15:770:15 | args | test.swift:771:15:771:15 | args |
+| test.swift:771:15:771:15 | [post] args | test.swift:772:15:772:15 | args |
+| test.swift:771:15:771:15 | args | test.swift:772:15:772:15 | args |
+| test.swift:775:19:775:24 | SSA def(v) | test.swift:776:15:776:15 | v |
+| test.swift:775:19:775:24 | v | test.swift:775:19:775:24 | SSA def(v) |
+| test.swift:775:29:775:40 | SSA def(args) | test.swift:777:15:777:15 | args |
+| test.swift:775:29:775:40 | args | test.swift:775:29:775:40 | SSA def(args) |
+| test.swift:777:15:777:15 | args | test.swift:778:15:778:15 | args |
+| test.swift:778:15:778:15 | [post] args | test.swift:779:15:779:15 | args |
+| test.swift:778:15:778:15 | args | test.swift:779:15:779:15 | args |
+| test.swift:779:15:779:15 | [post] args | test.swift:781:16:781:16 | args |
+| test.swift:779:15:779:15 | args | test.swift:781:16:781:16 | args |
+| test.swift:781:9:781:9 | SSA def(arg) | test.swift:782:19:782:19 | arg |
+| test.swift:781:9:781:9 | arg | test.swift:781:9:781:9 | SSA def(arg) |
+| test.swift:781:16:781:16 | args | test.swift:786:15:786:15 | args |
+| test.swift:785:9:785:9 | SSA def(myKeyPath) | test.swift:786:29:786:29 | myKeyPath |
+| test.swift:785:9:785:9 | myKeyPath | test.swift:785:9:785:9 | SSA def(myKeyPath) |
+| test.swift:785:21:785:29 | #keyPath(...) | test.swift:785:9:785:9 | myKeyPath |
+| test.swift:785:21:785:29 | enter #keyPath(...) | test.swift:785:27:785:29 | KeyPathComponent |
diff --git a/swift/ql/test/library-tests/dataflow/dataflow/test.swift b/swift/ql/test/library-tests/dataflow/dataflow/test.swift
index 44001572dbd..38e48a53615 100644
--- a/swift/ql/test/library-tests/dataflow/dataflow/test.swift
+++ b/swift/ql/test/library-tests/dataflow/dataflow/test.swift
@@ -759,3 +759,35 @@ func testWriteOptional() {
sink(arg: mo2!.v2!) // $ MISSING:flow=749
sink(arg: mo2!.v3) // $ MISSING:flow=750
}
+
+func testVarargs1(args: Int...) {
+ sink(arg: args)
+ sink(arg: args[0]) // $ MISSING: flow=790
+}
+
+func testVarargs2(_ v: Int, _ args: Int...) {
+ sink(arg: v) // $ flow=791
+ sink(arg: args)
+ sink(arg: args[0])
+ sink(arg: args[1])
+}
+
+func testVarargs3(_ v: Int, _ args: Int...) {
+ sink(arg: v)
+ sink(arg: args)
+ sink(arg: args[0])
+ sink(arg: args[1]) // $ MISSING: flow=792
+
+ for arg in args {
+ sink(arg: arg) // $ MISSING: flow=792
+ }
+
+ let myKeyPath = \[Int][1]
+ sink(arg: args[keyPath: myKeyPath]) // $ MISSING: flow=792
+}
+
+func testVarargsCaller() {
+ testVarargs1(args: source())
+ testVarargs2(source(), 2, 3)
+ testVarargs3(1, 2, source())
+}
From 269f0c6cb1d9052f9c88535fe63762dff08737de Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Tue, 15 Aug 2023 18:18:22 +0100
Subject: [PATCH 068/788] Swift: Flow through varargs.
---
.../dataflow/internal/DataFlowPrivate.qll | 10 ++++-
.../dataflow/dataflow/DataFlow.expected | 41 +++++++++++++++++++
.../dataflow/dataflow/LocalFlow.expected | 3 ++
.../dataflow/dataflow/test.swift | 8 ++--
4 files changed, 56 insertions(+), 6 deletions(-)
diff --git a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll
index 145ac20573b..09e76d02e32 100644
--- a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll
+++ b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll
@@ -190,6 +190,9 @@ private module Cached {
// flow through unary `+` (which does nothing)
nodeFrom.asExpr() = nodeTo.asExpr().(UnaryPlusExpr).getOperand()
or
+ // flow through varargs expansions (that wrap an `ArrayExpr` where varargs enter a call)
+ nodeFrom.asExpr() = nodeTo.asExpr().(VarargExpansionExpr).getSubExpr()
+ or
// flow through nil-coalescing operator `??`
exists(BinaryExpr nco |
nco.getOperator().(FreeFunction).getName() = "??(_:_:)" and
@@ -799,11 +802,14 @@ predicate readStep(Node node1, ContentSet c, Node node2) {
node2.(KeyPathReturnNodeImpl).getKeyPathExpr() = component.getKeyPathExpr()
)
or
- // read of an array member via subscript operator
+ // read of an array or variadic sequence type member via subscript operator
exists(SubscriptExpr subscript |
subscript.getBase() = node1.asExpr() and
subscript = node2.asExpr() and
- subscript.getBase().getType() instanceof ArrayType and
+ (
+ subscript.getBase().getType() instanceof ArrayType or
+ subscript.getBase().getType() instanceof VariadicSequenceType
+ ) and
c.isSingleton(any(Content::ArrayContent ac))
)
or
diff --git a/swift/ql/test/library-tests/dataflow/dataflow/DataFlow.expected b/swift/ql/test/library-tests/dataflow/dataflow/DataFlow.expected
index 25dcaf0c574..cb19ac2df30 100644
--- a/swift/ql/test/library-tests/dataflow/dataflow/DataFlow.expected
+++ b/swift/ql/test/library-tests/dataflow/dataflow/DataFlow.expected
@@ -404,8 +404,25 @@ edges
| test.swift:756:15:756:19 | .v2 [some:0] | test.swift:756:15:756:21 | ...! |
| test.swift:757:15:757:15 | mo1 [v3] | test.swift:732:9:732:9 | self [v3] |
| test.swift:757:15:757:15 | mo1 [v3] | test.swift:757:15:757:19 | .v3 |
+| test.swift:763:19:763:28 | args [Array element] | test.swift:765:15:765:15 | args [Array element] |
+| test.swift:765:15:765:15 | args [Array element] | test.swift:765:15:765:21 | ...[...] |
| test.swift:768:19:768:24 | v | test.swift:769:15:769:15 | v |
+| test.swift:775:29:775:40 | args [Array element] | test.swift:778:15:778:15 | args [Array element] |
+| test.swift:775:29:775:40 | args [Array element] | test.swift:779:15:779:15 | args [Array element] |
+| test.swift:775:29:775:40 | args [Array element] | test.swift:786:15:786:15 | args [Array element] |
+| test.swift:778:15:778:15 | args [Array element] | test.swift:778:15:778:21 | ...[...] |
+| test.swift:779:15:779:15 | args [Array element] | test.swift:779:15:779:21 | ...[...] |
+| test.swift:785:21:785:29 | enter #keyPath(...) [Array element] | test.swift:785:27:785:29 | KeyPathComponent [Array element] |
+| test.swift:785:27:785:29 | KeyPathComponent [Array element] | test.swift:785:21:785:29 | exit #keyPath(...) |
+| test.swift:786:15:786:15 | args [Array element] | test.swift:785:21:785:29 | enter #keyPath(...) [Array element] |
+| test.swift:786:15:786:15 | args [Array element] | test.swift:786:15:786:38 | \\...[...] |
+| test.swift:790:24:790:31 | [...] [Array element] | test.swift:763:19:763:28 | args [Array element] |
+| test.swift:790:24:790:31 | [...] [Array element] | test.swift:790:24:790:31 | [...] [Array element] |
+| test.swift:790:24:790:31 | call to source() | test.swift:790:24:790:31 | [...] [Array element] |
| test.swift:791:18:791:25 | call to source() | test.swift:768:19:768:24 | v |
+| test.swift:792:21:792:31 | [...] [Array element] | test.swift:775:29:775:40 | args [Array element] |
+| test.swift:792:21:792:31 | [...] [Array element] | test.swift:792:21:792:31 | [...] [Array element] |
+| test.swift:792:24:792:31 | call to source() | test.swift:792:21:792:31 | [...] [Array element] |
nodes
| file://:0:0:0:0 | .a [x] | semmle.label | .a [x] |
| file://:0:0:0:0 | .str | semmle.label | .str |
@@ -851,9 +868,28 @@ nodes
| test.swift:756:15:756:21 | ...! | semmle.label | ...! |
| test.swift:757:15:757:15 | mo1 [v3] | semmle.label | mo1 [v3] |
| test.swift:757:15:757:19 | .v3 | semmle.label | .v3 |
+| test.swift:763:19:763:28 | args [Array element] | semmle.label | args [Array element] |
+| test.swift:765:15:765:15 | args [Array element] | semmle.label | args [Array element] |
+| test.swift:765:15:765:21 | ...[...] | semmle.label | ...[...] |
| test.swift:768:19:768:24 | v | semmle.label | v |
| test.swift:769:15:769:15 | v | semmle.label | v |
+| test.swift:775:29:775:40 | args [Array element] | semmle.label | args [Array element] |
+| test.swift:778:15:778:15 | args [Array element] | semmle.label | args [Array element] |
+| test.swift:778:15:778:21 | ...[...] | semmle.label | ...[...] |
+| test.swift:779:15:779:15 | args [Array element] | semmle.label | args [Array element] |
+| test.swift:779:15:779:21 | ...[...] | semmle.label | ...[...] |
+| test.swift:785:21:785:29 | enter #keyPath(...) [Array element] | semmle.label | enter #keyPath(...) [Array element] |
+| test.swift:785:21:785:29 | exit #keyPath(...) | semmle.label | exit #keyPath(...) |
+| test.swift:785:27:785:29 | KeyPathComponent [Array element] | semmle.label | KeyPathComponent [Array element] |
+| test.swift:786:15:786:15 | args [Array element] | semmle.label | args [Array element] |
+| test.swift:786:15:786:38 | \\...[...] | semmle.label | \\...[...] |
+| test.swift:790:24:790:31 | [...] [Array element] | semmle.label | [...] [Array element] |
+| test.swift:790:24:790:31 | [...] [Array element] | semmle.label | [...] [Array element] |
+| test.swift:790:24:790:31 | call to source() | semmle.label | call to source() |
| test.swift:791:18:791:25 | call to source() | semmle.label | call to source() |
+| test.swift:792:21:792:31 | [...] [Array element] | semmle.label | [...] [Array element] |
+| test.swift:792:21:792:31 | [...] [Array element] | semmle.label | [...] [Array element] |
+| test.swift:792:24:792:31 | call to source() | semmle.label | call to source() |
subpaths
| test.swift:75:22:75:22 | x | test.swift:65:16:65:28 | arg1 | test.swift:65:1:70:1 | arg2[return] | test.swift:75:32:75:32 | [post] y |
| test.swift:114:19:114:19 | arg | test.swift:109:9:109:14 | arg | test.swift:110:12:110:12 | arg | test.swift:114:12:114:22 | call to ... |
@@ -902,6 +938,7 @@ subpaths
| test.swift:756:15:756:15 | mo1 [v2, some:0] | test.swift:731:9:731:9 | self [v2, some:0] | file://:0:0:0:0 | .v2 [some:0] | test.swift:756:15:756:19 | .v2 [some:0] |
| test.swift:756:15:756:15 | mo1 [v2] | test.swift:731:9:731:9 | self [v2] | file://:0:0:0:0 | .v2 | test.swift:756:15:756:19 | .v2 |
| test.swift:757:15:757:15 | mo1 [v3] | test.swift:732:9:732:9 | self [v3] | file://:0:0:0:0 | .v3 | test.swift:757:15:757:19 | .v3 |
+| test.swift:786:15:786:15 | args [Array element] | test.swift:785:21:785:29 | enter #keyPath(...) [Array element] | test.swift:785:21:785:29 | exit #keyPath(...) | test.swift:786:15:786:38 | \\...[...] |
#select
| test.swift:7:15:7:15 | t1 | test.swift:6:19:6:26 | call to source() | test.swift:7:15:7:15 | t1 | result |
| test.swift:9:15:9:15 | t1 | test.swift:6:19:6:26 | call to source() | test.swift:9:15:9:15 | t1 | result |
@@ -1001,4 +1038,8 @@ subpaths
| test.swift:754:15:754:15 | v3 | test.swift:744:10:744:17 | call to source() | test.swift:754:15:754:15 | v3 | result |
| test.swift:756:15:756:21 | ...! | test.swift:746:14:746:21 | call to source() | test.swift:756:15:756:21 | ...! | result |
| test.swift:757:15:757:19 | .v3 | test.swift:747:14:747:21 | call to source() | test.swift:757:15:757:19 | .v3 | result |
+| test.swift:765:15:765:21 | ...[...] | test.swift:790:24:790:31 | call to source() | test.swift:765:15:765:21 | ...[...] | result |
| test.swift:769:15:769:15 | v | test.swift:791:18:791:25 | call to source() | test.swift:769:15:769:15 | v | result |
+| test.swift:778:15:778:21 | ...[...] | test.swift:792:24:792:31 | call to source() | test.swift:778:15:778:21 | ...[...] | result |
+| test.swift:779:15:779:21 | ...[...] | test.swift:792:24:792:31 | call to source() | test.swift:779:15:779:21 | ...[...] | result |
+| test.swift:786:15:786:38 | \\...[...] | test.swift:792:24:792:31 | call to source() | test.swift:786:15:786:38 | \\...[...] | result |
diff --git a/swift/ql/test/library-tests/dataflow/dataflow/LocalFlow.expected b/swift/ql/test/library-tests/dataflow/dataflow/LocalFlow.expected
index f48269b333e..c7773e3313b 100644
--- a/swift/ql/test/library-tests/dataflow/dataflow/LocalFlow.expected
+++ b/swift/ql/test/library-tests/dataflow/dataflow/LocalFlow.expected
@@ -939,3 +939,6 @@
| test.swift:785:9:785:9 | myKeyPath | test.swift:785:9:785:9 | SSA def(myKeyPath) |
| test.swift:785:21:785:29 | #keyPath(...) | test.swift:785:9:785:9 | myKeyPath |
| test.swift:785:21:785:29 | enter #keyPath(...) | test.swift:785:27:785:29 | KeyPathComponent |
+| test.swift:790:24:790:31 | [...] | test.swift:790:24:790:31 | [...] |
+| test.swift:791:28:791:31 | [...] | test.swift:791:28:791:31 | [...] |
+| test.swift:792:21:792:31 | [...] | test.swift:792:21:792:31 | [...] |
diff --git a/swift/ql/test/library-tests/dataflow/dataflow/test.swift b/swift/ql/test/library-tests/dataflow/dataflow/test.swift
index 38e48a53615..55ec0207a81 100644
--- a/swift/ql/test/library-tests/dataflow/dataflow/test.swift
+++ b/swift/ql/test/library-tests/dataflow/dataflow/test.swift
@@ -762,7 +762,7 @@ func testWriteOptional() {
func testVarargs1(args: Int...) {
sink(arg: args)
- sink(arg: args[0]) // $ MISSING: flow=790
+ sink(arg: args[0]) // $ flow=790
}
func testVarargs2(_ v: Int, _ args: Int...) {
@@ -775,15 +775,15 @@ func testVarargs2(_ v: Int, _ args: Int...) {
func testVarargs3(_ v: Int, _ args: Int...) {
sink(arg: v)
sink(arg: args)
- sink(arg: args[0])
- sink(arg: args[1]) // $ MISSING: flow=792
+ sink(arg: args[0]) // $ SPURIOUS: flow=792
+ sink(arg: args[1]) // $ flow=792
for arg in args {
sink(arg: arg) // $ MISSING: flow=792
}
let myKeyPath = \[Int][1]
- sink(arg: args[keyPath: myKeyPath]) // $ MISSING: flow=792
+ sink(arg: args[keyPath: myKeyPath]) // $ flow=792
}
func testVarargsCaller() {
From 8f2e2a615517b6fae13f0939decb9fa4979c4025 Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Tue, 15 Aug 2023 18:26:48 +0100
Subject: [PATCH 069/788] Swift: Fix array content sinks for
swift/cleartext-logging.
---
.../swift/security/CleartextLoggingExtensions.qll | 12 ++++--------
.../codeql/swift/security/CleartextLoggingQuery.qll | 6 ++++++
.../Security/CWE-312/cleartextLoggingTest.swift | 10 +++++-----
3 files changed, 15 insertions(+), 13 deletions(-)
diff --git a/swift/ql/lib/codeql/swift/security/CleartextLoggingExtensions.qll b/swift/ql/lib/codeql/swift/security/CleartextLoggingExtensions.qll
index a38fdbafbdd..77e4079a0ca 100644
--- a/swift/ql/lib/codeql/swift/security/CleartextLoggingExtensions.qll
+++ b/swift/ql/lib/codeql/swift/security/CleartextLoggingExtensions.qll
@@ -87,14 +87,10 @@ private class LoggingSinks extends SinkModelCsv {
override predicate row(string row) {
row =
[
- ";;false;print(_:separator:terminator:);;;Argument[0].ArrayElement;log-injection",
- ";;false;print(_:separator:terminator:);;;Argument[1..2];log-injection",
- ";;false;print(_:separator:terminator:toStream:);;;Argument[0].ArrayElement;log-injection",
- ";;false;print(_:separator:terminator:toStream:);;;Argument[1..2];log-injection",
- ";;false;NSLog(_:_:);;;Argument[0];log-injection",
- ";;false;NSLog(_:_:);;;Argument[1].ArrayElement;log-injection",
- ";;false;NSLogv(_:_:);;;Argument[0];log-injection",
- ";;false;NSLogv(_:_:);;;Argument[1];log-injection",
+ ";;false;print(_:separator:terminator:);;;Argument[0..2];log-injection",
+ ";;false;print(_:separator:terminator:toStream:);;;Argument[0..2];log-injection",
+ ";;false;NSLog(_:_:);;;Argument[0..1];log-injection",
+ ";;false;NSLogv(_:_:);;;Argument[0..1];log-injection",
";;false;vfprintf(_:_:_:);;;Agument[1..2];log-injection",
";Logger;true;log(_:);;;Argument[0];log-injection",
";Logger;true;log(level:_:);;;Argument[1];log-injection",
diff --git a/swift/ql/lib/codeql/swift/security/CleartextLoggingQuery.qll b/swift/ql/lib/codeql/swift/security/CleartextLoggingQuery.qll
index 740fccefe97..08fed61c7d9 100644
--- a/swift/ql/lib/codeql/swift/security/CleartextLoggingQuery.qll
+++ b/swift/ql/lib/codeql/swift/security/CleartextLoggingQuery.qll
@@ -25,6 +25,12 @@ module CleartextLoggingConfig implements DataFlow::ConfigSig {
predicate isAdditionalFlowStep(DataFlow::Node n1, DataFlow::Node n2) {
any(CleartextLoggingAdditionalFlowStep s).step(n1, n2)
}
+
+ predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet c) {
+ // flow out from array content at the sink.
+ isSink(node) and
+ c.getAReadContent() instanceof DataFlow::Content::ArrayContent
+ }
}
/**
diff --git a/swift/ql/test/query-tests/Security/CWE-312/cleartextLoggingTest.swift b/swift/ql/test/query-tests/Security/CWE-312/cleartextLoggingTest.swift
index e1dd1a890cb..4c4a6baf551 100644
--- a/swift/ql/test/query-tests/Security/CWE-312/cleartextLoggingTest.swift
+++ b/swift/ql/test/query-tests/Security/CWE-312/cleartextLoggingTest.swift
@@ -84,17 +84,17 @@ struct Logger {
// --- tests ---
func test1(password: String, passwordHash : String, passphrase: String, pass_phrase: String) {
- print(password) // $ MISSING: hasCleartextLogging=87
- print(password, separator: "") // $ MISSING: $ hasCleartextLogging=88
+ print(password) // $ hasCleartextLogging=87
+ print(password, separator: "") // $ $ hasCleartextLogging=88
print("", separator: password) // $ hasCleartextLogging=89
- print(password, separator: "", terminator: "") // $ MISSING: hasCleartextLogging=90
+ print(password, separator: "", terminator: "") // $ hasCleartextLogging=90
print("", separator: password, terminator: "") // $ hasCleartextLogging=91
print("", separator: "", terminator: password) // $ hasCleartextLogging=92
print(passwordHash) // Safe
NSLog(password) // $ hasCleartextLogging=95
- NSLog("%@", password as! CVarArg) // $ MISSING: hasCleartextLogging=96
- NSLog("%@ %@", "" as! CVarArg, password as! CVarArg) // $ MISSING: hasCleartextLogging=97
+ NSLog("%@", password as! CVarArg) // $ hasCleartextLogging=96
+ NSLog("%@ %@", "" as! CVarArg, password as! CVarArg) // $ hasCleartextLogging=97
NSLog("\(password)") // $ hasCleartextLogging=98
NSLogv("%@", getVaList([password as! CVarArg])) // $ hasCleartextLogging=99
NSLogv("%@ %@", getVaList(["" as! CVarArg, password as! CVarArg])) // $ hasCleartextLogging=100
From 6a54a8bc62d24e95640317875c302d598ca6bdfa Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Tue, 15 Aug 2023 18:21:37 +0100
Subject: [PATCH 070/788] Swift: QLDoc VariadicSequenceType.
---
.../swift/elements/type/VariadicSequenceType.qll | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/swift/ql/lib/codeql/swift/elements/type/VariadicSequenceType.qll b/swift/ql/lib/codeql/swift/elements/type/VariadicSequenceType.qll
index 58845cc2b94..3e64b313c9c 100644
--- a/swift/ql/lib/codeql/swift/elements/type/VariadicSequenceType.qll
+++ b/swift/ql/lib/codeql/swift/elements/type/VariadicSequenceType.qll
@@ -1,4 +1,12 @@
-// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.type.VariadicSequenceType
+/**
+ * A variadic sequence type, that is, an array-like type that holds
+ * variadic arguments. For example the type `Int...` of `args` in:
+ * ```
+ * func myVarargsFunction(args: Int...) {
+ * ...
+ * }
+ * ```
+ */
class VariadicSequenceType extends Generated::VariadicSequenceType { }
From da6c2b6c31435e9c905d3694c8d94d7817c46164 Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Wed, 16 Aug 2023 10:33:33 +0100
Subject: [PATCH 071/788] Swift: Add more swift/cleartext-logging sinks.
---
.../codeql/swift/security/CleartextLoggingExtensions.qll | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/swift/ql/lib/codeql/swift/security/CleartextLoggingExtensions.qll b/swift/ql/lib/codeql/swift/security/CleartextLoggingExtensions.qll
index 77e4079a0ca..bf8033209bd 100644
--- a/swift/ql/lib/codeql/swift/security/CleartextLoggingExtensions.qll
+++ b/swift/ql/lib/codeql/swift/security/CleartextLoggingExtensions.qll
@@ -89,6 +89,13 @@ private class LoggingSinks extends SinkModelCsv {
[
";;false;print(_:separator:terminator:);;;Argument[0..2];log-injection",
";;false;print(_:separator:terminator:toStream:);;;Argument[0..2];log-injection",
+ ";;false;print(_:separator:terminator:to:);;;Argument[0..2];log-injection",
+ ";;false;debugPrint(_:separator:terminator:);;;Argument[0..2];log-injection",
+ ";;false;debugPrint(_:separator:terminator:to:);;;Argument[0..2];log-injection",
+ ";;false;dump(_:name:indent:maxDepth:maxItems:);;;Argument[0..1];log-injection",
+ ";;false;dump(_:to:name:indent:maxDepth:maxItems:);;;Argument[0];log-injection",
+ ";;false;dump(_:to:name:indent:maxDepth:maxItems:);;;Argument[2];log-injection",
+ ";;false;fatalError(_:file:line:);;;Argument[0];log-injection",
";;false;NSLog(_:_:);;;Argument[0..1];log-injection",
";;false;NSLogv(_:_:);;;Argument[0..1];log-injection",
";;false;vfprintf(_:_:_:);;;Agument[1..2];log-injection",
From c9e26678d053b6813bcf09206aa37f74cbda0d6f Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Wed, 16 Aug 2023 08:15:04 +0100
Subject: [PATCH 072/788] Swift: Change notes.
---
swift/ql/lib/change-notes/2023-08-16-varargs.md | 5 +++++
swift/ql/src/change-notes/2023-08-16-cleartext-logging.md | 5 +++++
2 files changed, 10 insertions(+)
create mode 100644 swift/ql/lib/change-notes/2023-08-16-varargs.md
create mode 100644 swift/ql/src/change-notes/2023-08-16-cleartext-logging.md
diff --git a/swift/ql/lib/change-notes/2023-08-16-varargs.md b/swift/ql/lib/change-notes/2023-08-16-varargs.md
new file mode 100644
index 00000000000..324c43f3e21
--- /dev/null
+++ b/swift/ql/lib/change-notes/2023-08-16-varargs.md
@@ -0,0 +1,5 @@
+---
+category: minorAnalysis
+---
+
+* Added flow through variadic arguments, and the `getVaList` function.
diff --git a/swift/ql/src/change-notes/2023-08-16-cleartext-logging.md b/swift/ql/src/change-notes/2023-08-16-cleartext-logging.md
new file mode 100644
index 00000000000..4462b378dd4
--- /dev/null
+++ b/swift/ql/src/change-notes/2023-08-16-cleartext-logging.md
@@ -0,0 +1,5 @@
+---
+category: minorAnalysis
+---
+
+* Added new logging sinks to the `swift/cleartext-logging` query.
From c123c3a8d829d8065607cec86631800c21be0c75 Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Wed, 16 Aug 2023 11:09:39 +0100
Subject: [PATCH 073/788] Swift: Codegen.
---
swift/ql/.generated.list | 1 -
swift/ql/.gitattributes | 1 -
2 files changed, 2 deletions(-)
diff --git a/swift/ql/.generated.list b/swift/ql/.generated.list
index a9ddc3be39d..8750c1fcb78 100644
--- a/swift/ql/.generated.list
+++ b/swift/ql/.generated.list
@@ -360,7 +360,6 @@ lib/codeql/swift/elements/type/UnownedStorageType.qll 2a8be26447acc1bcfddc186b95
lib/codeql/swift/elements/type/UnownedStorageTypeConstructor.qll 211c9f3a9d41d1c9e768aa8ece5c48cca37f7811c5daab8bf80fdc2bd663dd86 c4fb8b39d319e1c27175f96ceec9712f473e0df1597e801d5b475b4c5c9c6389
lib/codeql/swift/elements/type/UnresolvedType.qll 9bdb52645208b186cd55dac91cdee50dc33fc49e10e49fadbfd1d21c33996460 680dd2fc64eeec5f81d2c2a05221c56a1ef7004bdcb1a8517640caa5fba0890d
lib/codeql/swift/elements/type/UnresolvedTypeConstructor.qll 76c34ca055a017a0fa7cfff93843392d0698657fbf864ac798e1ae98325b3556 d0770637ec9674f9e2a47ad5c59423b91d12bb22a9d35dcfa8afa65da9e6ed93
-lib/codeql/swift/elements/type/VariadicSequenceType.qll 325e4c4481e9ac07acdc6aebbcfef618bcaeb420c026c62978a83cf8db4a2964 3ac870a1d6df1642fae26ccda6274a288524a5cf242fab6fac8705d70e3fca88
lib/codeql/swift/elements/type/VariadicSequenceTypeConstructor.qll 0d1d2328a3b5e503a883e7e6d7efd0ca5e7f2633abead9e4c94a9f98ed3cb223 69bff81c1b9413949eacb9298d2efb718ea808e68364569a1090c9878c4af856
lib/codeql/swift/elements/type/WeakStorageType.qll 7c07739cfc1459f068f24fef74838428128054adf611504d22532e4a156073e7 9c968414d7cc8d672f3754bced5d4f83f43a6d7872d0d263d79ff60483e1f996
lib/codeql/swift/elements/type/WeakStorageTypeConstructor.qll d88b031ef44d6de14b3ddcff2eb47b53dbd11550c37250ff2edb42e5d21ec3e9 26d855c33492cf7a118e439f7baeed0e5425cfaf058b1dcc007eca7ed765c897
diff --git a/swift/ql/.gitattributes b/swift/ql/.gitattributes
index 0f00752d7db..6c7b605d35a 100644
--- a/swift/ql/.gitattributes
+++ b/swift/ql/.gitattributes
@@ -362,7 +362,6 @@
/lib/codeql/swift/elements/type/UnownedStorageTypeConstructor.qll linguist-generated
/lib/codeql/swift/elements/type/UnresolvedType.qll linguist-generated
/lib/codeql/swift/elements/type/UnresolvedTypeConstructor.qll linguist-generated
-/lib/codeql/swift/elements/type/VariadicSequenceType.qll linguist-generated
/lib/codeql/swift/elements/type/VariadicSequenceTypeConstructor.qll linguist-generated
/lib/codeql/swift/elements/type/WeakStorageType.qll linguist-generated
/lib/codeql/swift/elements/type/WeakStorageTypeConstructor.qll linguist-generated
From 9a4410d4b764e58e82ee048adc3f6ef0227d4b7f Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Wed, 16 Aug 2023 11:53:05 +0100
Subject: [PATCH 074/788] Swift: Additional test cases for array conversions.
---
.../dataflow/taint/core/LocalTaint.expected | 195 +++++-----
.../dataflow/taint/core/Taint.expected | 348 +++++++++---------
.../dataflow/taint/core/conversions.swift | 87 +++--
3 files changed, 329 insertions(+), 301 deletions(-)
diff --git a/swift/ql/test/library-tests/dataflow/taint/core/LocalTaint.expected b/swift/ql/test/library-tests/dataflow/taint/core/LocalTaint.expected
index cb5fc364e9f..5953d76c22d 100644
--- a/swift/ql/test/library-tests/dataflow/taint/core/LocalTaint.expected
+++ b/swift/ql/test/library-tests/dataflow/taint/core/LocalTaint.expected
@@ -17,98 +17,109 @@
| conversions.swift:19:33:19:33 | self | conversions.swift:19:33:19:33 | SSA def(self) |
| conversions.swift:20:22:20:22 | SSA def(self) | conversions.swift:20:22:20:38 | self[return] |
| conversions.swift:20:22:20:22 | self | conversions.swift:20:22:20:22 | SSA def(self) |
-| conversions.swift:25:16:25:26 | call to sourceInt() | conversions.swift:25:12:25:27 | call to Self.init(_:) |
-| conversions.swift:26:18:26:28 | call to sourceInt() | conversions.swift:26:12:26:29 | call to Self.init(_:) |
-| conversions.swift:27:18:27:28 | call to sourceInt() | conversions.swift:27:12:27:29 | call to Float.init(_:) |
-| conversions.swift:28:19:28:29 | call to sourceInt() | conversions.swift:28:12:28:30 | call to String.init(_:) |
-| conversions.swift:29:12:29:30 | call to String.init(_:) | conversions.swift:29:12:29:32 | .utf8 |
-| conversions.swift:29:19:29:29 | call to sourceInt() | conversions.swift:29:12:29:30 | call to String.init(_:) |
-| conversions.swift:30:20:30:33 | call to sourceString() | conversions.swift:30:20:30:35 | .utf8 |
-| conversions.swift:32:5:32:9 | let ...? | conversions.swift:32:9:32:9 | v |
-| conversions.swift:32:9:32:9 | SSA def(v) | conversions.swift:33:13:33:13 | v |
-| conversions.swift:32:9:32:9 | v | conversions.swift:32:9:32:9 | SSA def(v) |
-| conversions.swift:32:13:32:23 | call to sourceInt() | conversions.swift:32:5:32:9 | let ...? |
-| conversions.swift:36:6:36:6 | SSA def(v2) | conversions.swift:37:12:37:12 | v2 |
-| conversions.swift:36:6:36:6 | v2 | conversions.swift:36:6:36:6 | SSA def(v2) |
-| conversions.swift:36:6:36:10 | ... as ... | conversions.swift:36:6:36:6 | v2 |
-| conversions.swift:36:18:36:41 | call to numericCast(_:) | conversions.swift:36:6:36:10 | ... as ... |
-| conversions.swift:36:30:36:40 | call to sourceInt() | conversions.swift:36:18:36:41 | call to numericCast(_:) |
-| conversions.swift:39:6:39:6 | SSA def(v4) | conversions.swift:40:12:40:12 | v4 |
-| conversions.swift:39:6:39:6 | v4 | conversions.swift:39:6:39:6 | SSA def(v4) |
-| conversions.swift:39:6:39:10 | ... as ... | conversions.swift:39:6:39:6 | v4 |
-| conversions.swift:39:17:39:57 | call to unsafeBitCast(_:to:) | conversions.swift:39:6:39:10 | ... as ... |
-| conversions.swift:39:31:39:41 | call to sourceInt() | conversions.swift:39:17:39:57 | call to unsafeBitCast(_:to:) |
-| conversions.swift:42:6:42:6 | SSA def(v5) | conversions.swift:43:12:43:12 | v5 |
-| conversions.swift:42:6:42:6 | v5 | conversions.swift:42:6:42:6 | SSA def(v5) |
-| conversions.swift:42:11:42:47 | call to Self.init(truncatingIfNeeded:) | conversions.swift:42:6:42:6 | v5 |
-| conversions.swift:42:36:42:46 | call to sourceInt() | conversions.swift:42:11:42:47 | call to Self.init(truncatingIfNeeded:) |
-| conversions.swift:45:6:45:6 | SSA def(v6) | conversions.swift:46:12:46:12 | v6 |
-| conversions.swift:45:6:45:6 | v6 | conversions.swift:45:6:45:6 | SSA def(v6) |
-| conversions.swift:45:11:45:39 | call to UInt.init(bitPattern:) | conversions.swift:45:6:45:6 | v6 |
-| conversions.swift:45:28:45:38 | call to sourceInt() | conversions.swift:45:11:45:39 | call to UInt.init(bitPattern:) |
-| conversions.swift:48:12:48:36 | call to Self.init(exactly:) | conversions.swift:48:12:48:37 | ...! |
-| conversions.swift:49:26:49:36 | call to sourceInt() | conversions.swift:49:12:49:37 | call to Self.init(clamping:) |
-| conversions.swift:50:36:50:46 | call to sourceInt() | conversions.swift:50:12:50:47 | call to Self.init(truncatingIfNeeded:) |
-| conversions.swift:51:12:51:41 | call to Self.init(_:radix:) | conversions.swift:51:12:51:42 | ...! |
-| conversions.swift:51:16:51:29 | call to sourceString() | conversions.swift:51:12:51:41 | call to Self.init(_:radix:) |
-| conversions.swift:53:30:53:40 | call to sourceInt() | conversions.swift:53:12:53:41 | call to Self.init(littleEndian:) |
-| conversions.swift:54:27:54:37 | call to sourceInt() | conversions.swift:54:12:54:38 | call to Self.init(bigEndian:) |
-| conversions.swift:55:12:55:22 | call to sourceInt() | conversions.swift:55:12:55:24 | .littleEndian |
-| conversions.swift:56:12:56:22 | call to sourceInt() | conversions.swift:56:12:56:24 | .bigEndian |
-| conversions.swift:61:18:61:30 | call to sourceFloat() | conversions.swift:61:12:61:31 | call to Float.init(_:) |
-| conversions.swift:62:18:62:30 | call to sourceFloat() | conversions.swift:62:12:62:31 | call to UInt8.init(_:) |
-| conversions.swift:63:19:63:31 | call to sourceFloat() | conversions.swift:63:12:63:32 | call to String.init(_:) |
-| conversions.swift:64:12:64:32 | call to String.init(_:) | conversions.swift:64:12:64:34 | .utf8 |
-| conversions.swift:64:19:64:31 | call to sourceFloat() | conversions.swift:64:12:64:32 | call to String.init(_:) |
-| conversions.swift:66:18:66:30 | call to sourceFloat() | conversions.swift:66:12:66:31 | call to Float.init(_:) |
-| conversions.swift:67:41:67:51 | call to sourceInt() | conversions.swift:67:12:67:70 | call to Float.init(sign:exponent:significand:) |
-| conversions.swift:67:67:67:67 | 0.0 | conversions.swift:67:12:67:70 | call to Float.init(sign:exponent:significand:) |
-| conversions.swift:68:41:68:41 | 0 | conversions.swift:68:12:68:70 | call to Float.init(sign:exponent:significand:) |
-| conversions.swift:68:57:68:69 | call to sourceFloat() | conversions.swift:68:12:68:70 | call to Float.init(sign:exponent:significand:) |
-| conversions.swift:69:54:69:54 | 0.0 | conversions.swift:69:12:69:57 | call to Float.init(signOf:magnitudeOf:) |
-| conversions.swift:70:44:70:56 | call to sourceFloat() | conversions.swift:70:12:70:57 | call to Float.init(signOf:magnitudeOf:) |
-| conversions.swift:72:12:72:24 | call to sourceFloat() | conversions.swift:72:12:72:26 | .exponent |
-| conversions.swift:73:12:73:24 | call to sourceFloat() | conversions.swift:73:12:73:26 | .significand |
-| conversions.swift:78:19:78:32 | call to sourceString() | conversions.swift:78:12:78:33 | call to String.init(_:) |
-| conversions.swift:80:6:80:6 | SSA def(ms1) | conversions.swift:81:12:81:12 | ms1 |
-| conversions.swift:80:6:80:6 | ms1 | conversions.swift:80:6:80:6 | SSA def(ms1) |
-| conversions.swift:80:12:80:26 | call to MyString.init(_:) | conversions.swift:80:12:80:27 | ...! |
-| conversions.swift:80:12:80:27 | ...! | conversions.swift:80:6:80:6 | ms1 |
-| conversions.swift:80:21:80:21 | abc | conversions.swift:80:12:80:26 | call to MyString.init(_:) |
-| conversions.swift:81:12:81:12 | [post] ms1 | conversions.swift:82:12:82:12 | ms1 |
-| conversions.swift:81:12:81:12 | ms1 | conversions.swift:82:12:82:12 | ms1 |
-| conversions.swift:82:12:82:12 | [post] ms1 | conversions.swift:83:12:83:12 | ms1 |
-| conversions.swift:82:12:82:12 | ms1 | conversions.swift:83:12:83:12 | ms1 |
-| conversions.swift:83:12:83:12 | [post] ms1 | conversions.swift:84:12:84:12 | ms1 |
-| conversions.swift:83:12:83:12 | ms1 | conversions.swift:84:12:84:12 | ms1 |
-| conversions.swift:86:6:86:6 | SSA def(ms2) | conversions.swift:87:12:87:12 | ms2 |
-| conversions.swift:86:6:86:6 | ms2 | conversions.swift:86:6:86:6 | SSA def(ms2) |
-| conversions.swift:86:12:86:35 | call to MyString.init(_:) | conversions.swift:86:12:86:36 | ...! |
-| conversions.swift:86:12:86:36 | ...! | conversions.swift:86:6:86:6 | ms2 |
-| conversions.swift:86:21:86:34 | call to sourceString() | conversions.swift:86:12:86:35 | call to MyString.init(_:) |
-| conversions.swift:87:12:87:12 | [post] ms2 | conversions.swift:88:12:88:12 | ms2 |
-| conversions.swift:87:12:87:12 | ms2 | conversions.swift:88:12:88:12 | ms2 |
-| conversions.swift:88:12:88:12 | [post] ms2 | conversions.swift:89:12:89:12 | ms2 |
-| conversions.swift:88:12:88:12 | ms2 | conversions.swift:89:12:89:12 | ms2 |
-| conversions.swift:89:12:89:12 | [post] ms2 | conversions.swift:90:12:90:12 | ms2 |
-| conversions.swift:89:12:89:12 | ms2 | conversions.swift:90:12:90:12 | ms2 |
-| conversions.swift:94:6:94:6 | SSA def(parent) | conversions.swift:95:12:95:12 | parent |
-| conversions.swift:94:6:94:6 | parent | conversions.swift:94:6:94:6 | SSA def(parent) |
-| conversions.swift:94:6:94:15 | ... as ... | conversions.swift:94:6:94:6 | parent |
-| conversions.swift:94:31:94:44 | call to sourceString() | conversions.swift:94:6:94:15 | ... as ... |
-| conversions.swift:95:12:95:12 | [post] parent | conversions.swift:96:12:96:12 | parent |
-| conversions.swift:95:12:95:12 | parent | conversions.swift:96:12:96:12 | parent |
-| conversions.swift:96:12:96:12 | [post] parent | conversions.swift:98:40:98:40 | parent |
-| conversions.swift:96:12:96:12 | parent | conversions.swift:98:40:98:40 | parent |
-| conversions.swift:98:6:98:6 | SSA def(v3) | conversions.swift:99:12:99:12 | v3 |
-| conversions.swift:98:6:98:6 | v3 | conversions.swift:98:6:98:6 | SSA def(v3) |
-| conversions.swift:98:6:98:10 | ... as ... | conversions.swift:98:6:98:6 | v3 |
-| conversions.swift:98:25:98:69 | call to unsafeDowncast(_:to:) | conversions.swift:98:6:98:10 | ... as ... |
-| conversions.swift:98:40:98:40 | parent | conversions.swift:98:25:98:69 | call to unsafeDowncast(_:to:) |
-| conversions.swift:99:12:99:12 | [post] v3 | conversions.swift:100:12:100:12 | v3 |
-| conversions.swift:99:12:99:12 | v3 | conversions.swift:100:12:100:12 | v3 |
-| conversions.swift:107:24:107:24 | myCEnumConst | conversions.swift:107:12:107:36 | call to Self.init(_:) |
-| conversions.swift:108:24:108:34 | call to sourceInt() | conversions.swift:108:12:108:35 | call to Self.init(_:) |
+| conversions.swift:27:16:27:26 | call to sourceInt() | conversions.swift:27:12:27:27 | call to Self.init(_:) |
+| conversions.swift:28:18:28:28 | call to sourceInt() | conversions.swift:28:12:28:29 | call to Self.init(_:) |
+| conversions.swift:29:18:29:28 | call to sourceInt() | conversions.swift:29:12:29:29 | call to Float.init(_:) |
+| conversions.swift:30:19:30:29 | call to sourceInt() | conversions.swift:30:12:30:30 | call to String.init(_:) |
+| conversions.swift:31:12:31:30 | call to String.init(_:) | conversions.swift:31:12:31:32 | .utf8 |
+| conversions.swift:31:19:31:29 | call to sourceInt() | conversions.swift:31:12:31:30 | call to String.init(_:) |
+| conversions.swift:33:6:33:6 | SSA def(arr) | conversions.swift:34:12:34:12 | arr |
+| conversions.swift:33:6:33:6 | arr | conversions.swift:33:6:33:6 | SSA def(arr) |
+| conversions.swift:33:12:33:30 | [...] | conversions.swift:33:6:33:6 | arr |
+| conversions.swift:34:12:34:12 | arr | conversions.swift:35:12:35:12 | arr |
+| conversions.swift:35:12:35:12 | [post] arr | conversions.swift:36:20:36:20 | arr |
+| conversions.swift:35:12:35:12 | arr | conversions.swift:35:12:35:17 | ...[...] |
+| conversions.swift:35:12:35:12 | arr | conversions.swift:36:20:36:20 | arr |
+| conversions.swift:36:20:36:20 | arr | conversions.swift:37:20:37:20 | arr |
+| conversions.swift:37:12:37:23 | call to Array.init(_:) | conversions.swift:37:12:37:26 | ...[...] |
+| conversions.swift:38:20:38:33 | call to sourceString() | conversions.swift:38:20:38:35 | .utf8 |
+| conversions.swift:39:12:39:39 | call to Array.init(_:) | conversions.swift:39:12:39:42 | ...[...] |
+| conversions.swift:39:20:39:33 | call to sourceString() | conversions.swift:39:20:39:35 | .utf8 |
+| conversions.swift:41:5:41:9 | let ...? | conversions.swift:41:9:41:9 | v |
+| conversions.swift:41:9:41:9 | SSA def(v) | conversions.swift:42:13:42:13 | v |
+| conversions.swift:41:9:41:9 | v | conversions.swift:41:9:41:9 | SSA def(v) |
+| conversions.swift:41:13:41:23 | call to sourceInt() | conversions.swift:41:5:41:9 | let ...? |
+| conversions.swift:45:6:45:6 | SSA def(v2) | conversions.swift:46:12:46:12 | v2 |
+| conversions.swift:45:6:45:6 | v2 | conversions.swift:45:6:45:6 | SSA def(v2) |
+| conversions.swift:45:6:45:10 | ... as ... | conversions.swift:45:6:45:6 | v2 |
+| conversions.swift:45:18:45:41 | call to numericCast(_:) | conversions.swift:45:6:45:10 | ... as ... |
+| conversions.swift:45:30:45:40 | call to sourceInt() | conversions.swift:45:18:45:41 | call to numericCast(_:) |
+| conversions.swift:48:6:48:6 | SSA def(v4) | conversions.swift:49:12:49:12 | v4 |
+| conversions.swift:48:6:48:6 | v4 | conversions.swift:48:6:48:6 | SSA def(v4) |
+| conversions.swift:48:6:48:10 | ... as ... | conversions.swift:48:6:48:6 | v4 |
+| conversions.swift:48:17:48:57 | call to unsafeBitCast(_:to:) | conversions.swift:48:6:48:10 | ... as ... |
+| conversions.swift:48:31:48:41 | call to sourceInt() | conversions.swift:48:17:48:57 | call to unsafeBitCast(_:to:) |
+| conversions.swift:51:6:51:6 | SSA def(v5) | conversions.swift:52:12:52:12 | v5 |
+| conversions.swift:51:6:51:6 | v5 | conversions.swift:51:6:51:6 | SSA def(v5) |
+| conversions.swift:51:11:51:47 | call to Self.init(truncatingIfNeeded:) | conversions.swift:51:6:51:6 | v5 |
+| conversions.swift:51:36:51:46 | call to sourceInt() | conversions.swift:51:11:51:47 | call to Self.init(truncatingIfNeeded:) |
+| conversions.swift:54:6:54:6 | SSA def(v6) | conversions.swift:55:12:55:12 | v6 |
+| conversions.swift:54:6:54:6 | v6 | conversions.swift:54:6:54:6 | SSA def(v6) |
+| conversions.swift:54:11:54:39 | call to UInt.init(bitPattern:) | conversions.swift:54:6:54:6 | v6 |
+| conversions.swift:54:28:54:38 | call to sourceInt() | conversions.swift:54:11:54:39 | call to UInt.init(bitPattern:) |
+| conversions.swift:57:12:57:36 | call to Self.init(exactly:) | conversions.swift:57:12:57:37 | ...! |
+| conversions.swift:58:26:58:36 | call to sourceInt() | conversions.swift:58:12:58:37 | call to Self.init(clamping:) |
+| conversions.swift:59:36:59:46 | call to sourceInt() | conversions.swift:59:12:59:47 | call to Self.init(truncatingIfNeeded:) |
+| conversions.swift:60:12:60:41 | call to Self.init(_:radix:) | conversions.swift:60:12:60:42 | ...! |
+| conversions.swift:60:16:60:29 | call to sourceString() | conversions.swift:60:12:60:41 | call to Self.init(_:radix:) |
+| conversions.swift:62:30:62:40 | call to sourceInt() | conversions.swift:62:12:62:41 | call to Self.init(littleEndian:) |
+| conversions.swift:63:27:63:37 | call to sourceInt() | conversions.swift:63:12:63:38 | call to Self.init(bigEndian:) |
+| conversions.swift:64:12:64:22 | call to sourceInt() | conversions.swift:64:12:64:24 | .littleEndian |
+| conversions.swift:65:12:65:22 | call to sourceInt() | conversions.swift:65:12:65:24 | .bigEndian |
+| conversions.swift:70:18:70:30 | call to sourceFloat() | conversions.swift:70:12:70:31 | call to Float.init(_:) |
+| conversions.swift:71:18:71:30 | call to sourceFloat() | conversions.swift:71:12:71:31 | call to UInt8.init(_:) |
+| conversions.swift:72:19:72:31 | call to sourceFloat() | conversions.swift:72:12:72:32 | call to String.init(_:) |
+| conversions.swift:73:12:73:32 | call to String.init(_:) | conversions.swift:73:12:73:34 | .utf8 |
+| conversions.swift:73:19:73:31 | call to sourceFloat() | conversions.swift:73:12:73:32 | call to String.init(_:) |
+| conversions.swift:75:18:75:30 | call to sourceFloat() | conversions.swift:75:12:75:31 | call to Float.init(_:) |
+| conversions.swift:76:41:76:51 | call to sourceInt() | conversions.swift:76:12:76:70 | call to Float.init(sign:exponent:significand:) |
+| conversions.swift:76:67:76:67 | 0.0 | conversions.swift:76:12:76:70 | call to Float.init(sign:exponent:significand:) |
+| conversions.swift:77:41:77:41 | 0 | conversions.swift:77:12:77:70 | call to Float.init(sign:exponent:significand:) |
+| conversions.swift:77:57:77:69 | call to sourceFloat() | conversions.swift:77:12:77:70 | call to Float.init(sign:exponent:significand:) |
+| conversions.swift:78:54:78:54 | 0.0 | conversions.swift:78:12:78:57 | call to Float.init(signOf:magnitudeOf:) |
+| conversions.swift:79:44:79:56 | call to sourceFloat() | conversions.swift:79:12:79:57 | call to Float.init(signOf:magnitudeOf:) |
+| conversions.swift:81:12:81:24 | call to sourceFloat() | conversions.swift:81:12:81:26 | .exponent |
+| conversions.swift:82:12:82:24 | call to sourceFloat() | conversions.swift:82:12:82:26 | .significand |
+| conversions.swift:87:19:87:32 | call to sourceString() | conversions.swift:87:12:87:33 | call to String.init(_:) |
+| conversions.swift:89:6:89:6 | SSA def(ms1) | conversions.swift:90:12:90:12 | ms1 |
+| conversions.swift:89:6:89:6 | ms1 | conversions.swift:89:6:89:6 | SSA def(ms1) |
+| conversions.swift:89:12:89:26 | call to MyString.init(_:) | conversions.swift:89:12:89:27 | ...! |
+| conversions.swift:89:12:89:27 | ...! | conversions.swift:89:6:89:6 | ms1 |
+| conversions.swift:89:21:89:21 | abc | conversions.swift:89:12:89:26 | call to MyString.init(_:) |
+| conversions.swift:90:12:90:12 | [post] ms1 | conversions.swift:91:12:91:12 | ms1 |
+| conversions.swift:90:12:90:12 | ms1 | conversions.swift:91:12:91:12 | ms1 |
+| conversions.swift:91:12:91:12 | [post] ms1 | conversions.swift:92:12:92:12 | ms1 |
+| conversions.swift:91:12:91:12 | ms1 | conversions.swift:92:12:92:12 | ms1 |
+| conversions.swift:92:12:92:12 | [post] ms1 | conversions.swift:93:12:93:12 | ms1 |
+| conversions.swift:92:12:92:12 | ms1 | conversions.swift:93:12:93:12 | ms1 |
+| conversions.swift:95:6:95:6 | SSA def(ms2) | conversions.swift:96:12:96:12 | ms2 |
+| conversions.swift:95:6:95:6 | ms2 | conversions.swift:95:6:95:6 | SSA def(ms2) |
+| conversions.swift:95:12:95:35 | call to MyString.init(_:) | conversions.swift:95:12:95:36 | ...! |
+| conversions.swift:95:12:95:36 | ...! | conversions.swift:95:6:95:6 | ms2 |
+| conversions.swift:95:21:95:34 | call to sourceString() | conversions.swift:95:12:95:35 | call to MyString.init(_:) |
+| conversions.swift:96:12:96:12 | [post] ms2 | conversions.swift:97:12:97:12 | ms2 |
+| conversions.swift:96:12:96:12 | ms2 | conversions.swift:97:12:97:12 | ms2 |
+| conversions.swift:97:12:97:12 | [post] ms2 | conversions.swift:98:12:98:12 | ms2 |
+| conversions.swift:97:12:97:12 | ms2 | conversions.swift:98:12:98:12 | ms2 |
+| conversions.swift:98:12:98:12 | [post] ms2 | conversions.swift:99:12:99:12 | ms2 |
+| conversions.swift:98:12:98:12 | ms2 | conversions.swift:99:12:99:12 | ms2 |
+| conversions.swift:103:6:103:6 | SSA def(parent) | conversions.swift:104:12:104:12 | parent |
+| conversions.swift:103:6:103:6 | parent | conversions.swift:103:6:103:6 | SSA def(parent) |
+| conversions.swift:103:6:103:15 | ... as ... | conversions.swift:103:6:103:6 | parent |
+| conversions.swift:103:31:103:44 | call to sourceString() | conversions.swift:103:6:103:15 | ... as ... |
+| conversions.swift:104:12:104:12 | [post] parent | conversions.swift:105:12:105:12 | parent |
+| conversions.swift:104:12:104:12 | parent | conversions.swift:105:12:105:12 | parent |
+| conversions.swift:105:12:105:12 | [post] parent | conversions.swift:107:40:107:40 | parent |
+| conversions.swift:105:12:105:12 | parent | conversions.swift:107:40:107:40 | parent |
+| conversions.swift:107:6:107:6 | SSA def(v3) | conversions.swift:108:12:108:12 | v3 |
+| conversions.swift:107:6:107:6 | v3 | conversions.swift:107:6:107:6 | SSA def(v3) |
+| conversions.swift:107:6:107:10 | ... as ... | conversions.swift:107:6:107:6 | v3 |
+| conversions.swift:107:25:107:69 | call to unsafeDowncast(_:to:) | conversions.swift:107:6:107:10 | ... as ... |
+| conversions.swift:107:40:107:40 | parent | conversions.swift:107:25:107:69 | call to unsafeDowncast(_:to:) |
+| conversions.swift:108:12:108:12 | [post] v3 | conversions.swift:109:12:109:12 | v3 |
+| conversions.swift:108:12:108:12 | v3 | conversions.swift:109:12:109:12 | v3 |
+| conversions.swift:116:24:116:24 | myCEnumConst | conversions.swift:116:12:116:36 | call to Self.init(_:) |
+| conversions.swift:117:24:117:34 | call to sourceInt() | conversions.swift:117:12:117:35 | call to Self.init(_:) |
| simple.swift:12:13:12:13 | 1 | simple.swift:12:13:12:24 | ... .+(_:_:) ... |
| simple.swift:12:17:12:24 | call to source() | simple.swift:12:13:12:24 | ... .+(_:_:) ... |
| simple.swift:13:13:13:20 | call to source() | simple.swift:13:13:13:24 | ... .+(_:_:) ... |
diff --git a/swift/ql/test/library-tests/dataflow/taint/core/Taint.expected b/swift/ql/test/library-tests/dataflow/taint/core/Taint.expected
index 427040adc40..4f10e907be3 100644
--- a/swift/ql/test/library-tests/dataflow/taint/core/Taint.expected
+++ b/swift/ql/test/library-tests/dataflow/taint/core/Taint.expected
@@ -1,53 +1,56 @@
edges
-| conversions.swift:25:16:25:26 | call to sourceInt() | conversions.swift:25:12:25:27 | call to Self.init(_:) |
-| conversions.swift:26:18:26:28 | call to sourceInt() | conversions.swift:26:12:26:29 | call to Self.init(_:) |
-| conversions.swift:27:18:27:28 | call to sourceInt() | conversions.swift:27:12:27:29 | call to Float.init(_:) |
-| conversions.swift:28:19:28:29 | call to sourceInt() | conversions.swift:28:12:28:30 | call to String.init(_:) |
-| conversions.swift:29:12:29:30 | call to String.init(_:) | conversions.swift:29:12:29:32 | .utf8 |
-| conversions.swift:29:19:29:29 | call to sourceInt() | conversions.swift:29:12:29:30 | call to String.init(_:) |
-| conversions.swift:32:13:32:23 | call to sourceInt() | conversions.swift:33:13:33:13 | v |
-| conversions.swift:36:18:36:41 | call to numericCast(_:) | conversions.swift:37:12:37:12 | v2 |
-| conversions.swift:36:30:36:40 | call to sourceInt() | conversions.swift:36:18:36:41 | call to numericCast(_:) |
-| conversions.swift:39:17:39:57 | call to unsafeBitCast(_:to:) | conversions.swift:40:12:40:12 | v4 |
-| conversions.swift:39:31:39:41 | call to sourceInt() | conversions.swift:39:17:39:57 | call to unsafeBitCast(_:to:) |
-| conversions.swift:42:11:42:47 | call to Self.init(truncatingIfNeeded:) | conversions.swift:43:12:43:12 | v5 |
-| conversions.swift:42:36:42:46 | call to sourceInt() | conversions.swift:42:11:42:47 | call to Self.init(truncatingIfNeeded:) |
-| conversions.swift:45:11:45:39 | call to UInt.init(bitPattern:) | conversions.swift:46:12:46:12 | v6 |
-| conversions.swift:45:28:45:38 | call to sourceInt() | conversions.swift:45:11:45:39 | call to UInt.init(bitPattern:) |
-| conversions.swift:48:12:48:36 | call to Self.init(exactly:) [some:0] | conversions.swift:48:12:48:37 | ...! |
-| conversions.swift:48:25:48:35 | call to sourceInt() | conversions.swift:48:12:48:36 | call to Self.init(exactly:) [some:0] |
-| conversions.swift:49:26:49:36 | call to sourceInt() | conversions.swift:49:12:49:37 | call to Self.init(clamping:) |
-| conversions.swift:50:36:50:46 | call to sourceInt() | conversions.swift:50:12:50:47 | call to Self.init(truncatingIfNeeded:) |
-| conversions.swift:51:12:51:41 | call to Self.init(_:radix:) | conversions.swift:51:12:51:42 | ...! |
-| conversions.swift:51:16:51:29 | call to sourceString() | conversions.swift:51:12:51:41 | call to Self.init(_:radix:) |
-| conversions.swift:53:30:53:40 | call to sourceInt() | conversions.swift:53:12:53:41 | call to Self.init(littleEndian:) |
-| conversions.swift:54:27:54:37 | call to sourceInt() | conversions.swift:54:12:54:38 | call to Self.init(bigEndian:) |
-| conversions.swift:55:12:55:22 | call to sourceInt() | conversions.swift:55:12:55:24 | .littleEndian |
-| conversions.swift:56:12:56:22 | call to sourceInt() | conversions.swift:56:12:56:24 | .bigEndian |
-| conversions.swift:61:18:61:30 | call to sourceFloat() | conversions.swift:61:12:61:31 | call to Float.init(_:) |
-| conversions.swift:62:18:62:30 | call to sourceFloat() | conversions.swift:62:12:62:31 | call to UInt8.init(_:) |
-| conversions.swift:63:19:63:31 | call to sourceFloat() | conversions.swift:63:12:63:32 | call to String.init(_:) |
-| conversions.swift:64:12:64:32 | call to String.init(_:) | conversions.swift:64:12:64:34 | .utf8 |
-| conversions.swift:64:19:64:31 | call to sourceFloat() | conversions.swift:64:12:64:32 | call to String.init(_:) |
-| conversions.swift:66:18:66:30 | call to sourceFloat() | conversions.swift:66:12:66:31 | call to Float.init(_:) |
-| conversions.swift:67:41:67:51 | call to sourceInt() | conversions.swift:67:12:67:70 | call to Float.init(sign:exponent:significand:) |
-| conversions.swift:68:57:68:69 | call to sourceFloat() | conversions.swift:68:12:68:70 | call to Float.init(sign:exponent:significand:) |
-| conversions.swift:70:44:70:56 | call to sourceFloat() | conversions.swift:70:12:70:57 | call to Float.init(signOf:magnitudeOf:) |
-| conversions.swift:72:12:72:24 | call to sourceFloat() | conversions.swift:72:12:72:26 | .exponent |
-| conversions.swift:73:12:73:24 | call to sourceFloat() | conversions.swift:73:12:73:26 | .significand |
-| conversions.swift:78:19:78:32 | call to sourceString() | conversions.swift:78:12:78:33 | call to String.init(_:) |
-| conversions.swift:86:12:86:35 | call to MyString.init(_:) | conversions.swift:86:12:86:35 | call to MyString.init(_:) [some:0] |
-| conversions.swift:86:12:86:35 | call to MyString.init(_:) | conversions.swift:87:12:87:12 | ms2 |
-| conversions.swift:86:12:86:35 | call to MyString.init(_:) [some:0] | conversions.swift:86:12:86:36 | ...! |
-| conversions.swift:86:12:86:36 | ...! | conversions.swift:87:12:87:12 | ms2 |
-| conversions.swift:86:21:86:34 | call to sourceString() | conversions.swift:86:12:86:35 | call to MyString.init(_:) |
-| conversions.swift:94:31:94:44 | call to sourceString() | conversions.swift:95:12:95:12 | parent |
-| conversions.swift:94:31:94:44 | call to sourceString() | conversions.swift:96:12:96:12 | parent |
-| conversions.swift:94:31:94:44 | call to sourceString() | conversions.swift:98:40:98:40 | parent |
-| conversions.swift:98:25:98:69 | call to unsafeDowncast(_:to:) | conversions.swift:99:12:99:12 | v3 |
-| conversions.swift:98:25:98:69 | call to unsafeDowncast(_:to:) | conversions.swift:100:12:100:12 | v3 |
-| conversions.swift:98:40:98:40 | parent | conversions.swift:98:25:98:69 | call to unsafeDowncast(_:to:) |
-| conversions.swift:108:24:108:34 | call to sourceInt() | conversions.swift:108:12:108:35 | call to Self.init(_:) |
+| conversions.swift:27:16:27:26 | call to sourceInt() | conversions.swift:27:12:27:27 | call to Self.init(_:) |
+| conversions.swift:28:18:28:28 | call to sourceInt() | conversions.swift:28:12:28:29 | call to Self.init(_:) |
+| conversions.swift:29:18:29:28 | call to sourceInt() | conversions.swift:29:12:29:29 | call to Float.init(_:) |
+| conversions.swift:30:19:30:29 | call to sourceInt() | conversions.swift:30:12:30:30 | call to String.init(_:) |
+| conversions.swift:31:12:31:30 | call to String.init(_:) | conversions.swift:31:12:31:32 | .utf8 |
+| conversions.swift:31:19:31:29 | call to sourceInt() | conversions.swift:31:12:31:30 | call to String.init(_:) |
+| conversions.swift:33:12:33:30 | [...] [Array element] | conversions.swift:35:12:35:12 | arr [Array element] |
+| conversions.swift:33:19:33:29 | call to sourceInt() | conversions.swift:33:12:33:30 | [...] [Array element] |
+| conversions.swift:35:12:35:12 | arr [Array element] | conversions.swift:35:12:35:17 | ...[...] |
+| conversions.swift:41:13:41:23 | call to sourceInt() | conversions.swift:42:13:42:13 | v |
+| conversions.swift:45:18:45:41 | call to numericCast(_:) | conversions.swift:46:12:46:12 | v2 |
+| conversions.swift:45:30:45:40 | call to sourceInt() | conversions.swift:45:18:45:41 | call to numericCast(_:) |
+| conversions.swift:48:17:48:57 | call to unsafeBitCast(_:to:) | conversions.swift:49:12:49:12 | v4 |
+| conversions.swift:48:31:48:41 | call to sourceInt() | conversions.swift:48:17:48:57 | call to unsafeBitCast(_:to:) |
+| conversions.swift:51:11:51:47 | call to Self.init(truncatingIfNeeded:) | conversions.swift:52:12:52:12 | v5 |
+| conversions.swift:51:36:51:46 | call to sourceInt() | conversions.swift:51:11:51:47 | call to Self.init(truncatingIfNeeded:) |
+| conversions.swift:54:11:54:39 | call to UInt.init(bitPattern:) | conversions.swift:55:12:55:12 | v6 |
+| conversions.swift:54:28:54:38 | call to sourceInt() | conversions.swift:54:11:54:39 | call to UInt.init(bitPattern:) |
+| conversions.swift:57:12:57:36 | call to Self.init(exactly:) [some:0] | conversions.swift:57:12:57:37 | ...! |
+| conversions.swift:57:25:57:35 | call to sourceInt() | conversions.swift:57:12:57:36 | call to Self.init(exactly:) [some:0] |
+| conversions.swift:58:26:58:36 | call to sourceInt() | conversions.swift:58:12:58:37 | call to Self.init(clamping:) |
+| conversions.swift:59:36:59:46 | call to sourceInt() | conversions.swift:59:12:59:47 | call to Self.init(truncatingIfNeeded:) |
+| conversions.swift:60:12:60:41 | call to Self.init(_:radix:) | conversions.swift:60:12:60:42 | ...! |
+| conversions.swift:60:16:60:29 | call to sourceString() | conversions.swift:60:12:60:41 | call to Self.init(_:radix:) |
+| conversions.swift:62:30:62:40 | call to sourceInt() | conversions.swift:62:12:62:41 | call to Self.init(littleEndian:) |
+| conversions.swift:63:27:63:37 | call to sourceInt() | conversions.swift:63:12:63:38 | call to Self.init(bigEndian:) |
+| conversions.swift:64:12:64:22 | call to sourceInt() | conversions.swift:64:12:64:24 | .littleEndian |
+| conversions.swift:65:12:65:22 | call to sourceInt() | conversions.swift:65:12:65:24 | .bigEndian |
+| conversions.swift:70:18:70:30 | call to sourceFloat() | conversions.swift:70:12:70:31 | call to Float.init(_:) |
+| conversions.swift:71:18:71:30 | call to sourceFloat() | conversions.swift:71:12:71:31 | call to UInt8.init(_:) |
+| conversions.swift:72:19:72:31 | call to sourceFloat() | conversions.swift:72:12:72:32 | call to String.init(_:) |
+| conversions.swift:73:12:73:32 | call to String.init(_:) | conversions.swift:73:12:73:34 | .utf8 |
+| conversions.swift:73:19:73:31 | call to sourceFloat() | conversions.swift:73:12:73:32 | call to String.init(_:) |
+| conversions.swift:75:18:75:30 | call to sourceFloat() | conversions.swift:75:12:75:31 | call to Float.init(_:) |
+| conversions.swift:76:41:76:51 | call to sourceInt() | conversions.swift:76:12:76:70 | call to Float.init(sign:exponent:significand:) |
+| conversions.swift:77:57:77:69 | call to sourceFloat() | conversions.swift:77:12:77:70 | call to Float.init(sign:exponent:significand:) |
+| conversions.swift:79:44:79:56 | call to sourceFloat() | conversions.swift:79:12:79:57 | call to Float.init(signOf:magnitudeOf:) |
+| conversions.swift:81:12:81:24 | call to sourceFloat() | conversions.swift:81:12:81:26 | .exponent |
+| conversions.swift:82:12:82:24 | call to sourceFloat() | conversions.swift:82:12:82:26 | .significand |
+| conversions.swift:87:19:87:32 | call to sourceString() | conversions.swift:87:12:87:33 | call to String.init(_:) |
+| conversions.swift:95:12:95:35 | call to MyString.init(_:) | conversions.swift:95:12:95:35 | call to MyString.init(_:) [some:0] |
+| conversions.swift:95:12:95:35 | call to MyString.init(_:) | conversions.swift:96:12:96:12 | ms2 |
+| conversions.swift:95:12:95:35 | call to MyString.init(_:) [some:0] | conversions.swift:95:12:95:36 | ...! |
+| conversions.swift:95:12:95:36 | ...! | conversions.swift:96:12:96:12 | ms2 |
+| conversions.swift:95:21:95:34 | call to sourceString() | conversions.swift:95:12:95:35 | call to MyString.init(_:) |
+| conversions.swift:103:31:103:44 | call to sourceString() | conversions.swift:104:12:104:12 | parent |
+| conversions.swift:103:31:103:44 | call to sourceString() | conversions.swift:105:12:105:12 | parent |
+| conversions.swift:103:31:103:44 | call to sourceString() | conversions.swift:107:40:107:40 | parent |
+| conversions.swift:107:25:107:69 | call to unsafeDowncast(_:to:) | conversions.swift:108:12:108:12 | v3 |
+| conversions.swift:107:25:107:69 | call to unsafeDowncast(_:to:) | conversions.swift:109:12:109:12 | v3 |
+| conversions.swift:107:40:107:40 | parent | conversions.swift:107:25:107:69 | call to unsafeDowncast(_:to:) |
+| conversions.swift:117:24:117:34 | call to sourceInt() | conversions.swift:117:12:117:35 | call to Self.init(_:) |
| file://:0:0:0:0 | self [first] | file://:0:0:0:0 | .first |
| file://:0:0:0:0 | self [second] | file://:0:0:0:0 | .second |
| file://:0:0:0:0 | value | file://:0:0:0:0 | [post] self [first] |
@@ -126,89 +129,93 @@ edges
| try.swift:18:18:18:25 | call to source() | try.swift:18:18:18:25 | call to source() [some:0] |
| try.swift:18:18:18:25 | call to source() [some:0] | try.swift:18:13:18:25 | try? ... [some:0] |
nodes
-| conversions.swift:24:12:24:22 | call to sourceInt() | semmle.label | call to sourceInt() |
-| conversions.swift:25:12:25:27 | call to Self.init(_:) | semmle.label | call to Self.init(_:) |
-| conversions.swift:25:16:25:26 | call to sourceInt() | semmle.label | call to sourceInt() |
-| conversions.swift:26:12:26:29 | call to Self.init(_:) | semmle.label | call to Self.init(_:) |
-| conversions.swift:26:18:26:28 | call to sourceInt() | semmle.label | call to sourceInt() |
-| conversions.swift:27:12:27:29 | call to Float.init(_:) | semmle.label | call to Float.init(_:) |
-| conversions.swift:27:18:27:28 | call to sourceInt() | semmle.label | call to sourceInt() |
-| conversions.swift:28:12:28:30 | call to String.init(_:) | semmle.label | call to String.init(_:) |
-| conversions.swift:28:19:28:29 | call to sourceInt() | semmle.label | call to sourceInt() |
-| conversions.swift:29:12:29:30 | call to String.init(_:) | semmle.label | call to String.init(_:) |
-| conversions.swift:29:12:29:32 | .utf8 | semmle.label | .utf8 |
-| conversions.swift:29:19:29:29 | call to sourceInt() | semmle.label | call to sourceInt() |
-| conversions.swift:32:13:32:23 | call to sourceInt() | semmle.label | call to sourceInt() |
-| conversions.swift:33:13:33:13 | v | semmle.label | v |
-| conversions.swift:36:18:36:41 | call to numericCast(_:) | semmle.label | call to numericCast(_:) |
-| conversions.swift:36:30:36:40 | call to sourceInt() | semmle.label | call to sourceInt() |
-| conversions.swift:37:12:37:12 | v2 | semmle.label | v2 |
-| conversions.swift:39:17:39:57 | call to unsafeBitCast(_:to:) | semmle.label | call to unsafeBitCast(_:to:) |
-| conversions.swift:39:31:39:41 | call to sourceInt() | semmle.label | call to sourceInt() |
-| conversions.swift:40:12:40:12 | v4 | semmle.label | v4 |
-| conversions.swift:42:11:42:47 | call to Self.init(truncatingIfNeeded:) | semmle.label | call to Self.init(truncatingIfNeeded:) |
-| conversions.swift:42:36:42:46 | call to sourceInt() | semmle.label | call to sourceInt() |
-| conversions.swift:43:12:43:12 | v5 | semmle.label | v5 |
-| conversions.swift:45:11:45:39 | call to UInt.init(bitPattern:) | semmle.label | call to UInt.init(bitPattern:) |
-| conversions.swift:45:28:45:38 | call to sourceInt() | semmle.label | call to sourceInt() |
-| conversions.swift:46:12:46:12 | v6 | semmle.label | v6 |
-| conversions.swift:48:12:48:36 | call to Self.init(exactly:) [some:0] | semmle.label | call to Self.init(exactly:) [some:0] |
-| conversions.swift:48:12:48:37 | ...! | semmle.label | ...! |
-| conversions.swift:48:25:48:35 | call to sourceInt() | semmle.label | call to sourceInt() |
-| conversions.swift:49:12:49:37 | call to Self.init(clamping:) | semmle.label | call to Self.init(clamping:) |
-| conversions.swift:49:26:49:36 | call to sourceInt() | semmle.label | call to sourceInt() |
-| conversions.swift:50:12:50:47 | call to Self.init(truncatingIfNeeded:) | semmle.label | call to Self.init(truncatingIfNeeded:) |
-| conversions.swift:50:36:50:46 | call to sourceInt() | semmle.label | call to sourceInt() |
-| conversions.swift:51:12:51:41 | call to Self.init(_:radix:) | semmle.label | call to Self.init(_:radix:) |
-| conversions.swift:51:12:51:42 | ...! | semmle.label | ...! |
-| conversions.swift:51:16:51:29 | call to sourceString() | semmle.label | call to sourceString() |
-| conversions.swift:53:12:53:41 | call to Self.init(littleEndian:) | semmle.label | call to Self.init(littleEndian:) |
-| conversions.swift:53:30:53:40 | call to sourceInt() | semmle.label | call to sourceInt() |
-| conversions.swift:54:12:54:38 | call to Self.init(bigEndian:) | semmle.label | call to Self.init(bigEndian:) |
-| conversions.swift:54:27:54:37 | call to sourceInt() | semmle.label | call to sourceInt() |
-| conversions.swift:55:12:55:22 | call to sourceInt() | semmle.label | call to sourceInt() |
-| conversions.swift:55:12:55:24 | .littleEndian | semmle.label | .littleEndian |
-| conversions.swift:56:12:56:22 | call to sourceInt() | semmle.label | call to sourceInt() |
-| conversions.swift:56:12:56:24 | .bigEndian | semmle.label | .bigEndian |
-| conversions.swift:60:12:60:24 | call to sourceFloat() | semmle.label | call to sourceFloat() |
-| conversions.swift:61:12:61:31 | call to Float.init(_:) | semmle.label | call to Float.init(_:) |
-| conversions.swift:61:18:61:30 | call to sourceFloat() | semmle.label | call to sourceFloat() |
-| conversions.swift:62:12:62:31 | call to UInt8.init(_:) | semmle.label | call to UInt8.init(_:) |
-| conversions.swift:62:18:62:30 | call to sourceFloat() | semmle.label | call to sourceFloat() |
-| conversions.swift:63:12:63:32 | call to String.init(_:) | semmle.label | call to String.init(_:) |
-| conversions.swift:63:19:63:31 | call to sourceFloat() | semmle.label | call to sourceFloat() |
-| conversions.swift:64:12:64:32 | call to String.init(_:) | semmle.label | call to String.init(_:) |
-| conversions.swift:64:12:64:34 | .utf8 | semmle.label | .utf8 |
-| conversions.swift:64:19:64:31 | call to sourceFloat() | semmle.label | call to sourceFloat() |
-| conversions.swift:66:12:66:31 | call to Float.init(_:) | semmle.label | call to Float.init(_:) |
-| conversions.swift:66:18:66:30 | call to sourceFloat() | semmle.label | call to sourceFloat() |
-| conversions.swift:67:12:67:70 | call to Float.init(sign:exponent:significand:) | semmle.label | call to Float.init(sign:exponent:significand:) |
-| conversions.swift:67:41:67:51 | call to sourceInt() | semmle.label | call to sourceInt() |
-| conversions.swift:68:12:68:70 | call to Float.init(sign:exponent:significand:) | semmle.label | call to Float.init(sign:exponent:significand:) |
-| conversions.swift:68:57:68:69 | call to sourceFloat() | semmle.label | call to sourceFloat() |
-| conversions.swift:70:12:70:57 | call to Float.init(signOf:magnitudeOf:) | semmle.label | call to Float.init(signOf:magnitudeOf:) |
-| conversions.swift:70:44:70:56 | call to sourceFloat() | semmle.label | call to sourceFloat() |
-| conversions.swift:72:12:72:24 | call to sourceFloat() | semmle.label | call to sourceFloat() |
-| conversions.swift:72:12:72:26 | .exponent | semmle.label | .exponent |
-| conversions.swift:73:12:73:24 | call to sourceFloat() | semmle.label | call to sourceFloat() |
-| conversions.swift:73:12:73:26 | .significand | semmle.label | .significand |
-| conversions.swift:77:12:77:25 | call to sourceString() | semmle.label | call to sourceString() |
-| conversions.swift:78:12:78:33 | call to String.init(_:) | semmle.label | call to String.init(_:) |
-| conversions.swift:78:19:78:32 | call to sourceString() | semmle.label | call to sourceString() |
-| conversions.swift:86:12:86:35 | call to MyString.init(_:) | semmle.label | call to MyString.init(_:) |
-| conversions.swift:86:12:86:35 | call to MyString.init(_:) [some:0] | semmle.label | call to MyString.init(_:) [some:0] |
-| conversions.swift:86:12:86:36 | ...! | semmle.label | ...! |
-| conversions.swift:86:21:86:34 | call to sourceString() | semmle.label | call to sourceString() |
-| conversions.swift:87:12:87:12 | ms2 | semmle.label | ms2 |
-| conversions.swift:94:31:94:44 | call to sourceString() | semmle.label | call to sourceString() |
-| conversions.swift:95:12:95:12 | parent | semmle.label | parent |
-| conversions.swift:96:12:96:12 | parent | semmle.label | parent |
-| conversions.swift:98:25:98:69 | call to unsafeDowncast(_:to:) | semmle.label | call to unsafeDowncast(_:to:) |
-| conversions.swift:98:40:98:40 | parent | semmle.label | parent |
-| conversions.swift:99:12:99:12 | v3 | semmle.label | v3 |
-| conversions.swift:100:12:100:12 | v3 | semmle.label | v3 |
-| conversions.swift:108:12:108:35 | call to Self.init(_:) | semmle.label | call to Self.init(_:) |
-| conversions.swift:108:24:108:34 | call to sourceInt() | semmle.label | call to sourceInt() |
+| conversions.swift:26:12:26:22 | call to sourceInt() | semmle.label | call to sourceInt() |
+| conversions.swift:27:12:27:27 | call to Self.init(_:) | semmle.label | call to Self.init(_:) |
+| conversions.swift:27:16:27:26 | call to sourceInt() | semmle.label | call to sourceInt() |
+| conversions.swift:28:12:28:29 | call to Self.init(_:) | semmle.label | call to Self.init(_:) |
+| conversions.swift:28:18:28:28 | call to sourceInt() | semmle.label | call to sourceInt() |
+| conversions.swift:29:12:29:29 | call to Float.init(_:) | semmle.label | call to Float.init(_:) |
+| conversions.swift:29:18:29:28 | call to sourceInt() | semmle.label | call to sourceInt() |
+| conversions.swift:30:12:30:30 | call to String.init(_:) | semmle.label | call to String.init(_:) |
+| conversions.swift:30:19:30:29 | call to sourceInt() | semmle.label | call to sourceInt() |
+| conversions.swift:31:12:31:30 | call to String.init(_:) | semmle.label | call to String.init(_:) |
+| conversions.swift:31:12:31:32 | .utf8 | semmle.label | .utf8 |
+| conversions.swift:31:19:31:29 | call to sourceInt() | semmle.label | call to sourceInt() |
+| conversions.swift:33:12:33:30 | [...] [Array element] | semmle.label | [...] [Array element] |
+| conversions.swift:33:19:33:29 | call to sourceInt() | semmle.label | call to sourceInt() |
+| conversions.swift:35:12:35:12 | arr [Array element] | semmle.label | arr [Array element] |
+| conversions.swift:35:12:35:17 | ...[...] | semmle.label | ...[...] |
+| conversions.swift:41:13:41:23 | call to sourceInt() | semmle.label | call to sourceInt() |
+| conversions.swift:42:13:42:13 | v | semmle.label | v |
+| conversions.swift:45:18:45:41 | call to numericCast(_:) | semmle.label | call to numericCast(_:) |
+| conversions.swift:45:30:45:40 | call to sourceInt() | semmle.label | call to sourceInt() |
+| conversions.swift:46:12:46:12 | v2 | semmle.label | v2 |
+| conversions.swift:48:17:48:57 | call to unsafeBitCast(_:to:) | semmle.label | call to unsafeBitCast(_:to:) |
+| conversions.swift:48:31:48:41 | call to sourceInt() | semmle.label | call to sourceInt() |
+| conversions.swift:49:12:49:12 | v4 | semmle.label | v4 |
+| conversions.swift:51:11:51:47 | call to Self.init(truncatingIfNeeded:) | semmle.label | call to Self.init(truncatingIfNeeded:) |
+| conversions.swift:51:36:51:46 | call to sourceInt() | semmle.label | call to sourceInt() |
+| conversions.swift:52:12:52:12 | v5 | semmle.label | v5 |
+| conversions.swift:54:11:54:39 | call to UInt.init(bitPattern:) | semmle.label | call to UInt.init(bitPattern:) |
+| conversions.swift:54:28:54:38 | call to sourceInt() | semmle.label | call to sourceInt() |
+| conversions.swift:55:12:55:12 | v6 | semmle.label | v6 |
+| conversions.swift:57:12:57:36 | call to Self.init(exactly:) [some:0] | semmle.label | call to Self.init(exactly:) [some:0] |
+| conversions.swift:57:12:57:37 | ...! | semmle.label | ...! |
+| conversions.swift:57:25:57:35 | call to sourceInt() | semmle.label | call to sourceInt() |
+| conversions.swift:58:12:58:37 | call to Self.init(clamping:) | semmle.label | call to Self.init(clamping:) |
+| conversions.swift:58:26:58:36 | call to sourceInt() | semmle.label | call to sourceInt() |
+| conversions.swift:59:12:59:47 | call to Self.init(truncatingIfNeeded:) | semmle.label | call to Self.init(truncatingIfNeeded:) |
+| conversions.swift:59:36:59:46 | call to sourceInt() | semmle.label | call to sourceInt() |
+| conversions.swift:60:12:60:41 | call to Self.init(_:radix:) | semmle.label | call to Self.init(_:radix:) |
+| conversions.swift:60:12:60:42 | ...! | semmle.label | ...! |
+| conversions.swift:60:16:60:29 | call to sourceString() | semmle.label | call to sourceString() |
+| conversions.swift:62:12:62:41 | call to Self.init(littleEndian:) | semmle.label | call to Self.init(littleEndian:) |
+| conversions.swift:62:30:62:40 | call to sourceInt() | semmle.label | call to sourceInt() |
+| conversions.swift:63:12:63:38 | call to Self.init(bigEndian:) | semmle.label | call to Self.init(bigEndian:) |
+| conversions.swift:63:27:63:37 | call to sourceInt() | semmle.label | call to sourceInt() |
+| conversions.swift:64:12:64:22 | call to sourceInt() | semmle.label | call to sourceInt() |
+| conversions.swift:64:12:64:24 | .littleEndian | semmle.label | .littleEndian |
+| conversions.swift:65:12:65:22 | call to sourceInt() | semmle.label | call to sourceInt() |
+| conversions.swift:65:12:65:24 | .bigEndian | semmle.label | .bigEndian |
+| conversions.swift:69:12:69:24 | call to sourceFloat() | semmle.label | call to sourceFloat() |
+| conversions.swift:70:12:70:31 | call to Float.init(_:) | semmle.label | call to Float.init(_:) |
+| conversions.swift:70:18:70:30 | call to sourceFloat() | semmle.label | call to sourceFloat() |
+| conversions.swift:71:12:71:31 | call to UInt8.init(_:) | semmle.label | call to UInt8.init(_:) |
+| conversions.swift:71:18:71:30 | call to sourceFloat() | semmle.label | call to sourceFloat() |
+| conversions.swift:72:12:72:32 | call to String.init(_:) | semmle.label | call to String.init(_:) |
+| conversions.swift:72:19:72:31 | call to sourceFloat() | semmle.label | call to sourceFloat() |
+| conversions.swift:73:12:73:32 | call to String.init(_:) | semmle.label | call to String.init(_:) |
+| conversions.swift:73:12:73:34 | .utf8 | semmle.label | .utf8 |
+| conversions.swift:73:19:73:31 | call to sourceFloat() | semmle.label | call to sourceFloat() |
+| conversions.swift:75:12:75:31 | call to Float.init(_:) | semmle.label | call to Float.init(_:) |
+| conversions.swift:75:18:75:30 | call to sourceFloat() | semmle.label | call to sourceFloat() |
+| conversions.swift:76:12:76:70 | call to Float.init(sign:exponent:significand:) | semmle.label | call to Float.init(sign:exponent:significand:) |
+| conversions.swift:76:41:76:51 | call to sourceInt() | semmle.label | call to sourceInt() |
+| conversions.swift:77:12:77:70 | call to Float.init(sign:exponent:significand:) | semmle.label | call to Float.init(sign:exponent:significand:) |
+| conversions.swift:77:57:77:69 | call to sourceFloat() | semmle.label | call to sourceFloat() |
+| conversions.swift:79:12:79:57 | call to Float.init(signOf:magnitudeOf:) | semmle.label | call to Float.init(signOf:magnitudeOf:) |
+| conversions.swift:79:44:79:56 | call to sourceFloat() | semmle.label | call to sourceFloat() |
+| conversions.swift:81:12:81:24 | call to sourceFloat() | semmle.label | call to sourceFloat() |
+| conversions.swift:81:12:81:26 | .exponent | semmle.label | .exponent |
+| conversions.swift:82:12:82:24 | call to sourceFloat() | semmle.label | call to sourceFloat() |
+| conversions.swift:82:12:82:26 | .significand | semmle.label | .significand |
+| conversions.swift:86:12:86:25 | call to sourceString() | semmle.label | call to sourceString() |
+| conversions.swift:87:12:87:33 | call to String.init(_:) | semmle.label | call to String.init(_:) |
+| conversions.swift:87:19:87:32 | call to sourceString() | semmle.label | call to sourceString() |
+| conversions.swift:95:12:95:35 | call to MyString.init(_:) | semmle.label | call to MyString.init(_:) |
+| conversions.swift:95:12:95:35 | call to MyString.init(_:) [some:0] | semmle.label | call to MyString.init(_:) [some:0] |
+| conversions.swift:95:12:95:36 | ...! | semmle.label | ...! |
+| conversions.swift:95:21:95:34 | call to sourceString() | semmle.label | call to sourceString() |
+| conversions.swift:96:12:96:12 | ms2 | semmle.label | ms2 |
+| conversions.swift:103:31:103:44 | call to sourceString() | semmle.label | call to sourceString() |
+| conversions.swift:104:12:104:12 | parent | semmle.label | parent |
+| conversions.swift:105:12:105:12 | parent | semmle.label | parent |
+| conversions.swift:107:25:107:69 | call to unsafeDowncast(_:to:) | semmle.label | call to unsafeDowncast(_:to:) |
+| conversions.swift:107:40:107:40 | parent | semmle.label | parent |
+| conversions.swift:108:12:108:12 | v3 | semmle.label | v3 |
+| conversions.swift:109:12:109:12 | v3 | semmle.label | v3 |
+| conversions.swift:117:12:117:35 | call to Self.init(_:) | semmle.label | call to Self.init(_:) |
+| conversions.swift:117:24:117:34 | call to sourceInt() | semmle.label | call to sourceInt() |
| file://:0:0:0:0 | .first | semmle.label | .first |
| file://:0:0:0:0 | .second | semmle.label | .second |
| file://:0:0:0:0 | [post] self [first] | semmle.label | [post] self [first] |
@@ -332,44 +339,45 @@ subpaths
| stringinterpolation.swift:28:14:28:21 | call to source() | stringinterpolation.swift:7:6:7:6 | value | file://:0:0:0:0 | [post] self [second] | stringinterpolation.swift:28:2:28:2 | [post] p2 [second] |
| stringinterpolation.swift:31:21:31:21 | p2 [second] | stringinterpolation.swift:7:6:7:6 | self [second] | file://:0:0:0:0 | .second | stringinterpolation.swift:31:21:31:24 | .second |
#select
-| conversions.swift:24:12:24:22 | call to sourceInt() | conversions.swift:24:12:24:22 | call to sourceInt() | conversions.swift:24:12:24:22 | call to sourceInt() | result |
-| conversions.swift:25:12:25:27 | call to Self.init(_:) | conversions.swift:25:16:25:26 | call to sourceInt() | conversions.swift:25:12:25:27 | call to Self.init(_:) | result |
-| conversions.swift:26:12:26:29 | call to Self.init(_:) | conversions.swift:26:18:26:28 | call to sourceInt() | conversions.swift:26:12:26:29 | call to Self.init(_:) | result |
-| conversions.swift:27:12:27:29 | call to Float.init(_:) | conversions.swift:27:18:27:28 | call to sourceInt() | conversions.swift:27:12:27:29 | call to Float.init(_:) | result |
-| conversions.swift:28:12:28:30 | call to String.init(_:) | conversions.swift:28:19:28:29 | call to sourceInt() | conversions.swift:28:12:28:30 | call to String.init(_:) | result |
-| conversions.swift:29:12:29:32 | .utf8 | conversions.swift:29:19:29:29 | call to sourceInt() | conversions.swift:29:12:29:32 | .utf8 | result |
-| conversions.swift:33:13:33:13 | v | conversions.swift:32:13:32:23 | call to sourceInt() | conversions.swift:33:13:33:13 | v | result |
-| conversions.swift:37:12:37:12 | v2 | conversions.swift:36:30:36:40 | call to sourceInt() | conversions.swift:37:12:37:12 | v2 | result |
-| conversions.swift:40:12:40:12 | v4 | conversions.swift:39:31:39:41 | call to sourceInt() | conversions.swift:40:12:40:12 | v4 | result |
-| conversions.swift:43:12:43:12 | v5 | conversions.swift:42:36:42:46 | call to sourceInt() | conversions.swift:43:12:43:12 | v5 | result |
-| conversions.swift:46:12:46:12 | v6 | conversions.swift:45:28:45:38 | call to sourceInt() | conversions.swift:46:12:46:12 | v6 | result |
-| conversions.swift:48:12:48:37 | ...! | conversions.swift:48:25:48:35 | call to sourceInt() | conversions.swift:48:12:48:37 | ...! | result |
-| conversions.swift:49:12:49:37 | call to Self.init(clamping:) | conversions.swift:49:26:49:36 | call to sourceInt() | conversions.swift:49:12:49:37 | call to Self.init(clamping:) | result |
-| conversions.swift:50:12:50:47 | call to Self.init(truncatingIfNeeded:) | conversions.swift:50:36:50:46 | call to sourceInt() | conversions.swift:50:12:50:47 | call to Self.init(truncatingIfNeeded:) | result |
-| conversions.swift:51:12:51:42 | ...! | conversions.swift:51:16:51:29 | call to sourceString() | conversions.swift:51:12:51:42 | ...! | result |
-| conversions.swift:53:12:53:41 | call to Self.init(littleEndian:) | conversions.swift:53:30:53:40 | call to sourceInt() | conversions.swift:53:12:53:41 | call to Self.init(littleEndian:) | result |
-| conversions.swift:54:12:54:38 | call to Self.init(bigEndian:) | conversions.swift:54:27:54:37 | call to sourceInt() | conversions.swift:54:12:54:38 | call to Self.init(bigEndian:) | result |
-| conversions.swift:55:12:55:24 | .littleEndian | conversions.swift:55:12:55:22 | call to sourceInt() | conversions.swift:55:12:55:24 | .littleEndian | result |
-| conversions.swift:56:12:56:24 | .bigEndian | conversions.swift:56:12:56:22 | call to sourceInt() | conversions.swift:56:12:56:24 | .bigEndian | result |
-| conversions.swift:60:12:60:24 | call to sourceFloat() | conversions.swift:60:12:60:24 | call to sourceFloat() | conversions.swift:60:12:60:24 | call to sourceFloat() | result |
-| conversions.swift:61:12:61:31 | call to Float.init(_:) | conversions.swift:61:18:61:30 | call to sourceFloat() | conversions.swift:61:12:61:31 | call to Float.init(_:) | result |
-| conversions.swift:62:12:62:31 | call to UInt8.init(_:) | conversions.swift:62:18:62:30 | call to sourceFloat() | conversions.swift:62:12:62:31 | call to UInt8.init(_:) | result |
-| conversions.swift:63:12:63:32 | call to String.init(_:) | conversions.swift:63:19:63:31 | call to sourceFloat() | conversions.swift:63:12:63:32 | call to String.init(_:) | result |
-| conversions.swift:64:12:64:34 | .utf8 | conversions.swift:64:19:64:31 | call to sourceFloat() | conversions.swift:64:12:64:34 | .utf8 | result |
-| conversions.swift:66:12:66:31 | call to Float.init(_:) | conversions.swift:66:18:66:30 | call to sourceFloat() | conversions.swift:66:12:66:31 | call to Float.init(_:) | result |
-| conversions.swift:67:12:67:70 | call to Float.init(sign:exponent:significand:) | conversions.swift:67:41:67:51 | call to sourceInt() | conversions.swift:67:12:67:70 | call to Float.init(sign:exponent:significand:) | result |
-| conversions.swift:68:12:68:70 | call to Float.init(sign:exponent:significand:) | conversions.swift:68:57:68:69 | call to sourceFloat() | conversions.swift:68:12:68:70 | call to Float.init(sign:exponent:significand:) | result |
-| conversions.swift:70:12:70:57 | call to Float.init(signOf:magnitudeOf:) | conversions.swift:70:44:70:56 | call to sourceFloat() | conversions.swift:70:12:70:57 | call to Float.init(signOf:magnitudeOf:) | result |
-| conversions.swift:72:12:72:26 | .exponent | conversions.swift:72:12:72:24 | call to sourceFloat() | conversions.swift:72:12:72:26 | .exponent | result |
-| conversions.swift:73:12:73:26 | .significand | conversions.swift:73:12:73:24 | call to sourceFloat() | conversions.swift:73:12:73:26 | .significand | result |
-| conversions.swift:77:12:77:25 | call to sourceString() | conversions.swift:77:12:77:25 | call to sourceString() | conversions.swift:77:12:77:25 | call to sourceString() | result |
-| conversions.swift:78:12:78:33 | call to String.init(_:) | conversions.swift:78:19:78:32 | call to sourceString() | conversions.swift:78:12:78:33 | call to String.init(_:) | result |
-| conversions.swift:87:12:87:12 | ms2 | conversions.swift:86:21:86:34 | call to sourceString() | conversions.swift:87:12:87:12 | ms2 | result |
-| conversions.swift:95:12:95:12 | parent | conversions.swift:94:31:94:44 | call to sourceString() | conversions.swift:95:12:95:12 | parent | result |
-| conversions.swift:96:12:96:12 | parent | conversions.swift:94:31:94:44 | call to sourceString() | conversions.swift:96:12:96:12 | parent | result |
-| conversions.swift:99:12:99:12 | v3 | conversions.swift:94:31:94:44 | call to sourceString() | conversions.swift:99:12:99:12 | v3 | result |
-| conversions.swift:100:12:100:12 | v3 | conversions.swift:94:31:94:44 | call to sourceString() | conversions.swift:100:12:100:12 | v3 | result |
-| conversions.swift:108:12:108:35 | call to Self.init(_:) | conversions.swift:108:24:108:34 | call to sourceInt() | conversions.swift:108:12:108:35 | call to Self.init(_:) | result |
+| conversions.swift:26:12:26:22 | call to sourceInt() | conversions.swift:26:12:26:22 | call to sourceInt() | conversions.swift:26:12:26:22 | call to sourceInt() | result |
+| conversions.swift:27:12:27:27 | call to Self.init(_:) | conversions.swift:27:16:27:26 | call to sourceInt() | conversions.swift:27:12:27:27 | call to Self.init(_:) | result |
+| conversions.swift:28:12:28:29 | call to Self.init(_:) | conversions.swift:28:18:28:28 | call to sourceInt() | conversions.swift:28:12:28:29 | call to Self.init(_:) | result |
+| conversions.swift:29:12:29:29 | call to Float.init(_:) | conversions.swift:29:18:29:28 | call to sourceInt() | conversions.swift:29:12:29:29 | call to Float.init(_:) | result |
+| conversions.swift:30:12:30:30 | call to String.init(_:) | conversions.swift:30:19:30:29 | call to sourceInt() | conversions.swift:30:12:30:30 | call to String.init(_:) | result |
+| conversions.swift:31:12:31:32 | .utf8 | conversions.swift:31:19:31:29 | call to sourceInt() | conversions.swift:31:12:31:32 | .utf8 | result |
+| conversions.swift:35:12:35:17 | ...[...] | conversions.swift:33:19:33:29 | call to sourceInt() | conversions.swift:35:12:35:17 | ...[...] | result |
+| conversions.swift:42:13:42:13 | v | conversions.swift:41:13:41:23 | call to sourceInt() | conversions.swift:42:13:42:13 | v | result |
+| conversions.swift:46:12:46:12 | v2 | conversions.swift:45:30:45:40 | call to sourceInt() | conversions.swift:46:12:46:12 | v2 | result |
+| conversions.swift:49:12:49:12 | v4 | conversions.swift:48:31:48:41 | call to sourceInt() | conversions.swift:49:12:49:12 | v4 | result |
+| conversions.swift:52:12:52:12 | v5 | conversions.swift:51:36:51:46 | call to sourceInt() | conversions.swift:52:12:52:12 | v5 | result |
+| conversions.swift:55:12:55:12 | v6 | conversions.swift:54:28:54:38 | call to sourceInt() | conversions.swift:55:12:55:12 | v6 | result |
+| conversions.swift:57:12:57:37 | ...! | conversions.swift:57:25:57:35 | call to sourceInt() | conversions.swift:57:12:57:37 | ...! | result |
+| conversions.swift:58:12:58:37 | call to Self.init(clamping:) | conversions.swift:58:26:58:36 | call to sourceInt() | conversions.swift:58:12:58:37 | call to Self.init(clamping:) | result |
+| conversions.swift:59:12:59:47 | call to Self.init(truncatingIfNeeded:) | conversions.swift:59:36:59:46 | call to sourceInt() | conversions.swift:59:12:59:47 | call to Self.init(truncatingIfNeeded:) | result |
+| conversions.swift:60:12:60:42 | ...! | conversions.swift:60:16:60:29 | call to sourceString() | conversions.swift:60:12:60:42 | ...! | result |
+| conversions.swift:62:12:62:41 | call to Self.init(littleEndian:) | conversions.swift:62:30:62:40 | call to sourceInt() | conversions.swift:62:12:62:41 | call to Self.init(littleEndian:) | result |
+| conversions.swift:63:12:63:38 | call to Self.init(bigEndian:) | conversions.swift:63:27:63:37 | call to sourceInt() | conversions.swift:63:12:63:38 | call to Self.init(bigEndian:) | result |
+| conversions.swift:64:12:64:24 | .littleEndian | conversions.swift:64:12:64:22 | call to sourceInt() | conversions.swift:64:12:64:24 | .littleEndian | result |
+| conversions.swift:65:12:65:24 | .bigEndian | conversions.swift:65:12:65:22 | call to sourceInt() | conversions.swift:65:12:65:24 | .bigEndian | result |
+| conversions.swift:69:12:69:24 | call to sourceFloat() | conversions.swift:69:12:69:24 | call to sourceFloat() | conversions.swift:69:12:69:24 | call to sourceFloat() | result |
+| conversions.swift:70:12:70:31 | call to Float.init(_:) | conversions.swift:70:18:70:30 | call to sourceFloat() | conversions.swift:70:12:70:31 | call to Float.init(_:) | result |
+| conversions.swift:71:12:71:31 | call to UInt8.init(_:) | conversions.swift:71:18:71:30 | call to sourceFloat() | conversions.swift:71:12:71:31 | call to UInt8.init(_:) | result |
+| conversions.swift:72:12:72:32 | call to String.init(_:) | conversions.swift:72:19:72:31 | call to sourceFloat() | conversions.swift:72:12:72:32 | call to String.init(_:) | result |
+| conversions.swift:73:12:73:34 | .utf8 | conversions.swift:73:19:73:31 | call to sourceFloat() | conversions.swift:73:12:73:34 | .utf8 | result |
+| conversions.swift:75:12:75:31 | call to Float.init(_:) | conversions.swift:75:18:75:30 | call to sourceFloat() | conversions.swift:75:12:75:31 | call to Float.init(_:) | result |
+| conversions.swift:76:12:76:70 | call to Float.init(sign:exponent:significand:) | conversions.swift:76:41:76:51 | call to sourceInt() | conversions.swift:76:12:76:70 | call to Float.init(sign:exponent:significand:) | result |
+| conversions.swift:77:12:77:70 | call to Float.init(sign:exponent:significand:) | conversions.swift:77:57:77:69 | call to sourceFloat() | conversions.swift:77:12:77:70 | call to Float.init(sign:exponent:significand:) | result |
+| conversions.swift:79:12:79:57 | call to Float.init(signOf:magnitudeOf:) | conversions.swift:79:44:79:56 | call to sourceFloat() | conversions.swift:79:12:79:57 | call to Float.init(signOf:magnitudeOf:) | result |
+| conversions.swift:81:12:81:26 | .exponent | conversions.swift:81:12:81:24 | call to sourceFloat() | conversions.swift:81:12:81:26 | .exponent | result |
+| conversions.swift:82:12:82:26 | .significand | conversions.swift:82:12:82:24 | call to sourceFloat() | conversions.swift:82:12:82:26 | .significand | result |
+| conversions.swift:86:12:86:25 | call to sourceString() | conversions.swift:86:12:86:25 | call to sourceString() | conversions.swift:86:12:86:25 | call to sourceString() | result |
+| conversions.swift:87:12:87:33 | call to String.init(_:) | conversions.swift:87:19:87:32 | call to sourceString() | conversions.swift:87:12:87:33 | call to String.init(_:) | result |
+| conversions.swift:96:12:96:12 | ms2 | conversions.swift:95:21:95:34 | call to sourceString() | conversions.swift:96:12:96:12 | ms2 | result |
+| conversions.swift:104:12:104:12 | parent | conversions.swift:103:31:103:44 | call to sourceString() | conversions.swift:104:12:104:12 | parent | result |
+| conversions.swift:105:12:105:12 | parent | conversions.swift:103:31:103:44 | call to sourceString() | conversions.swift:105:12:105:12 | parent | result |
+| conversions.swift:108:12:108:12 | v3 | conversions.swift:103:31:103:44 | call to sourceString() | conversions.swift:108:12:108:12 | v3 | result |
+| conversions.swift:109:12:109:12 | v3 | conversions.swift:103:31:103:44 | call to sourceString() | conversions.swift:109:12:109:12 | v3 | result |
+| conversions.swift:117:12:117:35 | call to Self.init(_:) | conversions.swift:117:24:117:34 | call to sourceInt() | conversions.swift:117:12:117:35 | call to Self.init(_:) | result |
| simple.swift:12:13:12:24 | ... .+(_:_:) ... | simple.swift:12:17:12:24 | call to source() | simple.swift:12:13:12:24 | ... .+(_:_:) ... | result |
| simple.swift:13:13:13:24 | ... .+(_:_:) ... | simple.swift:13:13:13:20 | call to source() | simple.swift:13:13:13:24 | ... .+(_:_:) ... | result |
| simple.swift:14:13:14:24 | ... .-(_:_:) ... | simple.swift:14:17:14:24 | call to source() | simple.swift:14:13:14:24 | ... .-(_:_:) ... | result |
diff --git a/swift/ql/test/library-tests/dataflow/taint/core/conversions.swift b/swift/ql/test/library-tests/dataflow/taint/core/conversions.swift
index 321c555e0ab..efb0bba4ed2 100644
--- a/swift/ql/test/library-tests/dataflow/taint/core/conversions.swift
+++ b/swift/ql/test/library-tests/dataflow/taint/core/conversions.swift
@@ -20,62 +20,71 @@ class MyString : LosslessStringConvertible, CustomStringConvertible, CustomDebug
var clean: String { get { return "" } }
}
+typealias MyInt = Int
+
func testConversions() {
- sink(arg: sourceInt()) // $ tainted=24
- sink(arg: Int(sourceInt())) // $ tainted=25
- sink(arg: UInt8(sourceInt())) // $ tainted=26
- sink(arg: Float(sourceInt())) // $ tainted=27
- sink(arg: String(sourceInt())) // $ tainted=28
- sink(arg: String(sourceInt()).utf8) // $ tainted=29
- sink(arg: [UInt8](sourceString().utf8)) // $ MISSING: tainted=
+ sink(arg: sourceInt()) // $ tainted=26
+ sink(arg: Int(sourceInt())) // $ tainted=27
+ sink(arg: UInt8(sourceInt())) // $ tainted=28
+ sink(arg: Float(sourceInt())) // $ tainted=29
+ sink(arg: String(sourceInt())) // $ tainted=30
+ sink(arg: String(sourceInt()).utf8) // $ tainted=31
+
+ let arr = [1, 2, sourceInt()]
+ sink(arg: arr)
+ sink(arg: arr[0]) // $ tainted=33
+ sink(arg: [MyInt](arr))
+ sink(arg: [MyInt](arr)[0]) // $ MISSING: tainted=33
+ sink(arg: [UInt8](sourceString().utf8))
+ sink(arg: [UInt8](sourceString().utf8)[0]) // $ MISSING: tainted=33
if let v = sourceInt() as? UInt {
- sink(arg: v) // $ tainted=32
+ sink(arg: v) // $ tainted=41
}
let v2: UInt8 = numericCast(sourceInt())
- sink(arg: v2) // $ tainted=36
+ sink(arg: v2) // $ tainted=45
let v4: UInt = unsafeBitCast(sourceInt(), to: UInt.self)
- sink(arg: v4) // $ tainted=39
+ sink(arg: v4) // $ tainted=48
let v5 = UInt(truncatingIfNeeded: sourceInt())
- sink(arg: v5) // $ tainted=42
+ sink(arg: v5) // $ tainted=51
let v6 = UInt(bitPattern: sourceInt())
- sink(arg: v6) // $ tainted=45
+ sink(arg: v6) // $ tainted=54
- sink(arg: Int(exactly: sourceInt())!) // $ tainted=48
- sink(arg: Int(clamping: sourceInt())) // $ tainted=49
- sink(arg: Int(truncatingIfNeeded: sourceInt())) // $ tainted=50
- sink(arg: Int(sourceString(), radix: 10)!) // $ tainted=51
+ sink(arg: Int(exactly: sourceInt())!) // $ tainted=57
+ sink(arg: Int(clamping: sourceInt())) // $ tainted=58
+ sink(arg: Int(truncatingIfNeeded: sourceInt())) // $ tainted=59
+ sink(arg: Int(sourceString(), radix: 10)!) // $ tainted=60
- sink(arg: Int(littleEndian: sourceInt())) // $ tainted=53
- sink(arg: Int(bigEndian: sourceInt())) // $ tainted=54
- sink(arg: sourceInt().littleEndian) // $ tainted=55
- sink(arg: sourceInt().bigEndian) // $ tainted=56
+ sink(arg: Int(littleEndian: sourceInt())) // $ tainted=62
+ sink(arg: Int(bigEndian: sourceInt())) // $ tainted=63
+ sink(arg: sourceInt().littleEndian) // $ tainted=64
+ sink(arg: sourceInt().bigEndian) // $ tainted=65
// ---
- sink(arg: sourceFloat()) // $ tainted=60
- sink(arg: Float(sourceFloat())) // $ tainted=61
- sink(arg: UInt8(sourceFloat())) // $ tainted=62
- sink(arg: String(sourceFloat())) // $ tainted=63
- sink(arg: String(sourceFloat()).utf8) // $ tainted=64
+ sink(arg: sourceFloat()) // $ tainted=69
+ sink(arg: Float(sourceFloat())) // $ tainted=70
+ sink(arg: UInt8(sourceFloat())) // $ tainted=71
+ sink(arg: String(sourceFloat())) // $ tainted=72
+ sink(arg: String(sourceFloat()).utf8) // $ tainted=73
- sink(arg: Float(sourceFloat())) // $ tainted=66
- sink(arg: Float(sign: .plus, exponent: sourceInt(), significand: 0.0)) // $ tainted=67
- sink(arg: Float(sign: .plus, exponent: 0, significand: sourceFloat())) // $ tainted=68
+ sink(arg: Float(sourceFloat())) // $ tainted=75
+ sink(arg: Float(sign: .plus, exponent: sourceInt(), significand: 0.0)) // $ tainted=76
+ sink(arg: Float(sign: .plus, exponent: 0, significand: sourceFloat())) // $ tainted=77
sink(arg: Float(signOf: sourceFloat(), magnitudeOf: 0.0)) // (good)
- sink(arg: Float(signOf: 0.0, magnitudeOf: sourceFloat())) // $ tainted=70
+ sink(arg: Float(signOf: 0.0, magnitudeOf: sourceFloat())) // $ tainted=79
- sink(arg: sourceFloat().exponent) // $ tainted=72
- sink(arg: sourceFloat().significand) // $ tainted=73
+ sink(arg: sourceFloat().exponent) // $ tainted=81
+ sink(arg: sourceFloat().significand) // $ tainted=82
// ---
- sink(arg: sourceString()) // $ tainted=77
- sink(arg: String(sourceString())) // $ tainted=78
+ sink(arg: sourceString()) // $ tainted=86
+ sink(arg: String(sourceString())) // $ tainted=87
let ms1 = MyString("abc")!
sink(arg: ms1)
@@ -84,7 +93,7 @@ func testConversions() {
sink(arg: ms1.clean)
let ms2 = MyString(sourceString())!
- sink(arg: ms2) // $ tainted=86
+ sink(arg: ms2) // $ tainted=95
sink(arg: ms2.description) // $ MISSING: tainted=
sink(arg: ms2.debugDescription) // $ MISSING: tainted=
sink(arg: ms2.clean)
@@ -92,12 +101,12 @@ func testConversions() {
// ---
let parent : MyParentClass = sourceString() as! MyChildClass
- sink(arg: parent) // $ tainted=94
- sink(arg: parent as! MyChildClass) // $ tainted=94
+ sink(arg: parent) // $ tainted=103
+ sink(arg: parent as! MyChildClass) // $ tainted=103
let v3: MyChildClass = unsafeDowncast(parent, to: MyChildClass.self)
- sink(arg: v3) // $ tainted=94
- sink(arg: v3 as! MyParentClass) // $ tainted=94
+ sink(arg: v3) // $ tainted=103
+ sink(arg: v3 as! MyParentClass) // $ tainted=103
}
var myCEnumConst : Int = 0
@@ -105,5 +114,5 @@ typealias MyCEnumType = UInt32
func testCEnum() {
sink(arg: MyCEnumType(myCEnumConst))
- sink(arg: MyCEnumType(sourceInt())) // $ tainted=108
+ sink(arg: MyCEnumType(sourceInt())) // $ tainted=117
}
From 4b66bada3d188fc891950b1171ae9b3abb572323 Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Wed, 16 Aug 2023 12:01:53 +0100
Subject: [PATCH 075/788] Swift: Model array initializers.
---
.../swift/frameworks/StandardLibrary/Array.qll | 5 +++++
.../dataflow/taint/core/Taint.expected | 15 +++++++++++++++
.../dataflow/taint/core/conversions.swift | 4 ++--
3 files changed, 22 insertions(+), 2 deletions(-)
diff --git a/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/Array.qll b/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/Array.qll
index 207d120e82e..30d753ae967 100644
--- a/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/Array.qll
+++ b/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/Array.qll
@@ -19,6 +19,11 @@ private class ArraySummaries extends SummaryModelCsv {
override predicate row(string row) {
row =
[
+ ";Array;true;init(_:);;;Argument[0];ReturnValue.ArrayElement;value",
+ ";Array;true;init(_:);;;Argument[0].ArrayElement;ReturnValue.ArrayElement;value",
+ ";Array;true;init(_:);;;Argument[0].CollectionElement;ReturnValue.ArrayElement;value",
+ ";Array;true;init(repeating:count:);;;Argument[0];ReturnValue.ArrayElement;value",
+ ";Array;true;init(arrayLiteral:);;;Argument[0].ArrayElement;ReturnValue.ArrayElement;value",
";Array;true;insert(_:at:);;;Argument[0];Argument[-1].ArrayElement;value",
";Array;true;insert(_:at:);;;Argument[1];Argument[-1];taint"
]
diff --git a/swift/ql/test/library-tests/dataflow/taint/core/Taint.expected b/swift/ql/test/library-tests/dataflow/taint/core/Taint.expected
index 4f10e907be3..440a286dfb9 100644
--- a/swift/ql/test/library-tests/dataflow/taint/core/Taint.expected
+++ b/swift/ql/test/library-tests/dataflow/taint/core/Taint.expected
@@ -6,8 +6,14 @@ edges
| conversions.swift:31:12:31:30 | call to String.init(_:) | conversions.swift:31:12:31:32 | .utf8 |
| conversions.swift:31:19:31:29 | call to sourceInt() | conversions.swift:31:12:31:30 | call to String.init(_:) |
| conversions.swift:33:12:33:30 | [...] [Array element] | conversions.swift:35:12:35:12 | arr [Array element] |
+| conversions.swift:33:12:33:30 | [...] [Array element] | conversions.swift:37:20:37:20 | arr [Array element] |
| conversions.swift:33:19:33:29 | call to sourceInt() | conversions.swift:33:12:33:30 | [...] [Array element] |
| conversions.swift:35:12:35:12 | arr [Array element] | conversions.swift:35:12:35:17 | ...[...] |
+| conversions.swift:37:12:37:23 | call to Array.init(_:) [Array element] | conversions.swift:37:12:37:26 | ...[...] |
+| conversions.swift:37:20:37:20 | arr [Array element] | conversions.swift:37:12:37:23 | call to Array.init(_:) [Array element] |
+| conversions.swift:39:12:39:39 | call to Array.init(_:) [Array element] | conversions.swift:39:12:39:42 | ...[...] |
+| conversions.swift:39:20:39:33 | call to sourceString() | conversions.swift:39:20:39:35 | .utf8 |
+| conversions.swift:39:20:39:35 | .utf8 | conversions.swift:39:12:39:39 | call to Array.init(_:) [Array element] |
| conversions.swift:41:13:41:23 | call to sourceInt() | conversions.swift:42:13:42:13 | v |
| conversions.swift:45:18:45:41 | call to numericCast(_:) | conversions.swift:46:12:46:12 | v2 |
| conversions.swift:45:30:45:40 | call to sourceInt() | conversions.swift:45:18:45:41 | call to numericCast(_:) |
@@ -145,6 +151,13 @@ nodes
| conversions.swift:33:19:33:29 | call to sourceInt() | semmle.label | call to sourceInt() |
| conversions.swift:35:12:35:12 | arr [Array element] | semmle.label | arr [Array element] |
| conversions.swift:35:12:35:17 | ...[...] | semmle.label | ...[...] |
+| conversions.swift:37:12:37:23 | call to Array.init(_:) [Array element] | semmle.label | call to Array.init(_:) [Array element] |
+| conversions.swift:37:12:37:26 | ...[...] | semmle.label | ...[...] |
+| conversions.swift:37:20:37:20 | arr [Array element] | semmle.label | arr [Array element] |
+| conversions.swift:39:12:39:39 | call to Array.init(_:) [Array element] | semmle.label | call to Array.init(_:) [Array element] |
+| conversions.swift:39:12:39:42 | ...[...] | semmle.label | ...[...] |
+| conversions.swift:39:20:39:33 | call to sourceString() | semmle.label | call to sourceString() |
+| conversions.swift:39:20:39:35 | .utf8 | semmle.label | .utf8 |
| conversions.swift:41:13:41:23 | call to sourceInt() | semmle.label | call to sourceInt() |
| conversions.swift:42:13:42:13 | v | semmle.label | v |
| conversions.swift:45:18:45:41 | call to numericCast(_:) | semmle.label | call to numericCast(_:) |
@@ -346,6 +359,8 @@ subpaths
| conversions.swift:30:12:30:30 | call to String.init(_:) | conversions.swift:30:19:30:29 | call to sourceInt() | conversions.swift:30:12:30:30 | call to String.init(_:) | result |
| conversions.swift:31:12:31:32 | .utf8 | conversions.swift:31:19:31:29 | call to sourceInt() | conversions.swift:31:12:31:32 | .utf8 | result |
| conversions.swift:35:12:35:17 | ...[...] | conversions.swift:33:19:33:29 | call to sourceInt() | conversions.swift:35:12:35:17 | ...[...] | result |
+| conversions.swift:37:12:37:26 | ...[...] | conversions.swift:33:19:33:29 | call to sourceInt() | conversions.swift:37:12:37:26 | ...[...] | result |
+| conversions.swift:39:12:39:42 | ...[...] | conversions.swift:39:20:39:33 | call to sourceString() | conversions.swift:39:12:39:42 | ...[...] | result |
| conversions.swift:42:13:42:13 | v | conversions.swift:41:13:41:23 | call to sourceInt() | conversions.swift:42:13:42:13 | v | result |
| conversions.swift:46:12:46:12 | v2 | conversions.swift:45:30:45:40 | call to sourceInt() | conversions.swift:46:12:46:12 | v2 | result |
| conversions.swift:49:12:49:12 | v4 | conversions.swift:48:31:48:41 | call to sourceInt() | conversions.swift:49:12:49:12 | v4 | result |
diff --git a/swift/ql/test/library-tests/dataflow/taint/core/conversions.swift b/swift/ql/test/library-tests/dataflow/taint/core/conversions.swift
index efb0bba4ed2..e24c8347251 100644
--- a/swift/ql/test/library-tests/dataflow/taint/core/conversions.swift
+++ b/swift/ql/test/library-tests/dataflow/taint/core/conversions.swift
@@ -34,9 +34,9 @@ func testConversions() {
sink(arg: arr)
sink(arg: arr[0]) // $ tainted=33
sink(arg: [MyInt](arr))
- sink(arg: [MyInt](arr)[0]) // $ MISSING: tainted=33
+ sink(arg: [MyInt](arr)[0]) // $ tainted=33
sink(arg: [UInt8](sourceString().utf8))
- sink(arg: [UInt8](sourceString().utf8)[0]) // $ MISSING: tainted=33
+ sink(arg: [UInt8](sourceString().utf8)[0]) // $ tainted=39
if let v = sourceInt() as? UInt {
sink(arg: v) // $ tainted=41
From 3ee3eabd958bb947bc9ed53046e94ee698a7461b Mon Sep 17 00:00:00 2001
From: Robert Marsh
Date: Wed, 16 Aug 2023 17:52:26 +0000
Subject: [PATCH 076/788] Swift: add EnumContent to clearsContent
---
.../ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll
index 998c0dd8627..0aeccaa0eb0 100644
--- a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll
+++ b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll
@@ -877,7 +877,8 @@ predicate clearsContent(Node n, ContentSet c) {
n = any(PostUpdateNode pun | storeStep(_, c, pun)).getPreUpdateNode() and
(
c.isSingleton(any(Content::FieldContent fc)) or
- c.isSingleton(any(Content::TupleContent tc))
+ c.isSingleton(any(Content::TupleContent tc)) or
+ c.isSingleton(any(Content::EnumContent ec))
)
}
From d3cc366dc5e3e4cb62f69bbebcfa25fd5e0f3321 Mon Sep 17 00:00:00 2001
From: Robert Marsh
Date: Wed, 16 Aug 2023 17:57:30 +0000
Subject: [PATCH 077/788] Swift: add QLDoc for DictionarySubscriptNode
---
.../lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll
index 0aeccaa0eb0..675a450359b 100644
--- a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll
+++ b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll
@@ -300,6 +300,12 @@ import Cached
/** Holds if `n` should be hidden from path explanations. */
predicate nodeIsHidden(Node n) { n instanceof FlowSummaryNode }
+/**
+ * The intermediate node for a dictionary subscript operation `dict[key]`. In a write, this is used
+ * as the destination of the `storeStep`s that add `TupleContent`s and the source of the storeStep
+ * that adds `CollectionContent`. In a read, this is the destination of the `readStep` that pops
+ * `CollectionContent` and the source of the `readStep` that pops `TupleContent[0]`
+ */
private class DictionarySubscriptNode extends NodeImpl, TDictionarySubscriptNode {
SubscriptExpr expr;
From 87364137df810ab89c2c0dc2173c1d8f99918de5 Mon Sep 17 00:00:00 2001
From: Max Schaefer
Date: Fri, 18 Aug 2023 14:43:57 +0100
Subject: [PATCH 078/788] Use more sensible validator in example.
---
.../CWE-601/examples/ServerSideUrlRedirect.js | 4 ++--
.../CWE-601/examples/ServerSideUrlRedirectGood.js | 4 ++--
.../CWE-601/examples/ServerSideUrlRedirectGood2.js | 12 ++++++------
.../ServerSideUrlRedirect.expected | 10 +++++-----
.../ServerSideUrlRedirect/ServerSideUrlRedirect.js | 4 ++--
.../ServerSideUrlRedirectGood.js | 4 ++--
.../ServerSideUrlRedirectGood2.js | 12 ++++++------
7 files changed, 25 insertions(+), 25 deletions(-)
diff --git a/javascript/ql/src/Security/CWE-601/examples/ServerSideUrlRedirect.js b/javascript/ql/src/Security/CWE-601/examples/ServerSideUrlRedirect.js
index d2ae7511c93..38538fc0f96 100644
--- a/javascript/ql/src/Security/CWE-601/examples/ServerSideUrlRedirect.js
+++ b/javascript/ql/src/Security/CWE-601/examples/ServerSideUrlRedirect.js
@@ -1,6 +1,6 @@
const app = require("express")();
-app.get('/redirect', function(req, res) {
+app.get("/redirect", function (req, res) {
// BAD: a request parameter is incorporated without validation into a URL redirect
- res.redirect(req.params["target"]);
+ res.redirect(req.query["target"]);
});
diff --git a/javascript/ql/src/Security/CWE-601/examples/ServerSideUrlRedirectGood.js b/javascript/ql/src/Security/CWE-601/examples/ServerSideUrlRedirectGood.js
index 8903ddf09fa..179f28ccb0b 100644
--- a/javascript/ql/src/Security/CWE-601/examples/ServerSideUrlRedirectGood.js
+++ b/javascript/ql/src/Security/CWE-601/examples/ServerSideUrlRedirectGood.js
@@ -2,9 +2,9 @@ const app = require("express")();
const VALID_REDIRECT = "http://cwe.mitre.org/data/definitions/601.html";
-app.get('/redirect', function(req, res) {
+app.get("/redirect", function (req, res) {
// GOOD: the request parameter is validated against a known fixed string
- let target = req.params["target"]
+ let target = req.query["target"];
if (VALID_REDIRECT === target) {
res.redirect(target);
} else {
diff --git a/javascript/ql/src/Security/CWE-601/examples/ServerSideUrlRedirectGood2.js b/javascript/ql/src/Security/CWE-601/examples/ServerSideUrlRedirectGood2.js
index 5eaedd0aac5..78b3be6c260 100644
--- a/javascript/ql/src/Security/CWE-601/examples/ServerSideUrlRedirectGood2.js
+++ b/javascript/ql/src/Security/CWE-601/examples/ServerSideUrlRedirectGood2.js
@@ -1,15 +1,15 @@
const app = require("express")();
-function isLocalUrl(url) {
- return url.startsWith("/") && !url.startsWith("//") && !url.startsWith("/\\");
+function isRelativePath(path) {
+ return !/^(\w+:)?[/\\]{2}/.test(path);
}
-app.get('/redirect', function(req, res) {
+app.get("/redirect", function (req, res) {
// GOOD: check that we don't redirect to a different host
- let target = req.params["target"];
- if (isLocalUrl(target)) {
+ let target = req.query["target"];
+ if (isRelativePath(target)) {
res.redirect(target);
} else {
res.redirect("/");
}
-});
\ No newline at end of file
+});
diff --git a/javascript/ql/test/query-tests/Security/CWE-601/ServerSideUrlRedirect/ServerSideUrlRedirect.expected b/javascript/ql/test/query-tests/Security/CWE-601/ServerSideUrlRedirect/ServerSideUrlRedirect.expected
index 2883cd3fdac..c03f57e7dd5 100644
--- a/javascript/ql/test/query-tests/Security/CWE-601/ServerSideUrlRedirect/ServerSideUrlRedirect.expected
+++ b/javascript/ql/test/query-tests/Security/CWE-601/ServerSideUrlRedirect/ServerSideUrlRedirect.expected
@@ -1,7 +1,7 @@
nodes
-| ServerSideUrlRedirect.js:5:16:5:35 | req.params["target"] |
-| ServerSideUrlRedirect.js:5:16:5:35 | req.params["target"] |
-| ServerSideUrlRedirect.js:5:16:5:35 | req.params["target"] |
+| ServerSideUrlRedirect.js:5:16:5:34 | req.query["target"] |
+| ServerSideUrlRedirect.js:5:16:5:34 | req.query["target"] |
+| ServerSideUrlRedirect.js:5:16:5:34 | req.query["target"] |
| express.js:7:16:7:34 | req.param("target") |
| express.js:7:16:7:34 | req.param("target") |
| express.js:7:16:7:34 | req.param("target") |
@@ -117,7 +117,7 @@ nodes
| react-native.js:9:26:9:32 | tainted |
| react-native.js:9:26:9:32 | tainted |
edges
-| ServerSideUrlRedirect.js:5:16:5:35 | req.params["target"] | ServerSideUrlRedirect.js:5:16:5:35 | req.params["target"] |
+| ServerSideUrlRedirect.js:5:16:5:34 | req.query["target"] | ServerSideUrlRedirect.js:5:16:5:34 | req.query["target"] |
| express.js:7:16:7:34 | req.param("target") | express.js:7:16:7:34 | req.param("target") |
| express.js:12:26:12:44 | req.param("target") | express.js:12:26:12:44 | req.param("target") |
| express.js:27:7:27:34 | target | express.js:33:18:33:23 | target |
@@ -215,7 +215,7 @@ edges
| react-native.js:7:17:7:33 | req.param("code") | react-native.js:7:7:7:33 | tainted |
| react-native.js:7:17:7:33 | req.param("code") | react-native.js:7:7:7:33 | tainted |
#select
-| ServerSideUrlRedirect.js:5:16:5:35 | req.params["target"] | ServerSideUrlRedirect.js:5:16:5:35 | req.params["target"] | ServerSideUrlRedirect.js:5:16:5:35 | req.params["target"] | Untrusted URL redirection depends on a $@. | ServerSideUrlRedirect.js:5:16:5:35 | req.params["target"] | user-provided value |
+| ServerSideUrlRedirect.js:5:16:5:34 | req.query["target"] | ServerSideUrlRedirect.js:5:16:5:34 | req.query["target"] | ServerSideUrlRedirect.js:5:16:5:34 | req.query["target"] | Untrusted URL redirection depends on a $@. | ServerSideUrlRedirect.js:5:16:5:34 | req.query["target"] | user-provided value |
| express.js:7:16:7:34 | req.param("target") | express.js:7:16:7:34 | req.param("target") | express.js:7:16:7:34 | req.param("target") | Untrusted URL redirection depends on a $@. | express.js:7:16:7:34 | req.param("target") | user-provided value |
| express.js:12:26:12:44 | req.param("target") | express.js:12:26:12:44 | req.param("target") | express.js:12:26:12:44 | req.param("target") | Untrusted URL redirection depends on a $@. | express.js:12:26:12:44 | req.param("target") | user-provided value |
| express.js:33:18:33:23 | target | express.js:27:16:27:34 | req.param("target") | express.js:33:18:33:23 | target | Untrusted URL redirection depends on a $@. | express.js:27:16:27:34 | req.param("target") | user-provided value |
diff --git a/javascript/ql/test/query-tests/Security/CWE-601/ServerSideUrlRedirect/ServerSideUrlRedirect.js b/javascript/ql/test/query-tests/Security/CWE-601/ServerSideUrlRedirect/ServerSideUrlRedirect.js
index d2ae7511c93..38538fc0f96 100644
--- a/javascript/ql/test/query-tests/Security/CWE-601/ServerSideUrlRedirect/ServerSideUrlRedirect.js
+++ b/javascript/ql/test/query-tests/Security/CWE-601/ServerSideUrlRedirect/ServerSideUrlRedirect.js
@@ -1,6 +1,6 @@
const app = require("express")();
-app.get('/redirect', function(req, res) {
+app.get("/redirect", function (req, res) {
// BAD: a request parameter is incorporated without validation into a URL redirect
- res.redirect(req.params["target"]);
+ res.redirect(req.query["target"]);
});
diff --git a/javascript/ql/test/query-tests/Security/CWE-601/ServerSideUrlRedirect/ServerSideUrlRedirectGood.js b/javascript/ql/test/query-tests/Security/CWE-601/ServerSideUrlRedirect/ServerSideUrlRedirectGood.js
index 8903ddf09fa..179f28ccb0b 100644
--- a/javascript/ql/test/query-tests/Security/CWE-601/ServerSideUrlRedirect/ServerSideUrlRedirectGood.js
+++ b/javascript/ql/test/query-tests/Security/CWE-601/ServerSideUrlRedirect/ServerSideUrlRedirectGood.js
@@ -2,9 +2,9 @@ const app = require("express")();
const VALID_REDIRECT = "http://cwe.mitre.org/data/definitions/601.html";
-app.get('/redirect', function(req, res) {
+app.get("/redirect", function (req, res) {
// GOOD: the request parameter is validated against a known fixed string
- let target = req.params["target"]
+ let target = req.query["target"];
if (VALID_REDIRECT === target) {
res.redirect(target);
} else {
diff --git a/javascript/ql/test/query-tests/Security/CWE-601/ServerSideUrlRedirect/ServerSideUrlRedirectGood2.js b/javascript/ql/test/query-tests/Security/CWE-601/ServerSideUrlRedirect/ServerSideUrlRedirectGood2.js
index 5eaedd0aac5..78b3be6c260 100644
--- a/javascript/ql/test/query-tests/Security/CWE-601/ServerSideUrlRedirect/ServerSideUrlRedirectGood2.js
+++ b/javascript/ql/test/query-tests/Security/CWE-601/ServerSideUrlRedirect/ServerSideUrlRedirectGood2.js
@@ -1,15 +1,15 @@
const app = require("express")();
-function isLocalUrl(url) {
- return url.startsWith("/") && !url.startsWith("//") && !url.startsWith("/\\");
+function isRelativePath(path) {
+ return !/^(\w+:)?[/\\]{2}/.test(path);
}
-app.get('/redirect', function(req, res) {
+app.get("/redirect", function (req, res) {
// GOOD: check that we don't redirect to a different host
- let target = req.params["target"];
- if (isLocalUrl(target)) {
+ let target = req.query["target"];
+ if (isRelativePath(target)) {
res.redirect(target);
} else {
res.redirect("/");
}
-});
\ No newline at end of file
+});
From d594de81902e18b22b5362e618eb68e8f0657d9d Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Thu, 17 Aug 2023 10:20:23 +0100
Subject: [PATCH 079/788] Swift: Test dataflow on fields a bit more.
---
.../dataflow/dataflow/DataFlow.expected | 62 +++++++++++++++++++
.../dataflow/dataflow/LocalFlow.expected | 36 +++++++++++
.../dataflow/dataflow/test.swift | 28 +++++++++
3 files changed, 126 insertions(+)
diff --git a/swift/ql/test/library-tests/dataflow/dataflow/DataFlow.expected b/swift/ql/test/library-tests/dataflow/dataflow/DataFlow.expected
index c638ea8e344..df3da66d96b 100644
--- a/swift/ql/test/library-tests/dataflow/dataflow/DataFlow.expected
+++ b/swift/ql/test/library-tests/dataflow/dataflow/DataFlow.expected
@@ -4,10 +4,12 @@ edges
| file://:0:0:0:0 | self [v2, some:0] | file://:0:0:0:0 | .v2 [some:0] |
| file://:0:0:0:0 | self [v2] | file://:0:0:0:0 | .v2 |
| file://:0:0:0:0 | self [v3] | file://:0:0:0:0 | .v3 |
+| file://:0:0:0:0 | self [v] | file://:0:0:0:0 | .v |
| file://:0:0:0:0 | self [x, some:0] | file://:0:0:0:0 | .x [some:0] |
| file://:0:0:0:0 | self [x] | file://:0:0:0:0 | .x |
| file://:0:0:0:0 | value | file://:0:0:0:0 | [post] self [v2] |
| file://:0:0:0:0 | value | file://:0:0:0:0 | [post] self [v3] |
+| file://:0:0:0:0 | value | file://:0:0:0:0 | [post] self [v] |
| file://:0:0:0:0 | value | file://:0:0:0:0 | [post] self [x] |
| file://:0:0:0:0 | value [some:0] | file://:0:0:0:0 | [post] self [v2, some:0] |
| file://:0:0:0:0 | value [some:0] | file://:0:0:0:0 | [post] self [x, some:0] |
@@ -404,9 +406,34 @@ edges
| test.swift:756:15:756:19 | .v2 [some:0] | test.swift:756:15:756:21 | ...! |
| test.swift:757:15:757:15 | mo1 [v3] | test.swift:732:9:732:9 | self [v3] |
| test.swift:757:15:757:15 | mo1 [v3] | test.swift:757:15:757:19 | .v3 |
+| test.swift:764:8:764:13 | v | test.swift:765:14:765:14 | v |
+| test.swift:765:5:765:5 | [post] self [v] | test.swift:764:3:766:3 | self[return] [v] |
+| test.swift:765:14:765:14 | v | test.swift:765:5:765:5 | [post] self [v] |
+| test.swift:768:8:768:8 | self [v] | test.swift:768:31:768:31 | self [v] |
+| test.swift:768:31:768:31 | self [v] | test.swift:768:31:768:31 | .v |
+| test.swift:768:31:768:31 | self [v] | test.swift:770:7:770:7 | self [v] |
+| test.swift:770:7:770:7 | self [v] | file://:0:0:0:0 | self [v] |
+| test.swift:770:7:770:7 | value | file://:0:0:0:0 | value |
+| test.swift:774:14:774:25 | call to S3.init(_:) [v] | test.swift:777:15:777:15 | s1 [v] |
+| test.swift:774:14:774:25 | call to S3.init(_:) [v] | test.swift:779:15:779:15 | s1 [v] |
+| test.swift:774:17:774:24 | call to source() | test.swift:764:8:764:13 | v |
+| test.swift:774:17:774:24 | call to source() | test.swift:774:14:774:25 | call to S3.init(_:) [v] |
+| test.swift:777:15:777:15 | s1 [v] | test.swift:770:7:770:7 | self [v] |
+| test.swift:777:15:777:15 | s1 [v] | test.swift:777:15:777:18 | .v |
+| test.swift:779:15:779:15 | s1 [v] | test.swift:768:8:768:8 | self [v] |
+| test.swift:779:15:779:15 | s1 [v] | test.swift:779:15:779:23 | call to getv() |
+| test.swift:783:5:783:5 | [post] s2 [v] | test.swift:786:15:786:15 | s2 [v] |
+| test.swift:783:5:783:5 | [post] s2 [v] | test.swift:788:15:788:15 | s2 [v] |
+| test.swift:783:12:783:19 | call to source() | test.swift:770:7:770:7 | value |
+| test.swift:783:12:783:19 | call to source() | test.swift:783:5:783:5 | [post] s2 [v] |
+| test.swift:786:15:786:15 | s2 [v] | test.swift:770:7:770:7 | self [v] |
+| test.swift:786:15:786:15 | s2 [v] | test.swift:786:15:786:18 | .v |
+| test.swift:788:15:788:15 | s2 [v] | test.swift:768:8:768:8 | self [v] |
+| test.swift:788:15:788:15 | s2 [v] | test.swift:788:15:788:23 | call to getv() |
nodes
| file://:0:0:0:0 | .a [x] | semmle.label | .a [x] |
| file://:0:0:0:0 | .str | semmle.label | .str |
+| file://:0:0:0:0 | .v | semmle.label | .v |
| file://:0:0:0:0 | .v2 | semmle.label | .v2 |
| file://:0:0:0:0 | .v2 [some:0] | semmle.label | .v2 [some:0] |
| file://:0:0:0:0 | .v3 | semmle.label | .v3 |
@@ -415,6 +442,7 @@ nodes
| file://:0:0:0:0 | [post] self [v2, some:0] | semmle.label | [post] self [v2, some:0] |
| file://:0:0:0:0 | [post] self [v2] | semmle.label | [post] self [v2] |
| file://:0:0:0:0 | [post] self [v3] | semmle.label | [post] self [v3] |
+| file://:0:0:0:0 | [post] self [v] | semmle.label | [post] self [v] |
| file://:0:0:0:0 | [post] self [x, some:0] | semmle.label | [post] self [x, some:0] |
| file://:0:0:0:0 | [post] self [x] | semmle.label | [post] self [x] |
| file://:0:0:0:0 | self [a, x] | semmle.label | self [a, x] |
@@ -422,11 +450,13 @@ nodes
| file://:0:0:0:0 | self [v2, some:0] | semmle.label | self [v2, some:0] |
| file://:0:0:0:0 | self [v2] | semmle.label | self [v2] |
| file://:0:0:0:0 | self [v3] | semmle.label | self [v3] |
+| file://:0:0:0:0 | self [v] | semmle.label | self [v] |
| file://:0:0:0:0 | self [x, some:0] | semmle.label | self [x, some:0] |
| file://:0:0:0:0 | self [x] | semmle.label | self [x] |
| 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 | semmle.label | value |
| file://:0:0:0:0 | value [some:0] | semmle.label | value [some:0] |
| file://:0:0:0:0 | value [some:0] | semmle.label | value [some:0] |
| test.swift:6:19:6:26 | call to source() | semmle.label | call to source() |
@@ -849,6 +879,27 @@ nodes
| test.swift:756:15:756:21 | ...! | semmle.label | ...! |
| test.swift:757:15:757:15 | mo1 [v3] | semmle.label | mo1 [v3] |
| test.swift:757:15:757:19 | .v3 | semmle.label | .v3 |
+| test.swift:764:3:766:3 | self[return] [v] | semmle.label | self[return] [v] |
+| test.swift:764:8:764:13 | v | semmle.label | v |
+| test.swift:765:5:765:5 | [post] self [v] | semmle.label | [post] self [v] |
+| test.swift:765:14:765:14 | v | semmle.label | v |
+| test.swift:768:8:768:8 | self [v] | semmle.label | self [v] |
+| test.swift:768:31:768:31 | .v | semmle.label | .v |
+| test.swift:768:31:768:31 | self [v] | semmle.label | self [v] |
+| test.swift:770:7:770:7 | self [v] | semmle.label | self [v] |
+| test.swift:770:7:770:7 | value | semmle.label | value |
+| test.swift:774:14:774:25 | call to S3.init(_:) [v] | semmle.label | call to S3.init(_:) [v] |
+| test.swift:774:17:774:24 | call to source() | semmle.label | call to source() |
+| test.swift:777:15:777:15 | s1 [v] | semmle.label | s1 [v] |
+| test.swift:777:15:777:18 | .v | semmle.label | .v |
+| test.swift:779:15:779:15 | s1 [v] | semmle.label | s1 [v] |
+| test.swift:779:15:779:23 | call to getv() | semmle.label | call to getv() |
+| test.swift:783:5:783:5 | [post] s2 [v] | semmle.label | [post] s2 [v] |
+| test.swift:783:12:783:19 | call to source() | semmle.label | call to source() |
+| test.swift:786:15:786:15 | s2 [v] | semmle.label | s2 [v] |
+| test.swift:786:15:786:18 | .v | semmle.label | .v |
+| test.swift:788:15:788:15 | s2 [v] | semmle.label | s2 [v] |
+| test.swift:788:15:788:23 | call to getv() | semmle.label | call to getv() |
subpaths
| test.swift:75:22:75:22 | x | test.swift:65:16:65:28 | arg1 | test.swift:65:1:70:1 | arg2[return] | test.swift:75:32:75:32 | [post] y |
| test.swift:114:19:114:19 | arg | test.swift:109:9:109:14 | arg | test.swift:110:12:110:12 | arg | test.swift:114:12:114:22 | call to ... |
@@ -897,6 +948,13 @@ subpaths
| test.swift:756:15:756:15 | mo1 [v2, some:0] | test.swift:731:9:731:9 | self [v2, some:0] | file://:0:0:0:0 | .v2 [some:0] | test.swift:756:15:756:19 | .v2 [some:0] |
| test.swift:756:15:756:15 | mo1 [v2] | test.swift:731:9:731:9 | self [v2] | file://:0:0:0:0 | .v2 | test.swift:756:15:756:19 | .v2 |
| test.swift:757:15:757:15 | mo1 [v3] | test.swift:732:9:732:9 | self [v3] | file://:0:0:0:0 | .v3 | test.swift:757:15:757:19 | .v3 |
+| test.swift:768:31:768:31 | self [v] | test.swift:770:7:770:7 | self [v] | file://:0:0:0:0 | .v | test.swift:768:31:768:31 | .v |
+| test.swift:774:17:774:24 | call to source() | test.swift:764:8:764:13 | v | test.swift:764:3:766:3 | self[return] [v] | test.swift:774:14:774:25 | call to S3.init(_:) [v] |
+| test.swift:777:15:777:15 | s1 [v] | test.swift:770:7:770:7 | self [v] | file://:0:0:0:0 | .v | test.swift:777:15:777:18 | .v |
+| test.swift:779:15:779:15 | s1 [v] | test.swift:768:8:768:8 | self [v] | test.swift:768:31:768:31 | .v | test.swift:779:15:779:23 | call to getv() |
+| test.swift:783:12:783:19 | call to source() | test.swift:770:7:770:7 | value | file://:0:0:0:0 | [post] self [v] | test.swift:783:5:783:5 | [post] s2 [v] |
+| test.swift:786:15:786:15 | s2 [v] | test.swift:770:7:770:7 | self [v] | file://:0:0:0:0 | .v | test.swift:786:15:786:18 | .v |
+| test.swift:788:15:788:15 | s2 [v] | test.swift:768:8:768:8 | self [v] | test.swift:768:31:768:31 | .v | test.swift:788:15:788:23 | call to getv() |
#select
| test.swift:7:15:7:15 | t1 | test.swift:6:19:6:26 | call to source() | test.swift:7:15:7:15 | t1 | result |
| test.swift:9:15:9:15 | t1 | test.swift:6:19:6:26 | call to source() | test.swift:9:15:9:15 | t1 | result |
@@ -996,3 +1054,7 @@ subpaths
| test.swift:754:15:754:15 | v3 | test.swift:744:10:744:17 | call to source() | test.swift:754:15:754:15 | v3 | result |
| test.swift:756:15:756:21 | ...! | test.swift:746:14:746:21 | call to source() | test.swift:756:15:756:21 | ...! | result |
| test.swift:757:15:757:19 | .v3 | test.swift:747:14:747:21 | call to source() | test.swift:757:15:757:19 | .v3 | result |
+| test.swift:777:15:777:18 | .v | test.swift:774:17:774:24 | call to source() | test.swift:777:15:777:18 | .v | result |
+| test.swift:779:15:779:23 | call to getv() | test.swift:774:17:774:24 | call to source() | test.swift:779:15:779:23 | call to getv() | result |
+| test.swift:786:15:786:18 | .v | test.swift:783:12:783:19 | call to source() | test.swift:786:15:786:18 | .v | result |
+| test.swift:788:15:788:23 | call to getv() | test.swift:783:12:783:19 | call to source() | test.swift:788:15:788:23 | call to getv() | result |
diff --git a/swift/ql/test/library-tests/dataflow/dataflow/LocalFlow.expected b/swift/ql/test/library-tests/dataflow/dataflow/LocalFlow.expected
index 18e5d25010d..c3040bc6c9a 100644
--- a/swift/ql/test/library-tests/dataflow/dataflow/LocalFlow.expected
+++ b/swift/ql/test/library-tests/dataflow/dataflow/LocalFlow.expected
@@ -913,3 +913,39 @@
| test.swift:759:15:759:15 | mo2 | test.swift:760:15:760:15 | mo2 |
| test.swift:759:15:759:20 | .v2 | test.swift:759:15:759:22 | ...! |
| test.swift:760:15:760:15 | mo2 | test.swift:760:15:760:18 | ...! |
+| test.swift:764:3:764:3 | SSA def(self) | test.swift:765:5:765:5 | self |
+| test.swift:764:3:764:3 | self | test.swift:764:3:764:3 | SSA def(self) |
+| test.swift:764:8:764:13 | SSA def(v) | test.swift:765:14:765:14 | v |
+| test.swift:764:8:764:13 | v | test.swift:764:8:764:13 | SSA def(v) |
+| test.swift:765:5:765:5 | [post] self | test.swift:764:3:766:3 | self[return] |
+| test.swift:765:5:765:5 | self | test.swift:764:3:766:3 | self[return] |
+| test.swift:768:8:768:8 | SSA def(self) | test.swift:768:31:768:31 | self |
+| test.swift:768:8:768:8 | self | test.swift:768:8:768:8 | SSA def(self) |
+| test.swift:768:31:768:31 | [post] self | test.swift:768:3:768:33 | self[return] |
+| test.swift:768:31:768:31 | self | test.swift:768:3:768:33 | self[return] |
+| test.swift:770:7:770:7 | self | test.swift:770:7:770:7 | SSA def(self) |
+| test.swift:770:7:770:7 | self | test.swift:770:7:770:7 | SSA def(self) |
+| test.swift:770:7:770:7 | self | test.swift:770:7:770:7 | SSA def(self) |
+| test.swift:770:7:770:7 | value | test.swift:770:7:770:7 | SSA def(value) |
+| test.swift:774:9:774:9 | SSA def(s1) | test.swift:777:15:777:15 | s1 |
+| test.swift:774:9:774:9 | s1 | test.swift:774:9:774:9 | SSA def(s1) |
+| test.swift:774:14:774:25 | call to S3.init(_:) | test.swift:774:9:774:9 | s1 |
+| test.swift:775:9:775:9 | SSA def(s2) | test.swift:778:15:778:15 | s2 |
+| test.swift:775:9:775:9 | s2 | test.swift:775:9:775:9 | SSA def(s2) |
+| test.swift:775:14:775:18 | call to S3.init(_:) | test.swift:775:9:775:9 | s2 |
+| test.swift:777:15:777:15 | [post] s1 | test.swift:779:15:779:15 | s1 |
+| test.swift:777:15:777:15 | s1 | test.swift:779:15:779:15 | s1 |
+| test.swift:778:15:778:15 | [post] s2 | test.swift:780:15:780:15 | s2 |
+| test.swift:778:15:778:15 | s2 | test.swift:780:15:780:15 | s2 |
+| test.swift:779:15:779:15 | [post] s1 | test.swift:782:5:782:5 | s1 |
+| test.swift:779:15:779:15 | s1 | test.swift:782:5:782:5 | s1 |
+| test.swift:780:15:780:15 | [post] s2 | test.swift:783:5:783:5 | s2 |
+| test.swift:780:15:780:15 | s2 | test.swift:783:5:783:5 | s2 |
+| test.swift:782:5:782:5 | [post] s1 | test.swift:785:15:785:15 | s1 |
+| test.swift:782:5:782:5 | s1 | test.swift:785:15:785:15 | s1 |
+| test.swift:783:5:783:5 | [post] s2 | test.swift:786:15:786:15 | s2 |
+| test.swift:783:5:783:5 | s2 | test.swift:786:15:786:15 | s2 |
+| test.swift:785:15:785:15 | [post] s1 | test.swift:787:15:787:15 | s1 |
+| test.swift:785:15:785:15 | s1 | test.swift:787:15:787:15 | s1 |
+| test.swift:786:15:786:15 | [post] s2 | test.swift:788:15:788:15 | s2 |
+| test.swift:786:15:786:15 | s2 | test.swift:788:15:788:15 | s2 |
diff --git a/swift/ql/test/library-tests/dataflow/dataflow/test.swift b/swift/ql/test/library-tests/dataflow/dataflow/test.swift
index 44001572dbd..60618063c8d 100644
--- a/swift/ql/test/library-tests/dataflow/dataflow/test.swift
+++ b/swift/ql/test/library-tests/dataflow/dataflow/test.swift
@@ -759,3 +759,31 @@ func testWriteOptional() {
sink(arg: mo2!.v2!) // $ MISSING:flow=749
sink(arg: mo2!.v3) // $ MISSING:flow=750
}
+
+struct S3 {
+ init(_ v: Int) {
+ self.v = v
+ }
+
+ func getv() -> Int { return v }
+
+ var v: Int
+}
+
+func testStruct() {
+ var s1 = S3(source())
+ var s2 = S3(0)
+
+ sink(arg: s1.v) // $ flow=774
+ sink(arg: s2.v)
+ sink(arg: s1.getv()) // $ flow=774
+ sink(arg: s2.getv())
+
+ s1.v = 0
+ s2.v = source()
+
+ sink(arg: s1.v)
+ sink(arg: s2.v) // $ flow=783
+ sink(arg: s1.getv())
+ sink(arg: s2.getv()) // $ flow=783
+}
From 2448bc8ce2bb41a60375ffa5a1df4bde0cad1922 Mon Sep 17 00:00:00 2001
From: Tony Torralba
Date: Wed, 23 Aug 2023 10:46:57 +0200
Subject: [PATCH 080/788] Java: Add new Apache CXF models
---
.../lib/ext/org.apache.cxf.catalog.model.yml | 6 +
...rg.apache.cxf.common.classloader.model.yml | 8 +
.../ext/org.apache.cxf.common.jaxb.model.yml | 6 +
.../org.apache.cxf.common.logging.model.yml | 11 +
...rg.apache.cxf.configuration.jsse.model.yml | 7 +
...org.apache.cxf.feature.transform.model.yml | 8 +
.../lib/ext/org.apache.cxf.helpers.model.yml | 15 +
.../lib/ext/org.apache.cxf.resource.model.yml | 14 +
.../ext/org.apache.cxf.staxutils.model.yml | 6 +
...org.apache.cxf.tools.corba.utils.model.yml | 9 +
.../ext/org.apache.cxf.tools.util.model.yml | 15 +
.../CWE-022/semmle/tests/TaintedPath.expected | 682 +++++++++++-------
.../CWE-022/semmle/tests/mad/Test.java | 74 ++
.../security/CWE-022/semmle/tests/options | 2 +-
.../security/CWE-117/LogInjectionTest.java | 17 +
.../test/query-tests/security/CWE-117/options | 2 +-
.../security/CWE-918/mad/Test.java | 25 +-
.../test/query-tests/security/CWE-918/options | 2 +-
.../cxf/catalog/OASISCatalogManager.java | 7 +
.../common/classloader/ClassLoaderUtils.java | 19 +
.../org/apache/cxf/common/jaxb/JAXBUtils.java | 13 +
.../apache/cxf/common/logging/LogUtils.java | 20 +
.../cxf/configuration/jsse/SSLUtils.java | 7 +
.../org/apache/cxf/helpers/FileUtils.java | 65 ++
.../cxf/resource/ExtendedURIResolver.java | 9 +
.../org/apache/cxf/resource/URIResolver.java | 13 +
.../org/apache/cxf/staxutils/StaxUtils.java | 10 +
.../corba/utils/FileOutputStreamFactory.java | 19 +
.../corba/utils/OutputStreamFactory.java | 9 +
.../apache/cxf/tools/util/FileWriterUtil.java | 30 +
.../cxf/tools/util/OutputStreamCreator.java | 11 +
31 files changed, 866 insertions(+), 275 deletions(-)
create mode 100644 java/ql/lib/ext/org.apache.cxf.catalog.model.yml
create mode 100644 java/ql/lib/ext/org.apache.cxf.common.classloader.model.yml
create mode 100644 java/ql/lib/ext/org.apache.cxf.common.jaxb.model.yml
create mode 100644 java/ql/lib/ext/org.apache.cxf.common.logging.model.yml
create mode 100644 java/ql/lib/ext/org.apache.cxf.configuration.jsse.model.yml
create mode 100644 java/ql/lib/ext/org.apache.cxf.feature.transform.model.yml
create mode 100644 java/ql/lib/ext/org.apache.cxf.helpers.model.yml
create mode 100644 java/ql/lib/ext/org.apache.cxf.resource.model.yml
create mode 100644 java/ql/lib/ext/org.apache.cxf.staxutils.model.yml
create mode 100644 java/ql/lib/ext/org.apache.cxf.tools.corba.utils.model.yml
create mode 100644 java/ql/lib/ext/org.apache.cxf.tools.util.model.yml
create mode 100644 java/ql/test/stubs/apache-cxf/org/apache/cxf/catalog/OASISCatalogManager.java
create mode 100644 java/ql/test/stubs/apache-cxf/org/apache/cxf/common/classloader/ClassLoaderUtils.java
create mode 100644 java/ql/test/stubs/apache-cxf/org/apache/cxf/common/jaxb/JAXBUtils.java
create mode 100644 java/ql/test/stubs/apache-cxf/org/apache/cxf/common/logging/LogUtils.java
create mode 100644 java/ql/test/stubs/apache-cxf/org/apache/cxf/configuration/jsse/SSLUtils.java
create mode 100644 java/ql/test/stubs/apache-cxf/org/apache/cxf/helpers/FileUtils.java
create mode 100644 java/ql/test/stubs/apache-cxf/org/apache/cxf/resource/ExtendedURIResolver.java
create mode 100644 java/ql/test/stubs/apache-cxf/org/apache/cxf/resource/URIResolver.java
create mode 100644 java/ql/test/stubs/apache-cxf/org/apache/cxf/staxutils/StaxUtils.java
create mode 100644 java/ql/test/stubs/apache-cxf/org/apache/cxf/tools/corba/utils/FileOutputStreamFactory.java
create mode 100644 java/ql/test/stubs/apache-cxf/org/apache/cxf/tools/corba/utils/OutputStreamFactory.java
create mode 100644 java/ql/test/stubs/apache-cxf/org/apache/cxf/tools/util/FileWriterUtil.java
create mode 100644 java/ql/test/stubs/apache-cxf/org/apache/cxf/tools/util/OutputStreamCreator.java
diff --git a/java/ql/lib/ext/org.apache.cxf.catalog.model.yml b/java/ql/lib/ext/org.apache.cxf.catalog.model.yml
new file mode 100644
index 00000000000..9f453be772f
--- /dev/null
+++ b/java/ql/lib/ext/org.apache.cxf.catalog.model.yml
@@ -0,0 +1,6 @@
+extensions:
+ - addsTo:
+ pack: codeql/java-all
+ extensible: sinkModel
+ data:
+ - ["org.apache.cxf.catalog", "OASISCatalogManager", True, "loadCatalog", "(URL)", "", "Argument[0]", "request-forgery", "manual"]
diff --git a/java/ql/lib/ext/org.apache.cxf.common.classloader.model.yml b/java/ql/lib/ext/org.apache.cxf.common.classloader.model.yml
new file mode 100644
index 00000000000..131d1242fd0
--- /dev/null
+++ b/java/ql/lib/ext/org.apache.cxf.common.classloader.model.yml
@@ -0,0 +1,8 @@
+extensions:
+ - addsTo:
+ pack: codeql/java-all
+ extensible: sinkModel
+ data:
+ - ["org.apache.cxf.common.classloader", "ClassLoaderUtils", True, "getResourceAsStream", "(String,Class)", "", "Argument[0]", "path-injection", "manual"]
+ - ["org.apache.cxf.common.classloader", "ClassLoaderUtils", True, "getURLClassLoader", "(URL[],ClassLoader)", "", "Argument[0]", "request-forgery", "manual"]
+ - ["org.apache.cxf.common.classloader", "ClassLoaderUtils", True, "getURLClassLoader", "(List,ClassLoader)", "", "Argument[0]", "request-forgery", "manual"]
diff --git a/java/ql/lib/ext/org.apache.cxf.common.jaxb.model.yml b/java/ql/lib/ext/org.apache.cxf.common.jaxb.model.yml
new file mode 100644
index 00000000000..86fcf9605ed
--- /dev/null
+++ b/java/ql/lib/ext/org.apache.cxf.common.jaxb.model.yml
@@ -0,0 +1,6 @@
+extensions:
+ - addsTo:
+ pack: codeql/java-all
+ extensible: sinkModel
+ data:
+ - ["org.apache.cxf.common.jaxb", "JAXBUtils", True, "createFileCodeWriter", "", "", "Argument[0]", "path-injection", "manual"]
diff --git a/java/ql/lib/ext/org.apache.cxf.common.logging.model.yml b/java/ql/lib/ext/org.apache.cxf.common.logging.model.yml
new file mode 100644
index 00000000000..5bde245534b
--- /dev/null
+++ b/java/ql/lib/ext/org.apache.cxf.common.logging.model.yml
@@ -0,0 +1,11 @@
+extensions:
+ - addsTo:
+ pack: codeql/java-all
+ extensible: sinkModel
+ data:
+ - ["org.apache.cxf.common.logging", "LogUtils", True, "log", "(Logger,Level,String)", "", "Argument[2]", "log-injection", "manual"]
+ - ["org.apache.cxf.common.logging", "LogUtils", True, "log", "(Logger,Level,String,Object)", "", "Argument[2]", "log-injection", "manual"]
+ - ["org.apache.cxf.common.logging", "LogUtils", True, "log", "(Logger,Level,String,Object[])", "", "Argument[2]", "log-injection", "manual"]
+ - ["org.apache.cxf.common.logging", "LogUtils", True, "log", "(Logger,Level,String,Throwable)", "", "Argument[2]", "log-injection", "manual"]
+ - ["org.apache.cxf.common.logging", "LogUtils", True, "log", "(Logger,Level,String,Throwable,Object)", "", "Argument[2]", "log-injection", "manual"]
+ - ["org.apache.cxf.common.logging", "LogUtils", True, "log", "(Logger,Level,String,Throwable,Object[])", "", "Argument[2]", "log-injection", "manual"]
diff --git a/java/ql/lib/ext/org.apache.cxf.configuration.jsse.model.yml b/java/ql/lib/ext/org.apache.cxf.configuration.jsse.model.yml
new file mode 100644
index 00000000000..590cfbc0b6c
--- /dev/null
+++ b/java/ql/lib/ext/org.apache.cxf.configuration.jsse.model.yml
@@ -0,0 +1,7 @@
+extensions:
+ - addsTo:
+ pack: codeql/java-all
+ extensible: sinkModel
+ data:
+ - ["org.apache.cxf.configuration.jsse", "SSLUtils", True, "loadFile", "(String)", "", "Argument[0]", "path-injection", "manual"]
+ - ["org.apache.cxf.configuration.jsse", "TLSClientParameters", True, "setHostnameVerifier", "(HostnameVerifier)", "", "Argument[0]", "hostname-verification", "manual"]
diff --git a/java/ql/lib/ext/org.apache.cxf.feature.transform.model.yml b/java/ql/lib/ext/org.apache.cxf.feature.transform.model.yml
new file mode 100644
index 00000000000..04bca0634d5
--- /dev/null
+++ b/java/ql/lib/ext/org.apache.cxf.feature.transform.model.yml
@@ -0,0 +1,8 @@
+extensions:
+ - addsTo:
+ pack: codeql/java-all
+ extensible: sinkModel
+ data:
+ - ["org.apache.cxf.transform", "XSLTUtils", True, "transform", "(Templates,InputStream)", "", "Argument[0]", "xslt-injection", "manual"]
+ - ["org.apache.cxf.transform", "XSLTUtils", True, "transform", "(Templates,Reader)", "", "Argument[0]", "xslt-injection", "manual"]
+ - ["org.apache.cxf.transform", "XSLTUtils", True, "transform", "(Templates,Document)", "", "Argument[0]", "xslt-injection", "manual"]
diff --git a/java/ql/lib/ext/org.apache.cxf.helpers.model.yml b/java/ql/lib/ext/org.apache.cxf.helpers.model.yml
new file mode 100644
index 00000000000..5e8a29e2b11
--- /dev/null
+++ b/java/ql/lib/ext/org.apache.cxf.helpers.model.yml
@@ -0,0 +1,15 @@
+extensions:
+ - addsTo:
+ pack: codeql/java-all
+ extensible: sinkModel
+ data:
+ - ["org.apache.cxf.helpers", "FileUtils", True, "delete", "(File)", "", "Argument[0]", "path-injection", "manual"]
+ - ["org.apache.cxf.helpers", "FileUtils", True, "delete", "(File,boolean)", "", "Argument[0]", "path-injection", "manual"]
+ - ["org.apache.cxf.helpers", "FileUtils", True, "mkdir", "(File)", "", "Argument[0]", "path-injection", "manual"]
+ - ["org.apache.cxf.helpers", "FileUtils", True, "readLines", "(File)", "", "Argument[0]", "path-injection", "manual"]
+ - ["org.apache.cxf.helpers", "FileUtils", True, "removeDir", "(File)", "", "Argument[0]", "path-injection", "manual"]
+ - ["org.apache.cxf.helpers", "XPathUtils", True, "getValue", "(String,Node,QName)", "", "Argument[0]", "xpath-injection", "manual"]
+ - ["org.apache.cxf.helpers", "XPathUtils", True, "getValueList", "(String,Node)", "", "Argument[0]", "xpath-injection", "manual"]
+ - ["org.apache.cxf.helpers", "XPathUtils", True, "getValueNode", "(String,Node)", "", "Argument[0]", "xpath-injection", "manual"]
+ - ["org.apache.cxf.helpers", "XPathUtils", True, "getValueString", "(String,Node)", "", "Argument[0]", "xpath-injection", "manual"]
+ - ["org.apache.cxf.helpers", "XPathUtils", True, "isExist", "(String,Node,QName)", "", "Argument[0]", "xpath-injection", "manual"]
diff --git a/java/ql/lib/ext/org.apache.cxf.resource.model.yml b/java/ql/lib/ext/org.apache.cxf.resource.model.yml
new file mode 100644
index 00000000000..c73c9a4ac8a
--- /dev/null
+++ b/java/ql/lib/ext/org.apache.cxf.resource.model.yml
@@ -0,0 +1,14 @@
+extensions:
+ - addsTo:
+ pack: codeql/java-all
+ extensible: sinkModel
+ data:
+ - ["org.apache.cxf.resource", "ExtendedURIResolver", True, "resolve", "(String,String)", "", "Argument[0]", "request-forgery", "manual"]
+ - ["org.apache.cxf.resource", "ExtendedURIResolver", True, "resolve", "(String,String)", "", "Argument[1]", "path-injection", "manual"]
+ - ["org.apache.cxf.resource", "URIResolver", True, "URIResolver", "(String)", "", "Argument[0]", "request-forgery", "manual"]
+ - ["org.apache.cxf.resource", "URIResolver", True, "URIResolver", "(String,String)", "", "Argument[0]", "path-injection", "manual"]
+ - ["org.apache.cxf.resource", "URIResolver", True, "URIResolver", "(String,String)", "", "Argument[1]", "request-forgery", "manual"]
+ - ["org.apache.cxf.resource", "URIResolver", True, "URIResolver", "(String,String,Class)", "", "Argument[0]", "path-injection", "manual"]
+ - ["org.apache.cxf.resource", "URIResolver", True, "URIResolver", "(String,String,Class)", "", "Argument[1]", "request-forgery", "manual"]
+ - ["org.apache.cxf.resource", "URIResolver", True, "resolve", "(String,String,Class)", "", "Argument[0]", "path-injection", "manual"]
+ - ["org.apache.cxf.resource", "URIResolver", True, "resolve", "(String,String,Class)", "", "Argument[1]", "request-forgery", "manual"]
diff --git a/java/ql/lib/ext/org.apache.cxf.staxutils.model.yml b/java/ql/lib/ext/org.apache.cxf.staxutils.model.yml
new file mode 100644
index 00000000000..959fc3d6e82
--- /dev/null
+++ b/java/ql/lib/ext/org.apache.cxf.staxutils.model.yml
@@ -0,0 +1,6 @@
+extensions:
+ - addsTo:
+ pack: codeql/java-all
+ extensible: sinkModel
+ data:
+ - ["org.apache.cxf.staxutils", "StaxUtils", True, "read", "(File)", "", "Argument[0]", "path-injection", "manual"]
diff --git a/java/ql/lib/ext/org.apache.cxf.tools.corba.utils.model.yml b/java/ql/lib/ext/org.apache.cxf.tools.corba.utils.model.yml
new file mode 100644
index 00000000000..c6bb4c0d90b
--- /dev/null
+++ b/java/ql/lib/ext/org.apache.cxf.tools.corba.utils.model.yml
@@ -0,0 +1,9 @@
+extensions:
+ - addsTo:
+ pack: codeql/java-all
+ extensible: sinkModel
+ data:
+ - ["org.apache.cxf.tools.corba.utils", "FileOutputStreamFactory", true, "FileOutputStreamFactory", "(String)", "", "Argument[0]", "path-injection", "manual"]
+ - ["org.apache.cxf.tools.corba.utils", "FileOutputStreamFactory", true, "FileOutputStreamFactory", "(String,FileOutputStreamFactory)", "", "Argument[0]", "path-injection", "manual"]
+ - ["org.apache.cxf.tools.corba.utils", "OutputStreamFactory", true, "createOutputStream", "(String)", "", "Argument[0]", "path-injection", "manual"]
+ - ["org.apache.cxf.tools.corba.utils", "OutputStreamFactory", true, "createOutputStream", "(String,String)", "", "Argument[0..1]", "path-injection", "manual"]
diff --git a/java/ql/lib/ext/org.apache.cxf.tools.util.model.yml b/java/ql/lib/ext/org.apache.cxf.tools.util.model.yml
new file mode 100644
index 00000000000..aeebecb82e3
--- /dev/null
+++ b/java/ql/lib/ext/org.apache.cxf.tools.util.model.yml
@@ -0,0 +1,15 @@
+extensions:
+ - addsTo:
+ pack: codeql/java-all
+ extensible: sinkModel
+ data:
+ - ["org.apache.cxf.tools.util", "FileWriterUtil", True, "FileWriterUtil", "(String,OutputStreamCreator)", "", "Argument[0]", "path-injection", "manual"]
+ - ["org.apache.cxf.tools.util", "FileWriterUtil", True, "buildDir", "(String)", "", "Argument[0]", "path-injection", "manual"]
+ - ["org.apache.cxf.tools.util", "FileWriterUtil", True, "getFileToWrite", "(String,String)", "", "Argument[0]", "path-injection", "manual"]
+ - ["org.apache.cxf.tools.util", "FileWriterUtil", True, "getFileToWrite", "(String,String)", "", "Argument[1]", "path-injection", "manual"]
+ - ["org.apache.cxf.tools.util", "FileWriterUtil", True, "getWriter", "(File,String)", "", "Argument[0]", "path-injection", "manual"]
+ - ["org.apache.cxf.tools.util", "FileWriterUtil", True, "getWriter", "(String,String)", "", "Argument[0]", "path-injection", "manual"]
+ - ["org.apache.cxf.tools.util", "FileWriterUtil", True, "getWriter", "(String,String)", "", "Argument[1]", "path-injection", "manual"]
+ - ["org.apache.cxf.tools.util", "FileWriterUtil", True, "getWriter", "(String,String,String)", "", "Argument[0]", "path-injection", "manual"]
+ - ["org.apache.cxf.tools.util", "FileWriterUtil", True, "getWriter", "(String,String,String)", "", "Argument[1]", "path-injection", "manual"]
+ - ["org.apache.cxf.tools.util", "OutputStreamCreator", true, "createOutputStream", "(File)", "", "Argument[0]", "path-injection", "manual"]
diff --git a/java/ql/test/query-tests/security/CWE-022/semmle/tests/TaintedPath.expected b/java/ql/test/query-tests/security/CWE-022/semmle/tests/TaintedPath.expected
index 2f9a646f9c1..8ebc5a03a31 100644
--- a/java/ql/test/query-tests/security/CWE-022/semmle/tests/TaintedPath.expected
+++ b/java/ql/test/query-tests/security/CWE-022/semmle/tests/TaintedPath.expected
@@ -19,114 +19,170 @@ edges
| Test.java:100:32:100:32 | t : String | Test.java:100:12:100:45 | new URI(...) |
| Test.java:100:32:100:32 | t : String | Test.java:101:41:101:41 | t : String |
| Test.java:101:41:101:41 | t : String | Test.java:101:12:101:54 | new URI(...) |
-| mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:35:61:35:68 | source(...) : String |
-| mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:37:41:37:48 | source(...) : String |
-| mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:39:56:39:63 | source(...) : String |
-| mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:41:46:41:53 | source(...) : String |
-| mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:43:38:43:45 | source(...) : String |
-| mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:45:36:45:43 | source(...) : String |
-| mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:47:31:47:38 | source(...) : String |
-| mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:49:33:49:40 | source(...) : String |
-| mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:51:27:51:34 | source(...) : String |
-| mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:53:27:53:34 | source(...) : String |
-| mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:55:40:55:47 | source(...) : String |
-| mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:57:47:57:54 | source(...) : String |
-| mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:59:40:59:47 | source(...) : String |
-| mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:61:38:61:45 | source(...) : String |
-| mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:63:33:63:40 | source(...) : String |
-| mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:65:33:65:40 | source(...) : String |
-| mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:67:41:67:48 | source(...) : String |
-| mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:69:42:69:49 | source(...) : String |
-| mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:71:37:71:44 | source(...) : String |
-| mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:73:29:73:36 | source(...) : String |
-| mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:75:37:75:44 | source(...) : String |
-| mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:77:28:77:35 | source(...) : String |
-| mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:79:33:79:40 | source(...) : String |
-| mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:81:40:81:47 | source(...) : String |
-| mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:83:40:83:47 | source(...) : String |
-| mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:84:40:84:47 | source(...) : String |
-| mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:86:38:86:45 | source(...) : String |
-| mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:88:28:88:35 | source(...) : String |
-| mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:89:28:89:35 | source(...) : String |
-| mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:90:28:90:35 | source(...) : String |
-| mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:92:34:92:41 | source(...) : String |
-| mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:93:34:93:41 | source(...) : String |
-| mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:95:33:95:40 | source(...) : String |
-| mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:97:42:97:49 | source(...) : String |
-| mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:99:50:99:57 | source(...) : String |
-| mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:101:54:101:61 | source(...) : String |
-| mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:103:50:103:57 | source(...) : String |
-| mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:105:35:105:42 | source(...) : String |
-| mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:107:48:107:55 | source(...) : String |
-| mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:109:37:109:44 | source(...) : String |
-| mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:111:35:111:42 | source(...) : String |
-| mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:116:37:116:44 | source(...) : String |
-| mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:118:74:118:81 | source(...) : String |
-| mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:120:68:120:75 | source(...) : String |
-| mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:122:68:122:75 | source(...) : String |
-| mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:124:30:124:37 | source(...) : String |
-| mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:129:30:129:37 | source(...) : String |
-| mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:134:33:134:40 | source(...) : String |
-| mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:136:27:136:34 | source(...) : String |
-| mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:138:28:138:35 | source(...) : String |
-| mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:140:29:140:36 | source(...) : String |
-| mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:145:27:145:34 | source(...) : String |
-| mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:147:26:147:33 | source(...) : String |
-| mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:152:29:152:36 | source(...) : String |
-| mad/Test.java:35:61:35:68 | source(...) : String | mad/Test.java:35:52:35:68 | (...)... |
-| mad/Test.java:37:41:37:48 | source(...) : String | mad/Test.java:37:32:37:48 | (...)... |
-| mad/Test.java:39:56:39:63 | source(...) : String | mad/Test.java:39:47:39:63 | (...)... |
-| mad/Test.java:41:46:41:53 | source(...) : String | mad/Test.java:41:39:41:53 | (...)... |
-| mad/Test.java:43:38:43:45 | source(...) : String | mad/Test.java:43:31:43:45 | (...)... |
-| mad/Test.java:45:36:45:43 | source(...) : String | mad/Test.java:45:29:45:43 | (...)... |
-| mad/Test.java:47:31:47:38 | source(...) : String | mad/Test.java:47:24:47:38 | (...)... |
-| mad/Test.java:49:33:49:40 | source(...) : String | mad/Test.java:49:24:49:40 | (...)... |
-| mad/Test.java:51:27:51:34 | source(...) : String | mad/Test.java:51:20:51:34 | (...)... |
-| mad/Test.java:53:27:53:34 | source(...) : String | mad/Test.java:53:20:53:34 | (...)... |
-| mad/Test.java:55:40:55:47 | source(...) : String | mad/Test.java:55:33:55:47 | (...)... |
-| mad/Test.java:57:47:57:54 | source(...) : String | mad/Test.java:57:40:57:54 | (...)... |
-| mad/Test.java:59:40:59:47 | source(...) : String | mad/Test.java:59:33:59:47 | (...)... |
-| mad/Test.java:61:38:61:45 | source(...) : String | mad/Test.java:61:31:61:45 | (...)... |
-| mad/Test.java:63:33:63:40 | source(...) : String | mad/Test.java:63:26:63:40 | (...)... |
-| mad/Test.java:65:33:65:40 | source(...) : String | mad/Test.java:65:26:65:40 | (...)... |
-| mad/Test.java:67:41:67:48 | source(...) : String | mad/Test.java:67:34:67:48 | (...)... |
-| mad/Test.java:69:42:69:49 | source(...) : String | mad/Test.java:69:35:69:49 | (...)... |
-| mad/Test.java:71:37:71:44 | source(...) : String | mad/Test.java:71:30:71:44 | (...)... |
-| mad/Test.java:73:29:73:36 | source(...) : String | mad/Test.java:73:22:73:36 | (...)... |
-| mad/Test.java:75:37:75:44 | source(...) : String | mad/Test.java:75:30:75:44 | (...)... |
-| mad/Test.java:77:28:77:35 | source(...) : String | mad/Test.java:77:21:77:35 | (...)... |
-| mad/Test.java:79:33:79:40 | source(...) : String | mad/Test.java:79:26:79:40 | (...)... |
-| mad/Test.java:81:40:81:47 | source(...) : String | mad/Test.java:81:33:81:47 | (...)... |
-| mad/Test.java:83:40:83:47 | source(...) : String | mad/Test.java:83:33:83:47 | (...)... |
-| mad/Test.java:84:40:84:47 | source(...) : String | mad/Test.java:84:33:84:47 | (...)... |
-| mad/Test.java:86:38:86:45 | source(...) : String | mad/Test.java:86:31:86:45 | (...)... |
-| mad/Test.java:88:28:88:35 | source(...) : String | mad/Test.java:88:21:88:35 | (...)... |
-| mad/Test.java:89:28:89:35 | source(...) : String | mad/Test.java:89:21:89:35 | (...)... |
-| mad/Test.java:90:28:90:35 | source(...) : String | mad/Test.java:90:21:90:35 | (...)... |
-| mad/Test.java:92:34:92:41 | source(...) : String | mad/Test.java:92:27:92:41 | (...)... |
-| mad/Test.java:93:34:93:41 | source(...) : String | mad/Test.java:93:27:93:41 | (...)... |
-| mad/Test.java:95:33:95:40 | source(...) : String | mad/Test.java:95:26:95:40 | (...)... |
-| mad/Test.java:97:42:97:49 | source(...) : String | mad/Test.java:97:35:97:49 | (...)... |
-| mad/Test.java:99:50:99:57 | source(...) : String | mad/Test.java:99:41:99:57 | (...)... |
-| mad/Test.java:101:54:101:61 | source(...) : String | mad/Test.java:101:45:101:61 | (...)... |
-| mad/Test.java:103:50:103:57 | source(...) : String | mad/Test.java:103:43:103:57 | (...)... |
-| mad/Test.java:105:35:105:42 | source(...) : String | mad/Test.java:105:28:105:42 | (...)... |
-| mad/Test.java:107:48:107:55 | source(...) : String | mad/Test.java:107:41:107:55 | (...)... |
-| mad/Test.java:109:37:109:44 | source(...) : String | mad/Test.java:109:28:109:44 | (...)... |
-| mad/Test.java:111:35:111:42 | source(...) : String | mad/Test.java:111:28:111:42 | (...)... |
-| mad/Test.java:116:37:116:44 | source(...) : String | mad/Test.java:116:30:116:44 | (...)... |
-| mad/Test.java:118:74:118:81 | source(...) : String | mad/Test.java:118:40:118:81 | (...)... |
-| mad/Test.java:120:68:120:75 | source(...) : String | mad/Test.java:120:34:120:75 | (...)... |
-| mad/Test.java:122:68:122:75 | source(...) : String | mad/Test.java:122:34:122:75 | (...)... |
-| mad/Test.java:124:30:124:37 | source(...) : String | mad/Test.java:124:23:124:37 | (...)... |
-| mad/Test.java:129:30:129:37 | source(...) : String | mad/Test.java:129:23:129:37 | (...)... |
-| mad/Test.java:134:33:134:40 | source(...) : String | mad/Test.java:134:23:134:40 | (...)... |
-| mad/Test.java:136:27:136:34 | source(...) : String | mad/Test.java:136:20:136:34 | (...)... |
-| mad/Test.java:138:28:138:35 | source(...) : String | mad/Test.java:138:21:138:35 | (...)... |
-| mad/Test.java:140:29:140:36 | source(...) : String | mad/Test.java:140:22:140:36 | (...)... |
-| mad/Test.java:145:27:145:34 | source(...) : String | mad/Test.java:145:20:145:34 | (...)... |
-| mad/Test.java:147:26:147:33 | source(...) : String | mad/Test.java:147:19:147:33 | (...)... |
-| mad/Test.java:152:29:152:36 | source(...) : String | mad/Test.java:152:20:152:36 | (...)... |
+| mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:45:61:45:68 | source(...) : String |
+| mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:47:41:47:48 | source(...) : String |
+| mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:49:56:49:63 | source(...) : String |
+| mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:51:46:51:53 | source(...) : String |
+| mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:53:38:53:45 | source(...) : String |
+| mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:55:36:55:43 | source(...) : String |
+| mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:57:31:57:38 | source(...) : String |
+| mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:59:33:59:40 | source(...) : String |
+| mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:61:27:61:34 | source(...) : String |
+| mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:63:27:63:34 | source(...) : String |
+| mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:65:40:65:47 | source(...) : String |
+| mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:67:47:67:54 | source(...) : String |
+| mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:69:40:69:47 | source(...) : String |
+| mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:71:38:71:45 | source(...) : String |
+| mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:73:33:73:40 | source(...) : String |
+| mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:75:33:75:40 | source(...) : String |
+| mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:77:41:77:48 | source(...) : String |
+| mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:79:42:79:49 | source(...) : String |
+| mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:81:37:81:44 | source(...) : String |
+| mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:83:29:83:36 | source(...) : String |
+| mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:85:37:85:44 | source(...) : String |
+| mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:87:28:87:35 | source(...) : String |
+| mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:89:33:89:40 | source(...) : String |
+| mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:91:40:91:47 | source(...) : String |
+| mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:93:40:93:47 | source(...) : String |
+| mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:94:40:94:47 | source(...) : String |
+| mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:96:38:96:45 | source(...) : String |
+| mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:98:28:98:35 | source(...) : String |
+| mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:99:28:99:35 | source(...) : String |
+| mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:100:28:100:35 | source(...) : String |
+| mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:102:34:102:41 | source(...) : String |
+| mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:103:34:103:41 | source(...) : String |
+| mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:105:33:105:40 | source(...) : String |
+| mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:107:42:107:49 | source(...) : String |
+| mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:109:50:109:57 | source(...) : String |
+| mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:111:54:111:61 | source(...) : String |
+| mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:113:50:113:57 | source(...) : String |
+| mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:115:35:115:42 | source(...) : String |
+| mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:117:48:117:55 | source(...) : String |
+| mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:119:37:119:44 | source(...) : String |
+| mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:121:35:121:42 | source(...) : String |
+| mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:123:55:123:62 | source(...) : String |
+| mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:125:47:125:54 | source(...) : String |
+| mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:127:47:127:54 | source(...) : String |
+| mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:131:35:131:42 | source(...) : String |
+| mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:135:56:135:63 | source(...) : String |
+| mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:137:56:137:63 | source(...) : String |
+| mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:141:59:141:66 | source(...) : String |
+| mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:143:59:143:66 | source(...) : String |
+| mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:145:58:145:65 | source(...) : String |
+| mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:147:34:147:41 | source(...) : String |
+| mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:149:34:149:41 | source(...) : String |
+| mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:151:44:151:51 | source(...) : String |
+| mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:153:31:153:38 | source(...) : String |
+| mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:155:46:155:53 | source(...) : String |
+| mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:157:46:157:53 | source(...) : String |
+| mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:159:67:159:74 | source(...) : String |
+| mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:161:67:161:74 | source(...) : String |
+| mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:163:73:163:80 | source(...) : String |
+| mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:166:37:166:44 | source(...) : String |
+| mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:168:48:168:55 | source(...) : String |
+| mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:170:54:170:61 | source(...) : String |
+| mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:172:69:172:76 | source(...) : String |
+| mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:174:47:174:54 | source(...) : String |
+| mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:176:49:176:56 | source(...) : String |
+| mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:178:64:178:71 | source(...) : String |
+| mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:180:49:180:56 | source(...) : String |
+| mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:182:64:182:71 | source(...) : String |
+| mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:184:61:184:68 | source(...) : String |
+| mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:190:37:190:44 | source(...) : String |
+| mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:192:74:192:81 | source(...) : String |
+| mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:194:68:194:75 | source(...) : String |
+| mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:196:68:196:75 | source(...) : String |
+| mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:198:30:198:37 | source(...) : String |
+| mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:203:30:203:37 | source(...) : String |
+| mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:208:33:208:40 | source(...) : String |
+| mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:210:27:210:34 | source(...) : String |
+| mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:212:28:212:35 | source(...) : String |
+| mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:214:29:214:36 | source(...) : String |
+| mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:219:27:219:34 | source(...) : String |
+| mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:221:26:221:33 | source(...) : String |
+| mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:226:29:226:36 | source(...) : String |
+| mad/Test.java:45:61:45:68 | source(...) : String | mad/Test.java:45:52:45:68 | (...)... |
+| mad/Test.java:47:41:47:48 | source(...) : String | mad/Test.java:47:32:47:48 | (...)... |
+| mad/Test.java:49:56:49:63 | source(...) : String | mad/Test.java:49:47:49:63 | (...)... |
+| mad/Test.java:51:46:51:53 | source(...) : String | mad/Test.java:51:39:51:53 | (...)... |
+| mad/Test.java:53:38:53:45 | source(...) : String | mad/Test.java:53:31:53:45 | (...)... |
+| mad/Test.java:55:36:55:43 | source(...) : String | mad/Test.java:55:29:55:43 | (...)... |
+| mad/Test.java:57:31:57:38 | source(...) : String | mad/Test.java:57:24:57:38 | (...)... |
+| mad/Test.java:59:33:59:40 | source(...) : String | mad/Test.java:59:24:59:40 | (...)... |
+| mad/Test.java:61:27:61:34 | source(...) : String | mad/Test.java:61:20:61:34 | (...)... |
+| mad/Test.java:63:27:63:34 | source(...) : String | mad/Test.java:63:20:63:34 | (...)... |
+| mad/Test.java:65:40:65:47 | source(...) : String | mad/Test.java:65:33:65:47 | (...)... |
+| mad/Test.java:67:47:67:54 | source(...) : String | mad/Test.java:67:40:67:54 | (...)... |
+| mad/Test.java:69:40:69:47 | source(...) : String | mad/Test.java:69:33:69:47 | (...)... |
+| mad/Test.java:71:38:71:45 | source(...) : String | mad/Test.java:71:31:71:45 | (...)... |
+| mad/Test.java:73:33:73:40 | source(...) : String | mad/Test.java:73:26:73:40 | (...)... |
+| mad/Test.java:75:33:75:40 | source(...) : String | mad/Test.java:75:26:75:40 | (...)... |
+| mad/Test.java:77:41:77:48 | source(...) : String | mad/Test.java:77:34:77:48 | (...)... |
+| mad/Test.java:79:42:79:49 | source(...) : String | mad/Test.java:79:35:79:49 | (...)... |
+| mad/Test.java:81:37:81:44 | source(...) : String | mad/Test.java:81:30:81:44 | (...)... |
+| mad/Test.java:83:29:83:36 | source(...) : String | mad/Test.java:83:22:83:36 | (...)... |
+| mad/Test.java:85:37:85:44 | source(...) : String | mad/Test.java:85:30:85:44 | (...)... |
+| mad/Test.java:87:28:87:35 | source(...) : String | mad/Test.java:87:21:87:35 | (...)... |
+| mad/Test.java:89:33:89:40 | source(...) : String | mad/Test.java:89:26:89:40 | (...)... |
+| mad/Test.java:91:40:91:47 | source(...) : String | mad/Test.java:91:33:91:47 | (...)... |
+| mad/Test.java:93:40:93:47 | source(...) : String | mad/Test.java:93:33:93:47 | (...)... |
+| mad/Test.java:94:40:94:47 | source(...) : String | mad/Test.java:94:33:94:47 | (...)... |
+| mad/Test.java:96:38:96:45 | source(...) : String | mad/Test.java:96:31:96:45 | (...)... |
+| mad/Test.java:98:28:98:35 | source(...) : String | mad/Test.java:98:21:98:35 | (...)... |
+| mad/Test.java:99:28:99:35 | source(...) : String | mad/Test.java:99:21:99:35 | (...)... |
+| mad/Test.java:100:28:100:35 | source(...) : String | mad/Test.java:100:21:100:35 | (...)... |
+| mad/Test.java:102:34:102:41 | source(...) : String | mad/Test.java:102:27:102:41 | (...)... |
+| mad/Test.java:103:34:103:41 | source(...) : String | mad/Test.java:103:27:103:41 | (...)... |
+| mad/Test.java:105:33:105:40 | source(...) : String | mad/Test.java:105:26:105:40 | (...)... |
+| mad/Test.java:107:42:107:49 | source(...) : String | mad/Test.java:107:35:107:49 | (...)... |
+| mad/Test.java:109:50:109:57 | source(...) : String | mad/Test.java:109:41:109:57 | (...)... |
+| mad/Test.java:111:54:111:61 | source(...) : String | mad/Test.java:111:45:111:61 | (...)... |
+| mad/Test.java:113:50:113:57 | source(...) : String | mad/Test.java:113:43:113:57 | (...)... |
+| mad/Test.java:115:35:115:42 | source(...) : String | mad/Test.java:115:28:115:42 | (...)... |
+| mad/Test.java:117:48:117:55 | source(...) : String | mad/Test.java:117:41:117:55 | (...)... |
+| mad/Test.java:119:37:119:44 | source(...) : String | mad/Test.java:119:28:119:44 | (...)... |
+| mad/Test.java:121:35:121:42 | source(...) : String | mad/Test.java:121:28:121:42 | (...)... |
+| mad/Test.java:123:55:123:62 | source(...) : String | mad/Test.java:123:46:123:62 | (...)... |
+| mad/Test.java:125:47:125:54 | source(...) : String | mad/Test.java:125:40:125:54 | (...)... |
+| mad/Test.java:127:47:127:54 | source(...) : String | mad/Test.java:127:40:127:54 | (...)... |
+| mad/Test.java:131:35:131:42 | source(...) : String | mad/Test.java:131:26:131:42 | (...)... |
+| mad/Test.java:135:56:135:63 | source(...) : String | mad/Test.java:135:49:135:63 | (...)... |
+| mad/Test.java:137:56:137:63 | source(...) : String | mad/Test.java:137:49:137:63 | (...)... |
+| mad/Test.java:141:59:141:66 | source(...) : String | mad/Test.java:141:52:141:66 | (...)... |
+| mad/Test.java:143:59:143:66 | source(...) : String | mad/Test.java:143:52:143:66 | (...)... |
+| mad/Test.java:145:58:145:65 | source(...) : String | mad/Test.java:145:49:145:65 | (...)... |
+| mad/Test.java:147:34:147:41 | source(...) : String | mad/Test.java:147:25:147:41 | (...)... |
+| mad/Test.java:149:34:149:41 | source(...) : String | mad/Test.java:149:25:149:41 | (...)... |
+| mad/Test.java:151:44:151:51 | source(...) : String | mad/Test.java:151:35:151:51 | (...)... |
+| mad/Test.java:153:31:153:38 | source(...) : String | mad/Test.java:153:24:153:38 | (...)... |
+| mad/Test.java:155:46:155:53 | source(...) : String | mad/Test.java:155:37:155:53 | (...)... |
+| mad/Test.java:157:46:157:53 | source(...) : String | mad/Test.java:157:37:157:53 | (...)... |
+| mad/Test.java:159:67:159:74 | source(...) : String | mad/Test.java:159:58:159:74 | (...)... |
+| mad/Test.java:161:67:161:74 | source(...) : String | mad/Test.java:161:58:161:74 | (...)... |
+| mad/Test.java:163:73:163:80 | source(...) : String | mad/Test.java:163:64:163:80 | (...)... |
+| mad/Test.java:166:37:166:44 | source(...) : String | mad/Test.java:166:28:166:44 | (...)... |
+| mad/Test.java:168:48:168:55 | source(...) : String | mad/Test.java:168:39:168:55 | (...)... |
+| mad/Test.java:170:54:170:61 | source(...) : String | mad/Test.java:170:45:170:61 | (...)... |
+| mad/Test.java:172:69:172:76 | source(...) : String | mad/Test.java:172:60:172:76 | (...)... |
+| mad/Test.java:174:47:174:54 | source(...) : String | mad/Test.java:174:40:174:54 | (...)... |
+| mad/Test.java:176:49:176:56 | source(...) : String | mad/Test.java:176:40:176:56 | (...)... |
+| mad/Test.java:178:64:178:71 | source(...) : String | mad/Test.java:178:55:178:71 | (...)... |
+| mad/Test.java:180:49:180:56 | source(...) : String | mad/Test.java:180:40:180:56 | (...)... |
+| mad/Test.java:182:64:182:71 | source(...) : String | mad/Test.java:182:55:182:71 | (...)... |
+| mad/Test.java:184:61:184:68 | source(...) : String | mad/Test.java:184:54:184:68 | (...)... |
+| mad/Test.java:190:37:190:44 | source(...) : String | mad/Test.java:190:30:190:44 | (...)... |
+| mad/Test.java:192:74:192:81 | source(...) : String | mad/Test.java:192:40:192:81 | (...)... |
+| mad/Test.java:194:68:194:75 | source(...) : String | mad/Test.java:194:34:194:75 | (...)... |
+| mad/Test.java:196:68:196:75 | source(...) : String | mad/Test.java:196:34:196:75 | (...)... |
+| mad/Test.java:198:30:198:37 | source(...) : String | mad/Test.java:198:23:198:37 | (...)... |
+| mad/Test.java:203:30:203:37 | source(...) : String | mad/Test.java:203:23:203:37 | (...)... |
+| mad/Test.java:208:33:208:40 | source(...) : String | mad/Test.java:208:23:208:40 | (...)... |
+| mad/Test.java:210:27:210:34 | source(...) : String | mad/Test.java:210:20:210:34 | (...)... |
+| mad/Test.java:212:28:212:35 | source(...) : String | mad/Test.java:212:21:212:35 | (...)... |
+| mad/Test.java:214:29:214:36 | source(...) : String | mad/Test.java:214:22:214:36 | (...)... |
+| mad/Test.java:219:27:219:34 | source(...) : String | mad/Test.java:219:20:219:34 | (...)... |
+| mad/Test.java:221:26:221:33 | source(...) : String | mad/Test.java:221:19:221:33 | (...)... |
+| mad/Test.java:226:29:226:36 | source(...) : String | mad/Test.java:226:20:226:36 | (...)... |
nodes
| Test.java:19:18:19:38 | getHostName(...) : String | semmle.label | getHostName(...) : String |
| Test.java:24:20:24:23 | temp | semmle.label | temp |
@@ -152,115 +208,171 @@ nodes
| Test.java:100:32:100:32 | t : String | semmle.label | t : String |
| Test.java:101:12:101:54 | new URI(...) | semmle.label | new URI(...) |
| Test.java:101:41:101:41 | t : String | semmle.label | t : String |
-| mad/Test.java:30:16:30:36 | getHostName(...) : String | semmle.label | getHostName(...) : String |
-| mad/Test.java:35:52:35:68 | (...)... | semmle.label | (...)... |
-| mad/Test.java:35:61:35:68 | source(...) : String | semmle.label | source(...) : String |
-| mad/Test.java:37:32:37:48 | (...)... | semmle.label | (...)... |
-| mad/Test.java:37:41:37:48 | source(...) : String | semmle.label | source(...) : String |
-| mad/Test.java:39:47:39:63 | (...)... | semmle.label | (...)... |
-| mad/Test.java:39:56:39:63 | source(...) : String | semmle.label | source(...) : String |
-| mad/Test.java:41:39:41:53 | (...)... | semmle.label | (...)... |
-| mad/Test.java:41:46:41:53 | source(...) : String | semmle.label | source(...) : String |
-| mad/Test.java:43:31:43:45 | (...)... | semmle.label | (...)... |
-| mad/Test.java:43:38:43:45 | source(...) : String | semmle.label | source(...) : String |
-| mad/Test.java:45:29:45:43 | (...)... | semmle.label | (...)... |
-| mad/Test.java:45:36:45:43 | source(...) : String | semmle.label | source(...) : String |
-| mad/Test.java:47:24:47:38 | (...)... | semmle.label | (...)... |
-| mad/Test.java:47:31:47:38 | source(...) : String | semmle.label | source(...) : String |
-| mad/Test.java:49:24:49:40 | (...)... | semmle.label | (...)... |
-| mad/Test.java:49:33:49:40 | source(...) : String | semmle.label | source(...) : String |
-| mad/Test.java:51:20:51:34 | (...)... | semmle.label | (...)... |
-| mad/Test.java:51:27:51:34 | source(...) : String | semmle.label | source(...) : String |
-| mad/Test.java:53:20:53:34 | (...)... | semmle.label | (...)... |
-| mad/Test.java:53:27:53:34 | source(...) : String | semmle.label | source(...) : String |
-| mad/Test.java:55:33:55:47 | (...)... | semmle.label | (...)... |
-| mad/Test.java:55:40:55:47 | source(...) : String | semmle.label | source(...) : String |
-| mad/Test.java:57:40:57:54 | (...)... | semmle.label | (...)... |
-| mad/Test.java:57:47:57:54 | source(...) : String | semmle.label | source(...) : String |
-| mad/Test.java:59:33:59:47 | (...)... | semmle.label | (...)... |
-| mad/Test.java:59:40:59:47 | source(...) : String | semmle.label | source(...) : String |
-| mad/Test.java:61:31:61:45 | (...)... | semmle.label | (...)... |
-| mad/Test.java:61:38:61:45 | source(...) : String | semmle.label | source(...) : String |
-| mad/Test.java:63:26:63:40 | (...)... | semmle.label | (...)... |
-| mad/Test.java:63:33:63:40 | source(...) : String | semmle.label | source(...) : String |
-| mad/Test.java:65:26:65:40 | (...)... | semmle.label | (...)... |
-| mad/Test.java:65:33:65:40 | source(...) : String | semmle.label | source(...) : String |
-| mad/Test.java:67:34:67:48 | (...)... | semmle.label | (...)... |
-| mad/Test.java:67:41:67:48 | source(...) : String | semmle.label | source(...) : String |
-| mad/Test.java:69:35:69:49 | (...)... | semmle.label | (...)... |
-| mad/Test.java:69:42:69:49 | source(...) : String | semmle.label | source(...) : String |
-| mad/Test.java:71:30:71:44 | (...)... | semmle.label | (...)... |
-| mad/Test.java:71:37:71:44 | source(...) : String | semmle.label | source(...) : String |
-| mad/Test.java:73:22:73:36 | (...)... | semmle.label | (...)... |
-| mad/Test.java:73:29:73:36 | source(...) : String | semmle.label | source(...) : String |
-| mad/Test.java:75:30:75:44 | (...)... | semmle.label | (...)... |
-| mad/Test.java:75:37:75:44 | source(...) : String | semmle.label | source(...) : String |
-| mad/Test.java:77:21:77:35 | (...)... | semmle.label | (...)... |
-| mad/Test.java:77:28:77:35 | source(...) : String | semmle.label | source(...) : String |
-| mad/Test.java:79:26:79:40 | (...)... | semmle.label | (...)... |
-| mad/Test.java:79:33:79:40 | source(...) : String | semmle.label | source(...) : String |
-| mad/Test.java:81:33:81:47 | (...)... | semmle.label | (...)... |
-| mad/Test.java:81:40:81:47 | source(...) : String | semmle.label | source(...) : String |
-| mad/Test.java:83:33:83:47 | (...)... | semmle.label | (...)... |
-| mad/Test.java:83:40:83:47 | source(...) : String | semmle.label | source(...) : String |
-| mad/Test.java:84:33:84:47 | (...)... | semmle.label | (...)... |
-| mad/Test.java:84:40:84:47 | source(...) : String | semmle.label | source(...) : String |
-| mad/Test.java:86:31:86:45 | (...)... | semmle.label | (...)... |
-| mad/Test.java:86:38:86:45 | source(...) : String | semmle.label | source(...) : String |
-| mad/Test.java:88:21:88:35 | (...)... | semmle.label | (...)... |
-| mad/Test.java:88:28:88:35 | source(...) : String | semmle.label | source(...) : String |
-| mad/Test.java:89:21:89:35 | (...)... | semmle.label | (...)... |
-| mad/Test.java:89:28:89:35 | source(...) : String | semmle.label | source(...) : String |
-| mad/Test.java:90:21:90:35 | (...)... | semmle.label | (...)... |
-| mad/Test.java:90:28:90:35 | source(...) : String | semmle.label | source(...) : String |
-| mad/Test.java:92:27:92:41 | (...)... | semmle.label | (...)... |
-| mad/Test.java:92:34:92:41 | source(...) : String | semmle.label | source(...) : String |
-| mad/Test.java:93:27:93:41 | (...)... | semmle.label | (...)... |
-| mad/Test.java:93:34:93:41 | source(...) : String | semmle.label | source(...) : String |
-| mad/Test.java:95:26:95:40 | (...)... | semmle.label | (...)... |
-| mad/Test.java:95:33:95:40 | source(...) : String | semmle.label | source(...) : String |
-| mad/Test.java:97:35:97:49 | (...)... | semmle.label | (...)... |
-| mad/Test.java:97:42:97:49 | source(...) : String | semmle.label | source(...) : String |
-| mad/Test.java:99:41:99:57 | (...)... | semmle.label | (...)... |
-| mad/Test.java:99:50:99:57 | source(...) : String | semmle.label | source(...) : String |
-| mad/Test.java:101:45:101:61 | (...)... | semmle.label | (...)... |
-| mad/Test.java:101:54:101:61 | source(...) : String | semmle.label | source(...) : String |
-| mad/Test.java:103:43:103:57 | (...)... | semmle.label | (...)... |
-| mad/Test.java:103:50:103:57 | source(...) : String | semmle.label | source(...) : String |
-| mad/Test.java:105:28:105:42 | (...)... | semmle.label | (...)... |
-| mad/Test.java:105:35:105:42 | source(...) : String | semmle.label | source(...) : String |
-| mad/Test.java:107:41:107:55 | (...)... | semmle.label | (...)... |
-| mad/Test.java:107:48:107:55 | source(...) : String | semmle.label | source(...) : String |
-| mad/Test.java:109:28:109:44 | (...)... | semmle.label | (...)... |
-| mad/Test.java:109:37:109:44 | source(...) : String | semmle.label | source(...) : String |
-| mad/Test.java:111:28:111:42 | (...)... | semmle.label | (...)... |
-| mad/Test.java:111:35:111:42 | source(...) : String | semmle.label | source(...) : String |
-| mad/Test.java:116:30:116:44 | (...)... | semmle.label | (...)... |
-| mad/Test.java:116:37:116:44 | source(...) : String | semmle.label | source(...) : String |
-| mad/Test.java:118:40:118:81 | (...)... | semmle.label | (...)... |
-| mad/Test.java:118:74:118:81 | source(...) : String | semmle.label | source(...) : String |
-| mad/Test.java:120:34:120:75 | (...)... | semmle.label | (...)... |
-| mad/Test.java:120:68:120:75 | source(...) : String | semmle.label | source(...) : String |
-| mad/Test.java:122:34:122:75 | (...)... | semmle.label | (...)... |
-| mad/Test.java:122:68:122:75 | source(...) : String | semmle.label | source(...) : String |
-| mad/Test.java:124:23:124:37 | (...)... | semmle.label | (...)... |
-| mad/Test.java:124:30:124:37 | source(...) : String | semmle.label | source(...) : String |
-| mad/Test.java:129:23:129:37 | (...)... | semmle.label | (...)... |
-| mad/Test.java:129:30:129:37 | source(...) : String | semmle.label | source(...) : String |
-| mad/Test.java:134:23:134:40 | (...)... | semmle.label | (...)... |
-| mad/Test.java:134:33:134:40 | source(...) : String | semmle.label | source(...) : String |
-| mad/Test.java:136:20:136:34 | (...)... | semmle.label | (...)... |
-| mad/Test.java:136:27:136:34 | source(...) : String | semmle.label | source(...) : String |
-| mad/Test.java:138:21:138:35 | (...)... | semmle.label | (...)... |
-| mad/Test.java:138:28:138:35 | source(...) : String | semmle.label | source(...) : String |
-| mad/Test.java:140:22:140:36 | (...)... | semmle.label | (...)... |
-| mad/Test.java:140:29:140:36 | source(...) : String | semmle.label | source(...) : String |
-| mad/Test.java:145:20:145:34 | (...)... | semmle.label | (...)... |
-| mad/Test.java:145:27:145:34 | source(...) : String | semmle.label | source(...) : String |
-| mad/Test.java:147:19:147:33 | (...)... | semmle.label | (...)... |
-| mad/Test.java:147:26:147:33 | source(...) : String | semmle.label | source(...) : String |
-| mad/Test.java:152:20:152:36 | (...)... | semmle.label | (...)... |
-| mad/Test.java:152:29:152:36 | source(...) : String | semmle.label | source(...) : String |
+| mad/Test.java:40:16:40:36 | getHostName(...) : String | semmle.label | getHostName(...) : String |
+| mad/Test.java:45:52:45:68 | (...)... | semmle.label | (...)... |
+| mad/Test.java:45:61:45:68 | source(...) : String | semmle.label | source(...) : String |
+| mad/Test.java:47:32:47:48 | (...)... | semmle.label | (...)... |
+| mad/Test.java:47:41:47:48 | source(...) : String | semmle.label | source(...) : String |
+| mad/Test.java:49:47:49:63 | (...)... | semmle.label | (...)... |
+| mad/Test.java:49:56:49:63 | source(...) : String | semmle.label | source(...) : String |
+| mad/Test.java:51:39:51:53 | (...)... | semmle.label | (...)... |
+| mad/Test.java:51:46:51:53 | source(...) : String | semmle.label | source(...) : String |
+| mad/Test.java:53:31:53:45 | (...)... | semmle.label | (...)... |
+| mad/Test.java:53:38:53:45 | source(...) : String | semmle.label | source(...) : String |
+| mad/Test.java:55:29:55:43 | (...)... | semmle.label | (...)... |
+| mad/Test.java:55:36:55:43 | source(...) : String | semmle.label | source(...) : String |
+| mad/Test.java:57:24:57:38 | (...)... | semmle.label | (...)... |
+| mad/Test.java:57:31:57:38 | source(...) : String | semmle.label | source(...) : String |
+| mad/Test.java:59:24:59:40 | (...)... | semmle.label | (...)... |
+| mad/Test.java:59:33:59:40 | source(...) : String | semmle.label | source(...) : String |
+| mad/Test.java:61:20:61:34 | (...)... | semmle.label | (...)... |
+| mad/Test.java:61:27:61:34 | source(...) : String | semmle.label | source(...) : String |
+| mad/Test.java:63:20:63:34 | (...)... | semmle.label | (...)... |
+| mad/Test.java:63:27:63:34 | source(...) : String | semmle.label | source(...) : String |
+| mad/Test.java:65:33:65:47 | (...)... | semmle.label | (...)... |
+| mad/Test.java:65:40:65:47 | source(...) : String | semmle.label | source(...) : String |
+| mad/Test.java:67:40:67:54 | (...)... | semmle.label | (...)... |
+| mad/Test.java:67:47:67:54 | source(...) : String | semmle.label | source(...) : String |
+| mad/Test.java:69:33:69:47 | (...)... | semmle.label | (...)... |
+| mad/Test.java:69:40:69:47 | source(...) : String | semmle.label | source(...) : String |
+| mad/Test.java:71:31:71:45 | (...)... | semmle.label | (...)... |
+| mad/Test.java:71:38:71:45 | source(...) : String | semmle.label | source(...) : String |
+| mad/Test.java:73:26:73:40 | (...)... | semmle.label | (...)... |
+| mad/Test.java:73:33:73:40 | source(...) : String | semmle.label | source(...) : String |
+| mad/Test.java:75:26:75:40 | (...)... | semmle.label | (...)... |
+| mad/Test.java:75:33:75:40 | source(...) : String | semmle.label | source(...) : String |
+| mad/Test.java:77:34:77:48 | (...)... | semmle.label | (...)... |
+| mad/Test.java:77:41:77:48 | source(...) : String | semmle.label | source(...) : String |
+| mad/Test.java:79:35:79:49 | (...)... | semmle.label | (...)... |
+| mad/Test.java:79:42:79:49 | source(...) : String | semmle.label | source(...) : String |
+| mad/Test.java:81:30:81:44 | (...)... | semmle.label | (...)... |
+| mad/Test.java:81:37:81:44 | source(...) : String | semmle.label | source(...) : String |
+| mad/Test.java:83:22:83:36 | (...)... | semmle.label | (...)... |
+| mad/Test.java:83:29:83:36 | source(...) : String | semmle.label | source(...) : String |
+| mad/Test.java:85:30:85:44 | (...)... | semmle.label | (...)... |
+| mad/Test.java:85:37:85:44 | source(...) : String | semmle.label | source(...) : String |
+| mad/Test.java:87:21:87:35 | (...)... | semmle.label | (...)... |
+| mad/Test.java:87:28:87:35 | source(...) : String | semmle.label | source(...) : String |
+| mad/Test.java:89:26:89:40 | (...)... | semmle.label | (...)... |
+| mad/Test.java:89:33:89:40 | source(...) : String | semmle.label | source(...) : String |
+| mad/Test.java:91:33:91:47 | (...)... | semmle.label | (...)... |
+| mad/Test.java:91:40:91:47 | source(...) : String | semmle.label | source(...) : String |
+| mad/Test.java:93:33:93:47 | (...)... | semmle.label | (...)... |
+| mad/Test.java:93:40:93:47 | source(...) : String | semmle.label | source(...) : String |
+| mad/Test.java:94:33:94:47 | (...)... | semmle.label | (...)... |
+| mad/Test.java:94:40:94:47 | source(...) : String | semmle.label | source(...) : String |
+| mad/Test.java:96:31:96:45 | (...)... | semmle.label | (...)... |
+| mad/Test.java:96:38:96:45 | source(...) : String | semmle.label | source(...) : String |
+| mad/Test.java:98:21:98:35 | (...)... | semmle.label | (...)... |
+| mad/Test.java:98:28:98:35 | source(...) : String | semmle.label | source(...) : String |
+| mad/Test.java:99:21:99:35 | (...)... | semmle.label | (...)... |
+| mad/Test.java:99:28:99:35 | source(...) : String | semmle.label | source(...) : String |
+| mad/Test.java:100:21:100:35 | (...)... | semmle.label | (...)... |
+| mad/Test.java:100:28:100:35 | source(...) : String | semmle.label | source(...) : String |
+| mad/Test.java:102:27:102:41 | (...)... | semmle.label | (...)... |
+| mad/Test.java:102:34:102:41 | source(...) : String | semmle.label | source(...) : String |
+| mad/Test.java:103:27:103:41 | (...)... | semmle.label | (...)... |
+| mad/Test.java:103:34:103:41 | source(...) : String | semmle.label | source(...) : String |
+| mad/Test.java:105:26:105:40 | (...)... | semmle.label | (...)... |
+| mad/Test.java:105:33:105:40 | source(...) : String | semmle.label | source(...) : String |
+| mad/Test.java:107:35:107:49 | (...)... | semmle.label | (...)... |
+| mad/Test.java:107:42:107:49 | source(...) : String | semmle.label | source(...) : String |
+| mad/Test.java:109:41:109:57 | (...)... | semmle.label | (...)... |
+| mad/Test.java:109:50:109:57 | source(...) : String | semmle.label | source(...) : String |
+| mad/Test.java:111:45:111:61 | (...)... | semmle.label | (...)... |
+| mad/Test.java:111:54:111:61 | source(...) : String | semmle.label | source(...) : String |
+| mad/Test.java:113:43:113:57 | (...)... | semmle.label | (...)... |
+| mad/Test.java:113:50:113:57 | source(...) : String | semmle.label | source(...) : String |
+| mad/Test.java:115:28:115:42 | (...)... | semmle.label | (...)... |
+| mad/Test.java:115:35:115:42 | source(...) : String | semmle.label | source(...) : String |
+| mad/Test.java:117:41:117:55 | (...)... | semmle.label | (...)... |
+| mad/Test.java:117:48:117:55 | source(...) : String | semmle.label | source(...) : String |
+| mad/Test.java:119:28:119:44 | (...)... | semmle.label | (...)... |
+| mad/Test.java:119:37:119:44 | source(...) : String | semmle.label | source(...) : String |
+| mad/Test.java:121:28:121:42 | (...)... | semmle.label | (...)... |
+| mad/Test.java:121:35:121:42 | source(...) : String | semmle.label | source(...) : String |
+| mad/Test.java:123:46:123:62 | (...)... | semmle.label | (...)... |
+| mad/Test.java:123:55:123:62 | source(...) : String | semmle.label | source(...) : String |
+| mad/Test.java:125:40:125:54 | (...)... | semmle.label | (...)... |
+| mad/Test.java:125:47:125:54 | source(...) : String | semmle.label | source(...) : String |
+| mad/Test.java:127:40:127:54 | (...)... | semmle.label | (...)... |
+| mad/Test.java:127:47:127:54 | source(...) : String | semmle.label | source(...) : String |
+| mad/Test.java:131:26:131:42 | (...)... | semmle.label | (...)... |
+| mad/Test.java:131:35:131:42 | source(...) : String | semmle.label | source(...) : String |
+| mad/Test.java:135:49:135:63 | (...)... | semmle.label | (...)... |
+| mad/Test.java:135:56:135:63 | source(...) : String | semmle.label | source(...) : String |
+| mad/Test.java:137:49:137:63 | (...)... | semmle.label | (...)... |
+| mad/Test.java:137:56:137:63 | source(...) : String | semmle.label | source(...) : String |
+| mad/Test.java:141:52:141:66 | (...)... | semmle.label | (...)... |
+| mad/Test.java:141:59:141:66 | source(...) : String | semmle.label | source(...) : String |
+| mad/Test.java:143:52:143:66 | (...)... | semmle.label | (...)... |
+| mad/Test.java:143:59:143:66 | source(...) : String | semmle.label | source(...) : String |
+| mad/Test.java:145:49:145:65 | (...)... | semmle.label | (...)... |
+| mad/Test.java:145:58:145:65 | source(...) : String | semmle.label | source(...) : String |
+| mad/Test.java:147:25:147:41 | (...)... | semmle.label | (...)... |
+| mad/Test.java:147:34:147:41 | source(...) : String | semmle.label | source(...) : String |
+| mad/Test.java:149:25:149:41 | (...)... | semmle.label | (...)... |
+| mad/Test.java:149:34:149:41 | source(...) : String | semmle.label | source(...) : String |
+| mad/Test.java:151:35:151:51 | (...)... | semmle.label | (...)... |
+| mad/Test.java:151:44:151:51 | source(...) : String | semmle.label | source(...) : String |
+| mad/Test.java:153:24:153:38 | (...)... | semmle.label | (...)... |
+| mad/Test.java:153:31:153:38 | source(...) : String | semmle.label | source(...) : String |
+| mad/Test.java:155:37:155:53 | (...)... | semmle.label | (...)... |
+| mad/Test.java:155:46:155:53 | source(...) : String | semmle.label | source(...) : String |
+| mad/Test.java:157:37:157:53 | (...)... | semmle.label | (...)... |
+| mad/Test.java:157:46:157:53 | source(...) : String | semmle.label | source(...) : String |
+| mad/Test.java:159:58:159:74 | (...)... | semmle.label | (...)... |
+| mad/Test.java:159:67:159:74 | source(...) : String | semmle.label | source(...) : String |
+| mad/Test.java:161:58:161:74 | (...)... | semmle.label | (...)... |
+| mad/Test.java:161:67:161:74 | source(...) : String | semmle.label | source(...) : String |
+| mad/Test.java:163:64:163:80 | (...)... | semmle.label | (...)... |
+| mad/Test.java:163:73:163:80 | source(...) : String | semmle.label | source(...) : String |
+| mad/Test.java:166:28:166:44 | (...)... | semmle.label | (...)... |
+| mad/Test.java:166:37:166:44 | source(...) : String | semmle.label | source(...) : String |
+| mad/Test.java:168:39:168:55 | (...)... | semmle.label | (...)... |
+| mad/Test.java:168:48:168:55 | source(...) : String | semmle.label | source(...) : String |
+| mad/Test.java:170:45:170:61 | (...)... | semmle.label | (...)... |
+| mad/Test.java:170:54:170:61 | source(...) : String | semmle.label | source(...) : String |
+| mad/Test.java:172:60:172:76 | (...)... | semmle.label | (...)... |
+| mad/Test.java:172:69:172:76 | source(...) : String | semmle.label | source(...) : String |
+| mad/Test.java:174:40:174:54 | (...)... | semmle.label | (...)... |
+| mad/Test.java:174:47:174:54 | source(...) : String | semmle.label | source(...) : String |
+| mad/Test.java:176:40:176:56 | (...)... | semmle.label | (...)... |
+| mad/Test.java:176:49:176:56 | source(...) : String | semmle.label | source(...) : String |
+| mad/Test.java:178:55:178:71 | (...)... | semmle.label | (...)... |
+| mad/Test.java:178:64:178:71 | source(...) : String | semmle.label | source(...) : String |
+| mad/Test.java:180:40:180:56 | (...)... | semmle.label | (...)... |
+| mad/Test.java:180:49:180:56 | source(...) : String | semmle.label | source(...) : String |
+| mad/Test.java:182:55:182:71 | (...)... | semmle.label | (...)... |
+| mad/Test.java:182:64:182:71 | source(...) : String | semmle.label | source(...) : String |
+| mad/Test.java:184:54:184:68 | (...)... | semmle.label | (...)... |
+| mad/Test.java:184:61:184:68 | source(...) : String | semmle.label | source(...) : String |
+| mad/Test.java:190:30:190:44 | (...)... | semmle.label | (...)... |
+| mad/Test.java:190:37:190:44 | source(...) : String | semmle.label | source(...) : String |
+| mad/Test.java:192:40:192:81 | (...)... | semmle.label | (...)... |
+| mad/Test.java:192:74:192:81 | source(...) : String | semmle.label | source(...) : String |
+| mad/Test.java:194:34:194:75 | (...)... | semmle.label | (...)... |
+| mad/Test.java:194:68:194:75 | source(...) : String | semmle.label | source(...) : String |
+| mad/Test.java:196:34:196:75 | (...)... | semmle.label | (...)... |
+| mad/Test.java:196:68:196:75 | source(...) : String | semmle.label | source(...) : String |
+| mad/Test.java:198:23:198:37 | (...)... | semmle.label | (...)... |
+| mad/Test.java:198:30:198:37 | source(...) : String | semmle.label | source(...) : String |
+| mad/Test.java:203:23:203:37 | (...)... | semmle.label | (...)... |
+| mad/Test.java:203:30:203:37 | source(...) : String | semmle.label | source(...) : String |
+| mad/Test.java:208:23:208:40 | (...)... | semmle.label | (...)... |
+| mad/Test.java:208:33:208:40 | source(...) : String | semmle.label | source(...) : String |
+| mad/Test.java:210:20:210:34 | (...)... | semmle.label | (...)... |
+| mad/Test.java:210:27:210:34 | source(...) : String | semmle.label | source(...) : String |
+| mad/Test.java:212:21:212:35 | (...)... | semmle.label | (...)... |
+| mad/Test.java:212:28:212:35 | source(...) : String | semmle.label | source(...) : String |
+| mad/Test.java:214:22:214:36 | (...)... | semmle.label | (...)... |
+| mad/Test.java:214:29:214:36 | source(...) : String | semmle.label | source(...) : String |
+| mad/Test.java:219:20:219:34 | (...)... | semmle.label | (...)... |
+| mad/Test.java:219:27:219:34 | source(...) : String | semmle.label | source(...) : String |
+| mad/Test.java:221:19:221:33 | (...)... | semmle.label | (...)... |
+| mad/Test.java:221:26:221:33 | source(...) : String | semmle.label | source(...) : String |
+| mad/Test.java:226:20:226:36 | (...)... | semmle.label | (...)... |
+| mad/Test.java:226:29:226:36 | source(...) : String | semmle.label | source(...) : String |
subpaths
#select
| Test.java:24:11:24:24 | new File(...) | Test.java:19:18:19:38 | getHostName(...) : String | Test.java:24:20:24:23 | temp | This path depends on a $@. | Test.java:19:18:19:38 | getHostName(...) | user-provided value |
@@ -274,57 +386,85 @@ subpaths
| Test.java:99:3:99:34 | new File(...) | Test.java:95:14:95:34 | getHostName(...) : String | Test.java:99:12:99:33 | new URI(...) | This path depends on a $@. | Test.java:95:14:95:34 | getHostName(...) | user-provided value |
| Test.java:100:3:100:46 | new File(...) | Test.java:95:14:95:34 | getHostName(...) : String | Test.java:100:12:100:45 | new URI(...) | This path depends on a $@. | Test.java:95:14:95:34 | getHostName(...) | user-provided value |
| Test.java:101:3:101:55 | new File(...) | Test.java:95:14:95:34 | getHostName(...) : String | Test.java:101:12:101:54 | new URI(...) | This path depends on a $@. | Test.java:95:14:95:34 | getHostName(...) | user-provided value |
-| mad/Test.java:35:52:35:68 | (...)... | mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:35:52:35:68 | (...)... | This path depends on a $@. | mad/Test.java:30:16:30:36 | getHostName(...) | user-provided value |
-| mad/Test.java:37:32:37:48 | (...)... | mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:37:32:37:48 | (...)... | This path depends on a $@. | mad/Test.java:30:16:30:36 | getHostName(...) | user-provided value |
-| mad/Test.java:39:47:39:63 | (...)... | mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:39:47:39:63 | (...)... | This path depends on a $@. | mad/Test.java:30:16:30:36 | getHostName(...) | user-provided value |
-| mad/Test.java:41:39:41:53 | (...)... | mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:41:39:41:53 | (...)... | This path depends on a $@. | mad/Test.java:30:16:30:36 | getHostName(...) | user-provided value |
-| mad/Test.java:43:31:43:45 | (...)... | mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:43:31:43:45 | (...)... | This path depends on a $@. | mad/Test.java:30:16:30:36 | getHostName(...) | user-provided value |
-| mad/Test.java:45:29:45:43 | (...)... | mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:45:29:45:43 | (...)... | This path depends on a $@. | mad/Test.java:30:16:30:36 | getHostName(...) | user-provided value |
-| mad/Test.java:47:24:47:38 | (...)... | mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:47:24:47:38 | (...)... | This path depends on a $@. | mad/Test.java:30:16:30:36 | getHostName(...) | user-provided value |
-| mad/Test.java:49:9:49:41 | new FileReader(...) | mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:49:24:49:40 | (...)... | This path depends on a $@. | mad/Test.java:30:16:30:36 | getHostName(...) | user-provided value |
-| mad/Test.java:51:20:51:34 | (...)... | mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:51:20:51:34 | (...)... | This path depends on a $@. | mad/Test.java:30:16:30:36 | getHostName(...) | user-provided value |
-| mad/Test.java:53:20:53:34 | (...)... | mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:53:20:53:34 | (...)... | This path depends on a $@. | mad/Test.java:30:16:30:36 | getHostName(...) | user-provided value |
-| mad/Test.java:55:33:55:47 | (...)... | mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:55:33:55:47 | (...)... | This path depends on a $@. | mad/Test.java:30:16:30:36 | getHostName(...) | user-provided value |
-| mad/Test.java:57:40:57:54 | (...)... | mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:57:40:57:54 | (...)... | This path depends on a $@. | mad/Test.java:30:16:30:36 | getHostName(...) | user-provided value |
-| mad/Test.java:59:33:59:47 | (...)... | mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:59:33:59:47 | (...)... | This path depends on a $@. | mad/Test.java:30:16:30:36 | getHostName(...) | user-provided value |
-| mad/Test.java:61:31:61:45 | (...)... | mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:61:31:61:45 | (...)... | This path depends on a $@. | mad/Test.java:30:16:30:36 | getHostName(...) | user-provided value |
-| mad/Test.java:63:26:63:40 | (...)... | mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:63:26:63:40 | (...)... | This path depends on a $@. | mad/Test.java:30:16:30:36 | getHostName(...) | user-provided value |
-| mad/Test.java:65:26:65:40 | (...)... | mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:65:26:65:40 | (...)... | This path depends on a $@. | mad/Test.java:30:16:30:36 | getHostName(...) | user-provided value |
-| mad/Test.java:67:34:67:48 | (...)... | mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:67:34:67:48 | (...)... | This path depends on a $@. | mad/Test.java:30:16:30:36 | getHostName(...) | user-provided value |
-| mad/Test.java:69:35:69:49 | (...)... | mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:69:35:69:49 | (...)... | This path depends on a $@. | mad/Test.java:30:16:30:36 | getHostName(...) | user-provided value |
-| mad/Test.java:71:30:71:44 | (...)... | mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:71:30:71:44 | (...)... | This path depends on a $@. | mad/Test.java:30:16:30:36 | getHostName(...) | user-provided value |
-| mad/Test.java:73:22:73:36 | (...)... | mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:73:22:73:36 | (...)... | This path depends on a $@. | mad/Test.java:30:16:30:36 | getHostName(...) | user-provided value |
-| mad/Test.java:75:30:75:44 | (...)... | mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:75:30:75:44 | (...)... | This path depends on a $@. | mad/Test.java:30:16:30:36 | getHostName(...) | user-provided value |
-| mad/Test.java:77:21:77:35 | (...)... | mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:77:21:77:35 | (...)... | This path depends on a $@. | mad/Test.java:30:16:30:36 | getHostName(...) | user-provided value |
-| mad/Test.java:79:26:79:40 | (...)... | mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:79:26:79:40 | (...)... | This path depends on a $@. | mad/Test.java:30:16:30:36 | getHostName(...) | user-provided value |
-| mad/Test.java:81:33:81:47 | (...)... | mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:81:33:81:47 | (...)... | This path depends on a $@. | mad/Test.java:30:16:30:36 | getHostName(...) | user-provided value |
-| mad/Test.java:83:33:83:47 | (...)... | mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:83:33:83:47 | (...)... | This path depends on a $@. | mad/Test.java:30:16:30:36 | getHostName(...) | user-provided value |
-| mad/Test.java:84:33:84:47 | (...)... | mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:84:33:84:47 | (...)... | This path depends on a $@. | mad/Test.java:30:16:30:36 | getHostName(...) | user-provided value |
-| mad/Test.java:86:31:86:45 | (...)... | mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:86:31:86:45 | (...)... | This path depends on a $@. | mad/Test.java:30:16:30:36 | getHostName(...) | user-provided value |
-| mad/Test.java:88:21:88:35 | (...)... | mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:88:21:88:35 | (...)... | This path depends on a $@. | mad/Test.java:30:16:30:36 | getHostName(...) | user-provided value |
-| mad/Test.java:89:21:89:35 | (...)... | mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:89:21:89:35 | (...)... | This path depends on a $@. | mad/Test.java:30:16:30:36 | getHostName(...) | user-provided value |
-| mad/Test.java:90:21:90:35 | (...)... | mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:90:21:90:35 | (...)... | This path depends on a $@. | mad/Test.java:30:16:30:36 | getHostName(...) | user-provided value |
-| mad/Test.java:92:27:92:41 | (...)... | mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:92:27:92:41 | (...)... | This path depends on a $@. | mad/Test.java:30:16:30:36 | getHostName(...) | user-provided value |
-| mad/Test.java:93:27:93:41 | (...)... | mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:93:27:93:41 | (...)... | This path depends on a $@. | mad/Test.java:30:16:30:36 | getHostName(...) | user-provided value |
-| mad/Test.java:95:26:95:40 | (...)... | mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:95:26:95:40 | (...)... | This path depends on a $@. | mad/Test.java:30:16:30:36 | getHostName(...) | user-provided value |
-| mad/Test.java:97:35:97:49 | (...)... | mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:97:35:97:49 | (...)... | This path depends on a $@. | mad/Test.java:30:16:30:36 | getHostName(...) | user-provided value |
-| mad/Test.java:99:41:99:57 | (...)... | mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:99:41:99:57 | (...)... | This path depends on a $@. | mad/Test.java:30:16:30:36 | getHostName(...) | user-provided value |
-| mad/Test.java:101:45:101:61 | (...)... | mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:101:45:101:61 | (...)... | This path depends on a $@. | mad/Test.java:30:16:30:36 | getHostName(...) | user-provided value |
-| mad/Test.java:103:43:103:57 | (...)... | mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:103:43:103:57 | (...)... | This path depends on a $@. | mad/Test.java:30:16:30:36 | getHostName(...) | user-provided value |
-| mad/Test.java:105:28:105:42 | (...)... | mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:105:28:105:42 | (...)... | This path depends on a $@. | mad/Test.java:30:16:30:36 | getHostName(...) | user-provided value |
-| mad/Test.java:107:41:107:55 | (...)... | mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:107:41:107:55 | (...)... | This path depends on a $@. | mad/Test.java:30:16:30:36 | getHostName(...) | user-provided value |
-| mad/Test.java:109:28:109:44 | (...)... | mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:109:28:109:44 | (...)... | This path depends on a $@. | mad/Test.java:30:16:30:36 | getHostName(...) | user-provided value |
-| mad/Test.java:111:28:111:42 | (...)... | mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:111:28:111:42 | (...)... | This path depends on a $@. | mad/Test.java:30:16:30:36 | getHostName(...) | user-provided value |
-| mad/Test.java:116:30:116:44 | (...)... | mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:116:30:116:44 | (...)... | This path depends on a $@. | mad/Test.java:30:16:30:36 | getHostName(...) | user-provided value |
-| mad/Test.java:118:40:118:81 | (...)... | mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:118:40:118:81 | (...)... | This path depends on a $@. | mad/Test.java:30:16:30:36 | getHostName(...) | user-provided value |
-| mad/Test.java:120:34:120:75 | (...)... | mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:120:34:120:75 | (...)... | This path depends on a $@. | mad/Test.java:30:16:30:36 | getHostName(...) | user-provided value |
-| mad/Test.java:122:34:122:75 | (...)... | mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:122:34:122:75 | (...)... | This path depends on a $@. | mad/Test.java:30:16:30:36 | getHostName(...) | user-provided value |
-| mad/Test.java:124:23:124:37 | (...)... | mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:124:23:124:37 | (...)... | This path depends on a $@. | mad/Test.java:30:16:30:36 | getHostName(...) | user-provided value |
-| mad/Test.java:129:23:129:37 | (...)... | mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:129:23:129:37 | (...)... | This path depends on a $@. | mad/Test.java:30:16:30:36 | getHostName(...) | user-provided value |
-| mad/Test.java:134:23:134:40 | (...)... | mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:134:23:134:40 | (...)... | This path depends on a $@. | mad/Test.java:30:16:30:36 | getHostName(...) | user-provided value |
-| mad/Test.java:136:20:136:34 | (...)... | mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:136:20:136:34 | (...)... | This path depends on a $@. | mad/Test.java:30:16:30:36 | getHostName(...) | user-provided value |
-| mad/Test.java:138:21:138:35 | (...)... | mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:138:21:138:35 | (...)... | This path depends on a $@. | mad/Test.java:30:16:30:36 | getHostName(...) | user-provided value |
-| mad/Test.java:140:22:140:36 | (...)... | mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:140:22:140:36 | (...)... | This path depends on a $@. | mad/Test.java:30:16:30:36 | getHostName(...) | user-provided value |
-| mad/Test.java:145:20:145:34 | (...)... | mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:145:20:145:34 | (...)... | This path depends on a $@. | mad/Test.java:30:16:30:36 | getHostName(...) | user-provided value |
-| mad/Test.java:147:19:147:33 | (...)... | mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:147:19:147:33 | (...)... | This path depends on a $@. | mad/Test.java:30:16:30:36 | getHostName(...) | user-provided value |
-| mad/Test.java:152:20:152:36 | (...)... | mad/Test.java:30:16:30:36 | getHostName(...) : String | mad/Test.java:152:20:152:36 | (...)... | This path depends on a $@. | mad/Test.java:30:16:30:36 | getHostName(...) | user-provided value |
+| mad/Test.java:45:52:45:68 | (...)... | mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:45:52:45:68 | (...)... | This path depends on a $@. | mad/Test.java:40:16:40:36 | getHostName(...) | user-provided value |
+| mad/Test.java:47:32:47:48 | (...)... | mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:47:32:47:48 | (...)... | This path depends on a $@. | mad/Test.java:40:16:40:36 | getHostName(...) | user-provided value |
+| mad/Test.java:49:47:49:63 | (...)... | mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:49:47:49:63 | (...)... | This path depends on a $@. | mad/Test.java:40:16:40:36 | getHostName(...) | user-provided value |
+| mad/Test.java:51:39:51:53 | (...)... | mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:51:39:51:53 | (...)... | This path depends on a $@. | mad/Test.java:40:16:40:36 | getHostName(...) | user-provided value |
+| mad/Test.java:53:31:53:45 | (...)... | mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:53:31:53:45 | (...)... | This path depends on a $@. | mad/Test.java:40:16:40:36 | getHostName(...) | user-provided value |
+| mad/Test.java:55:29:55:43 | (...)... | mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:55:29:55:43 | (...)... | This path depends on a $@. | mad/Test.java:40:16:40:36 | getHostName(...) | user-provided value |
+| mad/Test.java:57:24:57:38 | (...)... | mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:57:24:57:38 | (...)... | This path depends on a $@. | mad/Test.java:40:16:40:36 | getHostName(...) | user-provided value |
+| mad/Test.java:59:9:59:41 | new FileReader(...) | mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:59:24:59:40 | (...)... | This path depends on a $@. | mad/Test.java:40:16:40:36 | getHostName(...) | user-provided value |
+| mad/Test.java:61:20:61:34 | (...)... | mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:61:20:61:34 | (...)... | This path depends on a $@. | mad/Test.java:40:16:40:36 | getHostName(...) | user-provided value |
+| mad/Test.java:63:20:63:34 | (...)... | mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:63:20:63:34 | (...)... | This path depends on a $@. | mad/Test.java:40:16:40:36 | getHostName(...) | user-provided value |
+| mad/Test.java:65:33:65:47 | (...)... | mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:65:33:65:47 | (...)... | This path depends on a $@. | mad/Test.java:40:16:40:36 | getHostName(...) | user-provided value |
+| mad/Test.java:67:40:67:54 | (...)... | mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:67:40:67:54 | (...)... | This path depends on a $@. | mad/Test.java:40:16:40:36 | getHostName(...) | user-provided value |
+| mad/Test.java:69:33:69:47 | (...)... | mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:69:33:69:47 | (...)... | This path depends on a $@. | mad/Test.java:40:16:40:36 | getHostName(...) | user-provided value |
+| mad/Test.java:71:31:71:45 | (...)... | mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:71:31:71:45 | (...)... | This path depends on a $@. | mad/Test.java:40:16:40:36 | getHostName(...) | user-provided value |
+| mad/Test.java:73:26:73:40 | (...)... | mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:73:26:73:40 | (...)... | This path depends on a $@. | mad/Test.java:40:16:40:36 | getHostName(...) | user-provided value |
+| mad/Test.java:75:26:75:40 | (...)... | mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:75:26:75:40 | (...)... | This path depends on a $@. | mad/Test.java:40:16:40:36 | getHostName(...) | user-provided value |
+| mad/Test.java:77:34:77:48 | (...)... | mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:77:34:77:48 | (...)... | This path depends on a $@. | mad/Test.java:40:16:40:36 | getHostName(...) | user-provided value |
+| mad/Test.java:79:35:79:49 | (...)... | mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:79:35:79:49 | (...)... | This path depends on a $@. | mad/Test.java:40:16:40:36 | getHostName(...) | user-provided value |
+| mad/Test.java:81:30:81:44 | (...)... | mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:81:30:81:44 | (...)... | This path depends on a $@. | mad/Test.java:40:16:40:36 | getHostName(...) | user-provided value |
+| mad/Test.java:83:22:83:36 | (...)... | mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:83:22:83:36 | (...)... | This path depends on a $@. | mad/Test.java:40:16:40:36 | getHostName(...) | user-provided value |
+| mad/Test.java:85:30:85:44 | (...)... | mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:85:30:85:44 | (...)... | This path depends on a $@. | mad/Test.java:40:16:40:36 | getHostName(...) | user-provided value |
+| mad/Test.java:87:21:87:35 | (...)... | mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:87:21:87:35 | (...)... | This path depends on a $@. | mad/Test.java:40:16:40:36 | getHostName(...) | user-provided value |
+| mad/Test.java:89:26:89:40 | (...)... | mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:89:26:89:40 | (...)... | This path depends on a $@. | mad/Test.java:40:16:40:36 | getHostName(...) | user-provided value |
+| mad/Test.java:91:33:91:47 | (...)... | mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:91:33:91:47 | (...)... | This path depends on a $@. | mad/Test.java:40:16:40:36 | getHostName(...) | user-provided value |
+| mad/Test.java:93:33:93:47 | (...)... | mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:93:33:93:47 | (...)... | This path depends on a $@. | mad/Test.java:40:16:40:36 | getHostName(...) | user-provided value |
+| mad/Test.java:94:33:94:47 | (...)... | mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:94:33:94:47 | (...)... | This path depends on a $@. | mad/Test.java:40:16:40:36 | getHostName(...) | user-provided value |
+| mad/Test.java:96:31:96:45 | (...)... | mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:96:31:96:45 | (...)... | This path depends on a $@. | mad/Test.java:40:16:40:36 | getHostName(...) | user-provided value |
+| mad/Test.java:98:21:98:35 | (...)... | mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:98:21:98:35 | (...)... | This path depends on a $@. | mad/Test.java:40:16:40:36 | getHostName(...) | user-provided value |
+| mad/Test.java:99:21:99:35 | (...)... | mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:99:21:99:35 | (...)... | This path depends on a $@. | mad/Test.java:40:16:40:36 | getHostName(...) | user-provided value |
+| mad/Test.java:100:21:100:35 | (...)... | mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:100:21:100:35 | (...)... | This path depends on a $@. | mad/Test.java:40:16:40:36 | getHostName(...) | user-provided value |
+| mad/Test.java:102:27:102:41 | (...)... | mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:102:27:102:41 | (...)... | This path depends on a $@. | mad/Test.java:40:16:40:36 | getHostName(...) | user-provided value |
+| mad/Test.java:103:27:103:41 | (...)... | mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:103:27:103:41 | (...)... | This path depends on a $@. | mad/Test.java:40:16:40:36 | getHostName(...) | user-provided value |
+| mad/Test.java:105:26:105:40 | (...)... | mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:105:26:105:40 | (...)... | This path depends on a $@. | mad/Test.java:40:16:40:36 | getHostName(...) | user-provided value |
+| mad/Test.java:107:35:107:49 | (...)... | mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:107:35:107:49 | (...)... | This path depends on a $@. | mad/Test.java:40:16:40:36 | getHostName(...) | user-provided value |
+| mad/Test.java:109:41:109:57 | (...)... | mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:109:41:109:57 | (...)... | This path depends on a $@. | mad/Test.java:40:16:40:36 | getHostName(...) | user-provided value |
+| mad/Test.java:111:45:111:61 | (...)... | mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:111:45:111:61 | (...)... | This path depends on a $@. | mad/Test.java:40:16:40:36 | getHostName(...) | user-provided value |
+| mad/Test.java:113:43:113:57 | (...)... | mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:113:43:113:57 | (...)... | This path depends on a $@. | mad/Test.java:40:16:40:36 | getHostName(...) | user-provided value |
+| mad/Test.java:115:28:115:42 | (...)... | mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:115:28:115:42 | (...)... | This path depends on a $@. | mad/Test.java:40:16:40:36 | getHostName(...) | user-provided value |
+| mad/Test.java:117:41:117:55 | (...)... | mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:117:41:117:55 | (...)... | This path depends on a $@. | mad/Test.java:40:16:40:36 | getHostName(...) | user-provided value |
+| mad/Test.java:119:28:119:44 | (...)... | mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:119:28:119:44 | (...)... | This path depends on a $@. | mad/Test.java:40:16:40:36 | getHostName(...) | user-provided value |
+| mad/Test.java:121:28:121:42 | (...)... | mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:121:28:121:42 | (...)... | This path depends on a $@. | mad/Test.java:40:16:40:36 | getHostName(...) | user-provided value |
+| mad/Test.java:123:46:123:62 | (...)... | mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:123:46:123:62 | (...)... | This path depends on a $@. | mad/Test.java:40:16:40:36 | getHostName(...) | user-provided value |
+| mad/Test.java:125:40:125:54 | (...)... | mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:125:40:125:54 | (...)... | This path depends on a $@. | mad/Test.java:40:16:40:36 | getHostName(...) | user-provided value |
+| mad/Test.java:127:40:127:54 | (...)... | mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:127:40:127:54 | (...)... | This path depends on a $@. | mad/Test.java:40:16:40:36 | getHostName(...) | user-provided value |
+| mad/Test.java:131:26:131:42 | (...)... | mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:131:26:131:42 | (...)... | This path depends on a $@. | mad/Test.java:40:16:40:36 | getHostName(...) | user-provided value |
+| mad/Test.java:135:49:135:63 | (...)... | mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:135:49:135:63 | (...)... | This path depends on a $@. | mad/Test.java:40:16:40:36 | getHostName(...) | user-provided value |
+| mad/Test.java:137:49:137:63 | (...)... | mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:137:49:137:63 | (...)... | This path depends on a $@. | mad/Test.java:40:16:40:36 | getHostName(...) | user-provided value |
+| mad/Test.java:141:52:141:66 | (...)... | mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:141:52:141:66 | (...)... | This path depends on a $@. | mad/Test.java:40:16:40:36 | getHostName(...) | user-provided value |
+| mad/Test.java:143:52:143:66 | (...)... | mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:143:52:143:66 | (...)... | This path depends on a $@. | mad/Test.java:40:16:40:36 | getHostName(...) | user-provided value |
+| mad/Test.java:145:49:145:65 | (...)... | mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:145:49:145:65 | (...)... | This path depends on a $@. | mad/Test.java:40:16:40:36 | getHostName(...) | user-provided value |
+| mad/Test.java:147:25:147:41 | (...)... | mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:147:25:147:41 | (...)... | This path depends on a $@. | mad/Test.java:40:16:40:36 | getHostName(...) | user-provided value |
+| mad/Test.java:149:25:149:41 | (...)... | mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:149:25:149:41 | (...)... | This path depends on a $@. | mad/Test.java:40:16:40:36 | getHostName(...) | user-provided value |
+| mad/Test.java:151:35:151:51 | (...)... | mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:151:35:151:51 | (...)... | This path depends on a $@. | mad/Test.java:40:16:40:36 | getHostName(...) | user-provided value |
+| mad/Test.java:153:24:153:38 | (...)... | mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:153:24:153:38 | (...)... | This path depends on a $@. | mad/Test.java:40:16:40:36 | getHostName(...) | user-provided value |
+| mad/Test.java:155:37:155:53 | (...)... | mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:155:37:155:53 | (...)... | This path depends on a $@. | mad/Test.java:40:16:40:36 | getHostName(...) | user-provided value |
+| mad/Test.java:157:37:157:53 | (...)... | mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:157:37:157:53 | (...)... | This path depends on a $@. | mad/Test.java:40:16:40:36 | getHostName(...) | user-provided value |
+| mad/Test.java:159:58:159:74 | (...)... | mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:159:58:159:74 | (...)... | This path depends on a $@. | mad/Test.java:40:16:40:36 | getHostName(...) | user-provided value |
+| mad/Test.java:161:58:161:74 | (...)... | mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:161:58:161:74 | (...)... | This path depends on a $@. | mad/Test.java:40:16:40:36 | getHostName(...) | user-provided value |
+| mad/Test.java:163:64:163:80 | (...)... | mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:163:64:163:80 | (...)... | This path depends on a $@. | mad/Test.java:40:16:40:36 | getHostName(...) | user-provided value |
+| mad/Test.java:166:28:166:44 | (...)... | mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:166:28:166:44 | (...)... | This path depends on a $@. | mad/Test.java:40:16:40:36 | getHostName(...) | user-provided value |
+| mad/Test.java:168:39:168:55 | (...)... | mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:168:39:168:55 | (...)... | This path depends on a $@. | mad/Test.java:40:16:40:36 | getHostName(...) | user-provided value |
+| mad/Test.java:170:45:170:61 | (...)... | mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:170:45:170:61 | (...)... | This path depends on a $@. | mad/Test.java:40:16:40:36 | getHostName(...) | user-provided value |
+| mad/Test.java:172:60:172:76 | (...)... | mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:172:60:172:76 | (...)... | This path depends on a $@. | mad/Test.java:40:16:40:36 | getHostName(...) | user-provided value |
+| mad/Test.java:174:40:174:54 | (...)... | mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:174:40:174:54 | (...)... | This path depends on a $@. | mad/Test.java:40:16:40:36 | getHostName(...) | user-provided value |
+| mad/Test.java:176:40:176:56 | (...)... | mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:176:40:176:56 | (...)... | This path depends on a $@. | mad/Test.java:40:16:40:36 | getHostName(...) | user-provided value |
+| mad/Test.java:178:55:178:71 | (...)... | mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:178:55:178:71 | (...)... | This path depends on a $@. | mad/Test.java:40:16:40:36 | getHostName(...) | user-provided value |
+| mad/Test.java:180:40:180:56 | (...)... | mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:180:40:180:56 | (...)... | This path depends on a $@. | mad/Test.java:40:16:40:36 | getHostName(...) | user-provided value |
+| mad/Test.java:182:55:182:71 | (...)... | mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:182:55:182:71 | (...)... | This path depends on a $@. | mad/Test.java:40:16:40:36 | getHostName(...) | user-provided value |
+| mad/Test.java:184:54:184:68 | (...)... | mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:184:54:184:68 | (...)... | This path depends on a $@. | mad/Test.java:40:16:40:36 | getHostName(...) | user-provided value |
+| mad/Test.java:190:30:190:44 | (...)... | mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:190:30:190:44 | (...)... | This path depends on a $@. | mad/Test.java:40:16:40:36 | getHostName(...) | user-provided value |
+| mad/Test.java:192:40:192:81 | (...)... | mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:192:40:192:81 | (...)... | This path depends on a $@. | mad/Test.java:40:16:40:36 | getHostName(...) | user-provided value |
+| mad/Test.java:194:34:194:75 | (...)... | mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:194:34:194:75 | (...)... | This path depends on a $@. | mad/Test.java:40:16:40:36 | getHostName(...) | user-provided value |
+| mad/Test.java:196:34:196:75 | (...)... | mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:196:34:196:75 | (...)... | This path depends on a $@. | mad/Test.java:40:16:40:36 | getHostName(...) | user-provided value |
+| mad/Test.java:198:23:198:37 | (...)... | mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:198:23:198:37 | (...)... | This path depends on a $@. | mad/Test.java:40:16:40:36 | getHostName(...) | user-provided value |
+| mad/Test.java:203:23:203:37 | (...)... | mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:203:23:203:37 | (...)... | This path depends on a $@. | mad/Test.java:40:16:40:36 | getHostName(...) | user-provided value |
+| mad/Test.java:208:23:208:40 | (...)... | mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:208:23:208:40 | (...)... | This path depends on a $@. | mad/Test.java:40:16:40:36 | getHostName(...) | user-provided value |
+| mad/Test.java:210:20:210:34 | (...)... | mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:210:20:210:34 | (...)... | This path depends on a $@. | mad/Test.java:40:16:40:36 | getHostName(...) | user-provided value |
+| mad/Test.java:212:21:212:35 | (...)... | mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:212:21:212:35 | (...)... | This path depends on a $@. | mad/Test.java:40:16:40:36 | getHostName(...) | user-provided value |
+| mad/Test.java:214:22:214:36 | (...)... | mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:214:22:214:36 | (...)... | This path depends on a $@. | mad/Test.java:40:16:40:36 | getHostName(...) | user-provided value |
+| mad/Test.java:219:20:219:34 | (...)... | mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:219:20:219:34 | (...)... | This path depends on a $@. | mad/Test.java:40:16:40:36 | getHostName(...) | user-provided value |
+| mad/Test.java:221:19:221:33 | (...)... | mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:221:19:221:33 | (...)... | This path depends on a $@. | mad/Test.java:40:16:40:36 | getHostName(...) | user-provided value |
+| mad/Test.java:226:20:226:36 | (...)... | mad/Test.java:40:16:40:36 | getHostName(...) : String | mad/Test.java:226:20:226:36 | (...)... | This path depends on a $@. | mad/Test.java:40:16:40:36 | getHostName(...) | user-provided value |
diff --git a/java/ql/test/query-tests/security/CWE-022/semmle/tests/mad/Test.java b/java/ql/test/query-tests/security/CWE-022/semmle/tests/mad/Test.java
index 086e19ab127..169f3535c6b 100644
--- a/java/ql/test/query-tests/security/CWE-022/semmle/tests/mad/Test.java
+++ b/java/ql/test/query-tests/security/CWE-022/semmle/tests/mad/Test.java
@@ -11,6 +11,16 @@ import java.nio.file.Files;
import java.nio.file.Path;
import javax.activation.FileDataSource;
import javax.xml.transform.stream.StreamResult;
+import org.apache.cxf.common.classloader.ClassLoaderUtils;
+import org.apache.cxf.common.jaxb.JAXBUtils;
+import org.apache.cxf.configuration.jsse.SSLUtils;
+import org.apache.cxf.resource.ExtendedURIResolver;
+import org.apache.cxf.resource.URIResolver;
+import org.apache.cxf.staxutils.StaxUtils;
+import org.apache.cxf.tools.corba.utils.FileOutputStreamFactory;
+import org.apache.cxf.tools.corba.utils.OutputStreamFactory;
+import org.apache.cxf.tools.util.FileWriterUtil;
+import org.apache.cxf.tools.util.OutputStreamCreator;
import org.apache.commons.io.FileUtils;
import org.apache.tools.ant.AntClassLoader;
import org.apache.tools.ant.DirectoryScanner;
@@ -109,6 +119,70 @@ public class Test {
new FileDataSource((String) source());
// "javax.activation;FileDataSource;true;FileDataSource;(File);;Argument[0];path-injection;manual"
new FileDataSource((File) source());
+ // "org.apache.cxf.common.classloader;ClassLoaderUtils;true;getResourceAsStream;(String,Class);;Argument[0];path-injection;manual"
+ ClassLoaderUtils.getResourceAsStream((String) source(), null);
+ // "org.apache.cxf.common.jaxb;JAXBUtils;true;createFileCodeWriter;(File);;Argument[0];path-injection;manual"
+ JAXBUtils.createFileCodeWriter((File) source());
+ // "org.apache.cxf.common.jaxb;JAXBUtils;true;createFileCodeWriter;(File,String);;Argument[0];path-injection;manual"
+ JAXBUtils.createFileCodeWriter((File) source(), null);
+ // "org.apache.cxf.configuration.jsse:SSLUtils;true;loadFile;(String);;Argument[0];path-injection;manual"
+ new SSLUtils() {
+ public void test() {
+ loadFile((String) source());
+ }
+ };
+ // "org.apache.cxf.helpers;FileUtils;true;delete;(File);;Argument[0];path-injection;manual"
+ org.apache.cxf.helpers.FileUtils.delete((File) source());
+ // "org.apache.cxf.helpers;FileUtils;true;delete;(File,boolean);;Argument[0];path-injection;manual"
+ org.apache.cxf.helpers.FileUtils.delete((File) source(), false);
+ // "org.apache.cxf.helpers;FileUtils;true;mkdir;(File);;Argument[0];path-injection;manual"
+ org.apache.cxf.helpers.FileUtils.mkDir((File) source());
+ // "org.apache.cxf.helpers;FileUtils;true;readLines;(File);;Argument[0];path-injection;manual"
+ org.apache.cxf.helpers.FileUtils.readLines((File) source());
+ // "org.apache.cxf.helpers;FileUtils;true;removeDir;(File);;Argument[0];path-injection;manual"
+ org.apache.cxf.helpers.FileUtils.removeDir((File) source());
+ // "org.apache.cxf.resource;ExtendedURIResolver;true;resolve;(String,String);;Argument[1];path-injection;manual"
+ new ExtendedURIResolver().resolve(null, (String) source()); // $ SSRF
+ // "org.apache.cxf.resource;URIResolver;true;URIResolver;(String,String);;Argument[0];path-injection;manual"
+ new URIResolver((String) source(), null); // $ SSRF
+ // "org.apache.cxf.resource;URIResolver;true;URIResolver;(String,String,Class);;Argument[0];path-injection;manual"
+ new URIResolver((String) source(), null, null); // $ SSRF
+ // "org.apache.cxf.resource;URIResolver;true;resolve;(String,String,Class);;Argument[0];path-injection;manual"
+ new URIResolver().resolve((String) source(), null, null); // $ SSRF
+ // "org.apache.cxf.staxutils;StaxUtils;true;read;(File);;Argument[0];path-injection;manual"
+ StaxUtils.read((File) source()); // $ SSRF
+ // "org.apache.cxf.tools.corba.utils;FileOutputStreamFactory;true;FileOutputStreamFactory;(String);;Argument[0];path-injection;manual"
+ new FileOutputStreamFactory((String) source()); // $ SSRF
+ // "org.apache.cxf.tools.corba.utils;FileOutputStreamFactory;true;FileOutputStreamFactory;(String,FileOutputStreamFactory);;Argument[0];path-injection;manual"
+ new FileOutputStreamFactory((String) source(), null); // $ SSRF
+ // "org.apache.cxf.tools.corba.utils;OutputStreamFactory;true;createOutputStream;(String);;Argument[0];path-injection;manual"
+ new FileOutputStreamFactory().createOutputStream((String) source()); // $ SSRF
+ // "org.apache.cxf.tools.corba.utils;OutputStreamFactory;true;createOutputStream;(String,String);;Argument[0];path-injection;manual"
+ new FileOutputStreamFactory().createOutputStream((String) source(), null); // $ SSRF
+ // "org.apache.cxf.tools.corba.utils;OutputStreamFactory;true;createOutputStream;(String,String);;Argument[1];path-injection;manual"
+ new FileOutputStreamFactory().createOutputStream(null, (String) source()); // $ SSRF
+ // @formatter:off
+ // "org.apache.cxf.tools.util;FileWriterUtil;true;FileWriterUtil;(String,OutputStreamCreator);;Argument[0];path-injection;manual"
+ new FileWriterUtil((String) source(), null); // $ SSRF
+ // "org.apache.cxf.tools.util;FileWriterUtil;true;buildDir;(String);;Argument[0];path-injection;manual"
+ new FileWriterUtil().buildDir((String) source()); // $ SSRF
+ // "org.apache.cxf.tools.util;FileWriterUtil;true;getFileToWrite;(String,String);;Argument[0];path-injection;manual"
+ new FileWriterUtil().getFileToWrite((String) source(), (String) null); // $ SSRF
+ // "org.apache.cxf.tools.util;FileWriterUtil;true;getFileToWrite;(String,String);;Argument[1];path-injection;manual"
+ new FileWriterUtil().getFileToWrite((String) null, (String) source()); // $ SSRF
+ // "org.apache.cxf.tools.util;FileWriterUtil;true;getWriter;(File,String);;Argument[0];path-injection;manual"
+ new FileWriterUtil().getWriter((File) source(), (String) null); // $ SSRF
+ // "org.apache.cxf.tools.util;FileWriterUtil;true;getWriter;(String,String);;Argument[0];path-injection;manual"
+ new FileWriterUtil().getWriter((String) source(), null); // $ SSRF
+ // "org.apache.cxf.tools.util;FileWriterUtil;true;getWriter;(String,String);;Argument[1];path-injection;manual"
+ new FileWriterUtil().getWriter((String) null, (String) source()); // $ SSRF
+ // "org.apache.cxf.tools.util;FileWriterUtil;true;getWriter;(String,String,String);;Argument[0];path-injection;manual"
+ new FileWriterUtil().getWriter((String) source(), null, null); // $ SSRF
+ // "org.apache.cxf.tools.util;FileWriterUtil;true;getWriter;(String,String,String);;Argument[1];path-injection;manual"
+ new FileWriterUtil().getWriter((String) null, (String) source(), null); // $ SSRF
+ // "org.apache.cxf.tools.util;OutputStreamCreator;true;createOutputStream;(File);;Argument[0];path-injection;manual"
+ new OutputStreamCreator().createOutputStream((File) source()); // $ SSRF
+ // @formatter:on
}
void test(AntClassLoader acl) {
diff --git a/java/ql/test/query-tests/security/CWE-022/semmle/tests/options b/java/ql/test/query-tests/security/CWE-022/semmle/tests/options
index 99f205115cd..6f6c5a27888 100644
--- a/java/ql/test/query-tests/security/CWE-022/semmle/tests/options
+++ b/java/ql/test/query-tests/security/CWE-022/semmle/tests/options
@@ -1 +1 @@
-// semmle-extractor-options: --javac-args -cp ${testdir}/../../../../../stubs/servlet-api-2.4:${testdir}/../../../../../stubs/apache-commons-io-2.6:${testdir}/../../../../../stubs/cargo:${testdir}/../../../../../stubs/apache-ant-1.10.13:${testdir}/../../../../../stubs/stapler-1.263:${testdir}/../../../../../stubs/javax-servlet-2.5:${testdir}/../../../../../stubs/apache-commons-jelly-1.0.1:${testdir}/../../../../../stubs/apache-commons-fileupload-1.4:${testdir}/../../../../../stubs/saxon-xqj-9.x:${testdir}/../../../../../stubs/apache-commons-beanutils:${testdir}/../../../../../stubs/dom4j-2.1.1:${testdir}/../../../../../stubs/apache-commons-lang:${testdir}/../../../../../stubs/jaxen-1.2.0:${testdir}/../../../../../stubs/jmh-1.3.6:${testdir}/../../../../../stubs/springframework-5.3.8:${testdir}/../../../../../stubs/jaxws-api-2.0
\ No newline at end of file
+// semmle-extractor-options: --javac-args -cp ${testdir}/../../../../../stubs/servlet-api-2.4:${testdir}/../../../../../stubs/apache-commons-io-2.6:${testdir}/../../../../../stubs/cargo:${testdir}/../../../../../stubs/apache-ant-1.10.13:${testdir}/../../../../../stubs/stapler-1.263:${testdir}/../../../../../stubs/javax-servlet-2.5:${testdir}/../../../../../stubs/apache-commons-jelly-1.0.1:${testdir}/../../../../../stubs/apache-commons-fileupload-1.4:${testdir}/../../../../../stubs/saxon-xqj-9.x:${testdir}/../../../../../stubs/apache-commons-beanutils:${testdir}/../../../../../stubs/dom4j-2.1.1:${testdir}/../../../../../stubs/apache-commons-lang:${testdir}/../../../../../stubs/jaxen-1.2.0:${testdir}/../../../../../stubs/jmh-1.3.6:${testdir}/../../../../../stubs/springframework-5.3.8:${testdir}/../../../../../stubs/jaxws-api-2.0:${testdir}/../../../../../stubs/apache-cxf
diff --git a/java/ql/test/query-tests/security/CWE-117/LogInjectionTest.java b/java/ql/test/query-tests/security/CWE-117/LogInjectionTest.java
index 4bcdb197e15..a28a55cbbba 100644
--- a/java/ql/test/query-tests/security/CWE-117/LogInjectionTest.java
+++ b/java/ql/test/query-tests/security/CWE-117/LogInjectionTest.java
@@ -3,6 +3,7 @@ import java.util.logging.LogRecord;
import java.util.regex.Pattern;
import com.google.common.flogger.LoggingApi;
import org.apache.commons.logging.Log;
+import org.apache.cxf.common.logging.LogUtils;
import org.apache.log4j.Category;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogBuilder;
@@ -2122,5 +2123,21 @@ public class LogInjectionTest {
android.util.Log.e("", (String) source()); // $ hasTaintFlow
android.util.Log.wtf("", (String) source()); // $ hasTaintFlow
}
+ {
+ // @formatter:off
+ // "org.apache.cxf.common.logging;LogUtils;true;log;(Logger,Level,String);;Argument[2];log-injection;manual"
+ LogUtils.log(null, null, (String) source()); // $ hasTaintFlow
+ // "org.apache.cxf.common.logging;LogUtils;true;log;(Logger,Level,String,Object);;Argument[2];log-injection;manual"
+ LogUtils.log(null, null, (String) source(), (Object) null); // $ hasTaintFlow
+ // "org.apache.cxf.common.logging;LogUtils;true;log;(Logger,Level,String,Object[]);;Argument[2];log-injection;manual"
+ LogUtils.log(null, null, (String) source(), (Object[]) null); // $ hasTaintFlow
+ // "org.apache.cxf.common.logging;LogUtils;true;log;(Logger,Level,String,Throwable);;Argument[2];log-injection;manual"
+ LogUtils.log(null, null, (String) source(), (Throwable) null); // $ hasTaintFlow
+ // "org.apache.cxf.common.logging;LogUtils;true;log;(Logger,Level,String,Throwable,Object);;Argument[2];log-injection;manual"
+ LogUtils.log(null, null, (String) source(), (Throwable) null, (Object) null); // $ hasTaintFlow
+ // "org.apache.cxf.common.logging;LogUtils;true;log;(Logger,Level,String,Throwable,Object[]);;Argument[2];log-injection;manual"
+ LogUtils.log(null, null, (String) source(), (Throwable) null, (Object) null, (Object) null); // $ hasTaintFlow
+ // @formatter:on
+ }
}
}
diff --git a/java/ql/test/query-tests/security/CWE-117/options b/java/ql/test/query-tests/security/CWE-117/options
index 01138ecc34b..372b08b0806 100644
--- a/java/ql/test/query-tests/security/CWE-117/options
+++ b/java/ql/test/query-tests/security/CWE-117/options
@@ -1 +1 @@
-//semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/apache-log4j-1.2.17:${testdir}/../../../stubs/apache-log4j-2.14.1:${testdir}/../../../stubs/apache-commons-logging-1.2:${testdir}/../../../stubs/jboss-logging-3.4.2:${testdir}/../../../stubs/slf4j-2.0.0:${testdir}/../../../stubs/scijava-common-2.87.1:${testdir}/../../../stubs/flogger-0.7.1:${testdir}/../../../stubs/google-android-9.0.0
\ No newline at end of file
+//semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/apache-log4j-1.2.17:${testdir}/../../../stubs/apache-log4j-2.14.1:${testdir}/../../../stubs/apache-commons-logging-1.2:${testdir}/../../../stubs/jboss-logging-3.4.2:${testdir}/../../../stubs/slf4j-2.0.0:${testdir}/../../../stubs/scijava-common-2.87.1:${testdir}/../../../stubs/flogger-0.7.1:${testdir}/../../../stubs/google-android-9.0.0:${testdir}/../../../stubs/apache-cxf
\ No newline at end of file
diff --git a/java/ql/test/query-tests/security/CWE-918/mad/Test.java b/java/ql/test/query-tests/security/CWE-918/mad/Test.java
index 29cb7abd793..5bf070bbe50 100644
--- a/java/ql/test/query-tests/security/CWE-918/mad/Test.java
+++ b/java/ql/test/query-tests/security/CWE-918/mad/Test.java
@@ -4,10 +4,15 @@ import java.net.Socket;
import java.net.SocketAddress;
import java.net.URL;
import java.net.URLClassLoader;
+import java.util.List;
import javax.activation.URLDataSource;
import javax.servlet.http.HttpServletRequest;
import javafx.scene.web.WebEngine;
import org.apache.commons.jelly.JellyContext;
+import org.apache.cxf.catalog.OASISCatalogManager;
+import org.apache.cxf.common.classloader.ClassLoaderUtils;
+import org.apache.cxf.resource.ExtendedURIResolver;
+import org.apache.cxf.resource.URIResolver;
import org.codehaus.cargo.container.installer.ZipURLInstaller;
import org.kohsuke.stapler.HttpResponses;
import play.libs.ws.WSClient;
@@ -35,7 +40,7 @@ public class Test {
((URL) source()).openStream(); // $ SSRF
}
- public void test(URLClassLoader cl) throws Exception {
+ public void test() throws Exception {
// "java.net;URLClassLoader;false;URLClassLoader;(String,URL[],ClassLoader);;Argument[1];open-url;manual"
new URLClassLoader("", (URL[]) source(), null); // $ SSRF
// "java.net;URLClassLoader;false;URLClassLoader;(String,URL[],ClassLoader,URLStreamHandlerFactory);;Argument[1];open-url;manual"
@@ -62,6 +67,24 @@ public class Test {
new JellyContext((URL) source()); // $ SSRF
// "javax.activation;URLDataSource;true;URLDataSource;(URL);;Argument[0];request-forgery;manual"
new URLDataSource((URL) source()); // $ SSRF
+ // "org.apache.cxf.catalog;OASISCatalogManager;true;loadCatalog;(URL);;Argument[0];request-forgery;manual"
+ new OASISCatalogManager().loadCatalog((URL) source()); // $ SSRF
+ // @formatter:off
+ // "org.apache.cxf.common.classloader;ClassLoaderUtils;true;getURLClassLoader;(URL[],ClassLoader);;Argument[0];request-forgery;manual"
+ new ClassLoaderUtils().getURLClassLoader((URL[]) source(), null); // $ SSRF
+ // "org.apache.cxf.common.classloader;ClassLoaderUtils;true;getURLClassLoader;(List,ClassLoader);;Argument[0];request-forgery;manual"
+ new ClassLoaderUtils().getURLClassLoader((List) source(), null); // $ SSRF
+ // "org.apache.cxf.resource;ExtendedURIResolver;true;resolve;(String,String);;Argument[0];request-forgery;manual"]
+ new ExtendedURIResolver().resolve((String) source(), null); // $ SSRF
+ // "org.apache.cxf.resource;URIResolver;true;URIResolver;(String);;Argument[0];request-forgery;manual"]
+ new URIResolver((String) source()); // $ SSRF
+ // "org.apache.cxf.resource;URIResolver;true;URIResolver;(String,String);;Argument[1];request-forgery;manual"]
+ new URIResolver(null, (String) source()); // $ SSRF
+ // "org.apache.cxf.resource;URIResolver;true;URIResolver;(String,String,Class);;Argument[1];request-forgery;manual"]
+ new URIResolver(null, (String) source(), null); // $ SSRF
+ // "org.apache.cxf.resource;URIResolver;true;resolve;(String,String,Class);;Argument[1];request-forgery;manual"
+ new URIResolver().resolve(null, (String) source(), null); // $ SSRF
+ // @formatter:on
}
public void test(WebEngine webEngine) {
diff --git a/java/ql/test/query-tests/security/CWE-918/options b/java/ql/test/query-tests/security/CWE-918/options
index 64fb822e2af..4158843ef98 100644
--- a/java/ql/test/query-tests/security/CWE-918/options
+++ b/java/ql/test/query-tests/security/CWE-918/options
@@ -1 +1 @@
-//semmle-extractor-options: --javac-args -source 11 -target 11 -cp ${testdir}/../../../stubs/springframework-5.3.8:${testdir}/../../../stubs/javax-ws-rs-api-2.1.1:${testdir}/../../../stubs/javax-ws-rs-api-3.0.0:${testdir}/../../../stubs/apache-http-4.4.13/:${testdir}/../../../stubs/projectreactor-3.4.3/:${testdir}/../../../stubs/postgresql-42.3.3/:${testdir}/../../../stubs/HikariCP-3.4.5/:${testdir}/../../../stubs/spring-jdbc-5.3.8/:${testdir}/../../../stubs/jdbi3-core-3.27.2/:${testdir}/../../../stubs/cargo:${testdir}/../../../stubs/javafx-web:${testdir}/../../../stubs/apache-commons-jelly-1.0.1:${testdir}/../../../stubs/dom4j-2.1.1:${testdir}/../../../stubs/jaxen-1.2.0:${testdir}/../../../stubs/stapler-1.263:${testdir}/../../../stubs/javax-servlet-2.5:${testdir}/../../../stubs/apache-commons-fileupload-1.4:${testdir}/../../../stubs/saxon-xqj-9.x:${testdir}/../../../stubs/apache-commons-beanutils:${testdir}/../../../stubs/apache-commons-lang:${testdir}/../../../stubs/apache-http-5:${testdir}/../../../stubs/playframework-2.6.x:${testdir}/../../../stubs/jaxws-api-2.0
+//semmle-extractor-options: --javac-args -source 11 -target 11 -cp ${testdir}/../../../stubs/springframework-5.3.8:${testdir}/../../../stubs/javax-ws-rs-api-2.1.1:${testdir}/../../../stubs/javax-ws-rs-api-3.0.0:${testdir}/../../../stubs/apache-http-4.4.13/:${testdir}/../../../stubs/projectreactor-3.4.3/:${testdir}/../../../stubs/postgresql-42.3.3/:${testdir}/../../../stubs/HikariCP-3.4.5/:${testdir}/../../../stubs/spring-jdbc-5.3.8/:${testdir}/../../../stubs/jdbi3-core-3.27.2/:${testdir}/../../../stubs/cargo:${testdir}/../../../stubs/javafx-web:${testdir}/../../../stubs/apache-commons-jelly-1.0.1:${testdir}/../../../stubs/dom4j-2.1.1:${testdir}/../../../stubs/jaxen-1.2.0:${testdir}/../../../stubs/stapler-1.263:${testdir}/../../../stubs/javax-servlet-2.5:${testdir}/../../../stubs/apache-commons-fileupload-1.4:${testdir}/../../../stubs/saxon-xqj-9.x:${testdir}/../../../stubs/apache-commons-beanutils:${testdir}/../../../stubs/apache-commons-lang:${testdir}/../../../stubs/apache-http-5:${testdir}/../../../stubs/playframework-2.6.x:${testdir}/../../../stubs/jaxws-api-2.0:${testdir}/../../../stubs/apache-cxf
diff --git a/java/ql/test/stubs/apache-cxf/org/apache/cxf/catalog/OASISCatalogManager.java b/java/ql/test/stubs/apache-cxf/org/apache/cxf/catalog/OASISCatalogManager.java
new file mode 100644
index 00000000000..096ebe8b75c
--- /dev/null
+++ b/java/ql/test/stubs/apache-cxf/org/apache/cxf/catalog/OASISCatalogManager.java
@@ -0,0 +1,7 @@
+package org.apache.cxf.catalog;
+
+import java.net.URL;
+
+public class OASISCatalogManager {
+ public final void loadCatalog(URL catalogURL) {}
+}
diff --git a/java/ql/test/stubs/apache-cxf/org/apache/cxf/common/classloader/ClassLoaderUtils.java b/java/ql/test/stubs/apache-cxf/org/apache/cxf/common/classloader/ClassLoaderUtils.java
new file mode 100644
index 00000000000..e1f3f3407ee
--- /dev/null
+++ b/java/ql/test/stubs/apache-cxf/org/apache/cxf/common/classloader/ClassLoaderUtils.java
@@ -0,0 +1,19 @@
+package org.apache.cxf.common.classloader;
+
+import java.io.InputStream;
+import java.net.URL;
+import java.util.List;
+
+public class ClassLoaderUtils {
+ public static ClassLoader getURLClassLoader(URL[] urls, ClassLoader parent) {
+ return null;
+ }
+
+ public static ClassLoader getURLClassLoader(List urlList, ClassLoader parent) {
+ return null;
+ }
+
+ public static InputStream getResourceAsStream(String resourceName, Class> callingClass) {
+ return null;
+ }
+}
diff --git a/java/ql/test/stubs/apache-cxf/org/apache/cxf/common/jaxb/JAXBUtils.java b/java/ql/test/stubs/apache-cxf/org/apache/cxf/common/jaxb/JAXBUtils.java
new file mode 100644
index 00000000000..86bc017b6f2
--- /dev/null
+++ b/java/ql/test/stubs/apache-cxf/org/apache/cxf/common/jaxb/JAXBUtils.java
@@ -0,0 +1,13 @@
+package org.apache.cxf.common.jaxb;
+
+import java.io.File;
+
+public class JAXBUtils {
+ public static Object createFileCodeWriter(File f) {
+ return null;
+ }
+
+ public static Object createFileCodeWriter(File f, String encoding) {
+ return null;
+ }
+}
diff --git a/java/ql/test/stubs/apache-cxf/org/apache/cxf/common/logging/LogUtils.java b/java/ql/test/stubs/apache-cxf/org/apache/cxf/common/logging/LogUtils.java
new file mode 100644
index 00000000000..bc0119f1e63
--- /dev/null
+++ b/java/ql/test/stubs/apache-cxf/org/apache/cxf/common/logging/LogUtils.java
@@ -0,0 +1,20 @@
+package org.apache.cxf.common.logging;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+public class LogUtils {
+ public static void log(Logger logger, Level level, String message) {}
+
+ public static void log(Logger logger, Level level, String message, Object parameter) {}
+
+ public static void log(Logger logger, Level level, String message, Object[] parameters) {}
+
+ public static void log(Logger logger, Level level, String message, Throwable throwable) {}
+
+ public static void log(Logger logger, Level level, String message, Throwable throwable,
+ Object parameter) {}
+
+ public static void log(Logger logger, Level level, String message, Throwable throwable,
+ Object... parameters) {}
+}
diff --git a/java/ql/test/stubs/apache-cxf/org/apache/cxf/configuration/jsse/SSLUtils.java b/java/ql/test/stubs/apache-cxf/org/apache/cxf/configuration/jsse/SSLUtils.java
new file mode 100644
index 00000000000..a9613edd8e1
--- /dev/null
+++ b/java/ql/test/stubs/apache-cxf/org/apache/cxf/configuration/jsse/SSLUtils.java
@@ -0,0 +1,7 @@
+package org.apache.cxf.configuration.jsse;
+
+public class SSLUtils {
+ protected static byte[] loadFile(String fileName) {
+ return null;
+ }
+}
diff --git a/java/ql/test/stubs/apache-cxf/org/apache/cxf/helpers/FileUtils.java b/java/ql/test/stubs/apache-cxf/org/apache/cxf/helpers/FileUtils.java
new file mode 100644
index 00000000000..e6515acc1c9
--- /dev/null
+++ b/java/ql/test/stubs/apache-cxf/org/apache/cxf/helpers/FileUtils.java
@@ -0,0 +1,65 @@
+package org.apache.cxf.helpers;
+
+import java.io.File;
+import java.util.List;
+
+public class FileUtils {
+ public static File createTempFile(String prefix, String suffix) {
+ return null;
+ }
+
+ public static File createTempFile(String prefix, String suffix, File parentDir,
+ boolean deleteOnExit) {
+ return null;
+ }
+
+ public static File createTmpDir() {
+ return null;
+ }
+
+ public static File createTmpDir(boolean addHook) {
+ return null;
+ }
+
+ public static void delete(File f) {}
+
+ public static void delete(File f, boolean inShutdown) {}
+
+ public static boolean exists(File file) {
+ return false;
+ }
+
+ public static File getDefaultTempDir() {
+ return null;
+ }
+
+ public static List getFiles(File dir, String pattern) {
+ return null;
+ }
+
+ public static List getFilesRecurseUsingSuffix(File dir, String suffix) {
+ return null;
+ }
+
+ public static List getFilesUsingSuffix(File dir, String suffix) {
+ return null;
+ }
+
+ public static boolean isValidFileName(String name) {
+ return false;
+ }
+
+ public static void maybeDeleteDefaultTempDir() {}
+
+ public static void mkDir(File dir) {}
+
+ public static List readLines(File file) {
+ return null;
+ }
+
+ public static void removeDir(File d) {}
+
+ public static String stripPath(String name) {
+ return null;
+ }
+}
diff --git a/java/ql/test/stubs/apache-cxf/org/apache/cxf/resource/ExtendedURIResolver.java b/java/ql/test/stubs/apache-cxf/org/apache/cxf/resource/ExtendedURIResolver.java
new file mode 100644
index 00000000000..1858337c7e5
--- /dev/null
+++ b/java/ql/test/stubs/apache-cxf/org/apache/cxf/resource/ExtendedURIResolver.java
@@ -0,0 +1,9 @@
+package org.apache.cxf.resource;
+
+import org.xml.sax.InputSource;
+
+public class ExtendedURIResolver {
+ public InputSource resolve(String curUri, String baseUri) {
+ return null;
+ }
+}
diff --git a/java/ql/test/stubs/apache-cxf/org/apache/cxf/resource/URIResolver.java b/java/ql/test/stubs/apache-cxf/org/apache/cxf/resource/URIResolver.java
new file mode 100644
index 00000000000..6e94734fcd3
--- /dev/null
+++ b/java/ql/test/stubs/apache-cxf/org/apache/cxf/resource/URIResolver.java
@@ -0,0 +1,13 @@
+package org.apache.cxf.resource;
+
+public class URIResolver {
+ public URIResolver() {}
+
+ public URIResolver(String path) {}
+
+ public URIResolver(String baseUriStr, String uriStr) {}
+
+ public URIResolver(String baseUriStr, String uriStr, Class> calling) {}
+
+ public void resolve(String baseUriStr, String uriStr, Class> callingCls) {}
+}
diff --git a/java/ql/test/stubs/apache-cxf/org/apache/cxf/staxutils/StaxUtils.java b/java/ql/test/stubs/apache-cxf/org/apache/cxf/staxutils/StaxUtils.java
new file mode 100644
index 00000000000..3106c985014
--- /dev/null
+++ b/java/ql/test/stubs/apache-cxf/org/apache/cxf/staxutils/StaxUtils.java
@@ -0,0 +1,10 @@
+package org.apache.cxf.staxutils;
+
+import java.io.File;
+import org.w3c.dom.Document;
+
+public class StaxUtils {
+ public static Document read(File is) {
+ return null;
+ }
+}
diff --git a/java/ql/test/stubs/apache-cxf/org/apache/cxf/tools/corba/utils/FileOutputStreamFactory.java b/java/ql/test/stubs/apache-cxf/org/apache/cxf/tools/corba/utils/FileOutputStreamFactory.java
new file mode 100644
index 00000000000..2f2e55b58ec
--- /dev/null
+++ b/java/ql/test/stubs/apache-cxf/org/apache/cxf/tools/corba/utils/FileOutputStreamFactory.java
@@ -0,0 +1,19 @@
+package org.apache.cxf.tools.corba.utils;
+
+import java.io.OutputStream;
+
+public class FileOutputStreamFactory implements OutputStreamFactory {
+ public FileOutputStreamFactory() {}
+
+ public FileOutputStreamFactory(String dir) {}
+
+ public FileOutputStreamFactory(String dir, FileOutputStreamFactory p) {}
+
+ public OutputStream createOutputStream(String name) {
+ return null;
+ }
+
+ public OutputStream createOutputStream(String packageName, String name) {
+ return null;
+ }
+}
diff --git a/java/ql/test/stubs/apache-cxf/org/apache/cxf/tools/corba/utils/OutputStreamFactory.java b/java/ql/test/stubs/apache-cxf/org/apache/cxf/tools/corba/utils/OutputStreamFactory.java
new file mode 100644
index 00000000000..e740fd8f031
--- /dev/null
+++ b/java/ql/test/stubs/apache-cxf/org/apache/cxf/tools/corba/utils/OutputStreamFactory.java
@@ -0,0 +1,9 @@
+package org.apache.cxf.tools.corba.utils;
+
+import java.io.OutputStream;
+
+public interface OutputStreamFactory {
+ OutputStream createOutputStream(String name);
+
+ OutputStream createOutputStream(String packageName, String name);
+}
diff --git a/java/ql/test/stubs/apache-cxf/org/apache/cxf/tools/util/FileWriterUtil.java b/java/ql/test/stubs/apache-cxf/org/apache/cxf/tools/util/FileWriterUtil.java
new file mode 100644
index 00000000000..a42f8facd3d
--- /dev/null
+++ b/java/ql/test/stubs/apache-cxf/org/apache/cxf/tools/util/FileWriterUtil.java
@@ -0,0 +1,30 @@
+package org.apache.cxf.tools.util;
+
+import java.io.File;
+import java.io.Writer;
+
+public class FileWriterUtil {
+ public FileWriterUtil() {}
+
+ public FileWriterUtil(String targetDir, OutputStreamCreator osc) {}
+
+ public File buildDir(String packageName) {
+ return null;
+ }
+
+ public File getFileToWrite(String packageName, String fileName) {
+ return null;
+ }
+
+ public Writer getWriter(File fn, String encoding) {
+ return null;
+ }
+
+ public Writer getWriter(String packageName, String fileName) {
+ return null;
+ }
+
+ public Writer getWriter(String packageName, String fileName, String encoding) {
+ return null;
+ }
+}
diff --git a/java/ql/test/stubs/apache-cxf/org/apache/cxf/tools/util/OutputStreamCreator.java b/java/ql/test/stubs/apache-cxf/org/apache/cxf/tools/util/OutputStreamCreator.java
new file mode 100644
index 00000000000..9cac1e27e53
--- /dev/null
+++ b/java/ql/test/stubs/apache-cxf/org/apache/cxf/tools/util/OutputStreamCreator.java
@@ -0,0 +1,11 @@
+package org.apache.cxf.tools.util;
+
+import java.io.File;
+import java.io.OutputStream;
+
+public class OutputStreamCreator {
+ public OutputStream createOutputStream(File file) {
+ return null;
+ }
+
+}
From 25ac87279e262062fb4e8c6859dcbd13add6da27 Mon Sep 17 00:00:00 2001
From: Tony Torralba
Date: Wed, 23 Aug 2023 10:47:58 +0200
Subject: [PATCH 081/788] Add change note
---
java/ql/lib/change-notes/2023-08-23-apache-cxf-models.md | 4 ++++
1 file changed, 4 insertions(+)
create mode 100644 java/ql/lib/change-notes/2023-08-23-apache-cxf-models.md
diff --git a/java/ql/lib/change-notes/2023-08-23-apache-cxf-models.md b/java/ql/lib/change-notes/2023-08-23-apache-cxf-models.md
new file mode 100644
index 00000000000..fbd0fef3b7f
--- /dev/null
+++ b/java/ql/lib/change-notes/2023-08-23-apache-cxf-models.md
@@ -0,0 +1,4 @@
+---
+category: minorAnalysis
+---
+* Added new dataflow models for the Apache CXF framework.
From 5d986d7b60b6ba911cc6d784b01f3476bbbeee08 Mon Sep 17 00:00:00 2001
From: data-douser <70299490+data-douser@users.noreply.github.com>
Date: Fri, 25 Aug 2023 07:00:32 -0600
Subject: [PATCH 082/788] Update codeql-library-for-go.rst
Correct a typo in the golang docs.
---
docs/codeql/codeql-language-guides/codeql-library-for-go.rst | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/codeql/codeql-language-guides/codeql-library-for-go.rst b/docs/codeql/codeql-language-guides/codeql-library-for-go.rst
index 33468ab7a71..ab8c7bf65af 100644
--- a/docs/codeql/codeql-language-guides/codeql-library-for-go.rst
+++ b/docs/codeql/codeql-language-guides/codeql-library-for-go.rst
@@ -275,7 +275,7 @@ Entities and name binding
Not all elements of a code base can be represented as AST nodes. For example, functions defined in
the standard library or in a dependency do not have a source-level definition within the source code
of the program itself, and built-in functions like ``len`` do not have a definition at all. Hence
-functions cannot simplify be identified with their definition, and similarly for variables, types,
+functions cannot simply be identified with their definition, and similarly for variables, types,
and so on.
To smooth over this difference and provide a unified view of functions no matter where they are
From 245c24077dc3853022abeaf0bee4d59d2e5a0c95 Mon Sep 17 00:00:00 2001
From: Rasmus Wriedt Larsen
Date: Fri, 25 Aug 2023 12:29:44 +0200
Subject: [PATCH 083/788] Python: Move `SqlInjection` to new dataflow API
---
.../security/dataflow/SqlInjectionQuery.qll | 15 ++++++++++++++-
python/ql/src/Security/CWE-089/SqlInjection.ql | 6 +++---
2 files changed, 17 insertions(+), 4 deletions(-)
diff --git a/python/ql/lib/semmle/python/security/dataflow/SqlInjectionQuery.qll b/python/ql/lib/semmle/python/security/dataflow/SqlInjectionQuery.qll
index 23e6b91a0ef..9b78686fed3 100644
--- a/python/ql/lib/semmle/python/security/dataflow/SqlInjectionQuery.qll
+++ b/python/ql/lib/semmle/python/security/dataflow/SqlInjectionQuery.qll
@@ -12,9 +12,11 @@ import semmle.python.dataflow.new.TaintTracking
import SqlInjectionCustomizations::SqlInjection
/**
+ * DEPRECATED: Use `SqlInjectionFlow` module instead.
+ *
* A taint-tracking configuration for detecting "SQL injection" vulnerabilities.
*/
-class Configuration extends TaintTracking::Configuration {
+deprecated class Configuration extends TaintTracking::Configuration {
Configuration() { this = "SqlInjection" }
override predicate isSource(DataFlow::Node source) { source instanceof Source }
@@ -27,3 +29,14 @@ class Configuration extends TaintTracking::Configuration {
guard instanceof SanitizerGuard
}
}
+
+private module SqlInjectionConfig 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 "SQL injection" vulnerabilities. */
+module SqlInjectionFlow = TaintTracking::Global;
diff --git a/python/ql/src/Security/CWE-089/SqlInjection.ql b/python/ql/src/Security/CWE-089/SqlInjection.ql
index 5e910cf3edf..e6861e86066 100644
--- a/python/ql/src/Security/CWE-089/SqlInjection.ql
+++ b/python/ql/src/Security/CWE-089/SqlInjection.ql
@@ -13,9 +13,9 @@
import python
import semmle.python.security.dataflow.SqlInjectionQuery
-import DataFlow::PathGraph
+import SqlInjectionFlow::PathGraph
-from Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink
-where config.hasFlowPath(source, sink)
+from SqlInjectionFlow::PathNode source, SqlInjectionFlow::PathNode sink
+where SqlInjectionFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "This SQL query depends on a $@.", source.getNode(),
"user-provided value"
From e97032909aaafa1df1da300af341999ae237608f Mon Sep 17 00:00:00 2001
From: Rasmus Wriedt Larsen
Date: Fri, 25 Aug 2023 15:34:51 +0200
Subject: [PATCH 084/788] Python: Move `PathInjection` to new dataflow API
---
.../security/dataflow/PathInjectionQuery.qll | 53 ++++++++++++++++++-
.../ql/src/Security/CWE-022/PathInjection.ql | 6 +--
.../PathInjection.expected | 8 ++-
3 files changed, 61 insertions(+), 6 deletions(-)
diff --git a/python/ql/lib/semmle/python/security/dataflow/PathInjectionQuery.qll b/python/ql/lib/semmle/python/security/dataflow/PathInjectionQuery.qll
index 5616a94465a..307c16da05d 100644
--- a/python/ql/lib/semmle/python/security/dataflow/PathInjectionQuery.qll
+++ b/python/ql/lib/semmle/python/security/dataflow/PathInjectionQuery.qll
@@ -13,6 +13,8 @@ import semmle.python.dataflow.new.TaintTracking
import PathInjectionCustomizations::PathInjection
/**
+ * DEPRECATED: Use `PathInjectionFlow` module instead.
+ *
* A taint-tracking configuration for detecting "path injection" vulnerabilities.
*
* This configuration uses two flow states, `NotNormalized` and `NormalizedUnchecked`,
@@ -25,7 +27,7 @@ import PathInjectionCustomizations::PathInjection
*
* Such checks are ineffective in the `NotNormalized` state.
*/
-class Configuration extends TaintTracking::Configuration {
+deprecated class Configuration extends TaintTracking::Configuration {
Configuration() { this = "PathInjection" }
override predicate isSource(DataFlow::Node source, DataFlow::FlowState state) {
@@ -74,3 +76,52 @@ class NotNormalized extends DataFlow::FlowState {
class NormalizedUnchecked extends DataFlow::FlowState {
NormalizedUnchecked() { this = "NormalizedUnchecked" }
}
+
+/**
+ * This configuration uses two flow states, `NotNormalized` and `NormalizedUnchecked`,
+ * to track the requirement that a file path must be first normalized and then checked
+ * before it is safe to use.
+ *
+ * At sources, paths are assumed not normalized. At normalization points, they change
+ * state to `NormalizedUnchecked` after which they can be made safe by an appropriate
+ * check of the prefix.
+ *
+ * Such checks are ineffective in the `NotNormalized` state.
+ */
+private module PathInjectionConfig implements DataFlow::StateConfigSig {
+ class FlowState = DataFlow::FlowState;
+
+ predicate isSource(DataFlow::Node source, FlowState state) {
+ source instanceof Source and state instanceof NotNormalized
+ }
+
+ predicate isSink(DataFlow::Node sink, FlowState state) {
+ sink instanceof Sink and
+ (
+ state instanceof NotNormalized or
+ state instanceof NormalizedUnchecked
+ )
+ }
+
+ predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer }
+
+ predicate isBarrier(DataFlow::Node node, FlowState state) {
+ // Block `NotNormalized` paths here, since they change state to `NormalizedUnchecked`
+ node instanceof Path::PathNormalization and
+ state instanceof NotNormalized
+ or
+ node instanceof Path::SafeAccessCheck and
+ state instanceof NormalizedUnchecked
+ }
+
+ predicate isAdditionalFlowStep(
+ DataFlow::Node nodeFrom, FlowState stateFrom, DataFlow::Node nodeTo, FlowState stateTo
+ ) {
+ nodeFrom = nodeTo.(Path::PathNormalization).getPathArg() and
+ stateFrom instanceof NotNormalized and
+ stateTo instanceof NormalizedUnchecked
+ }
+}
+
+/** Global taint-tracking for detecting "path injection" vulnerabilities. */
+module PathInjectionFlow = TaintTracking::GlobalWithState;
diff --git a/python/ql/src/Security/CWE-022/PathInjection.ql b/python/ql/src/Security/CWE-022/PathInjection.ql
index 8548c815fe4..1686dec7c91 100644
--- a/python/ql/src/Security/CWE-022/PathInjection.ql
+++ b/python/ql/src/Security/CWE-022/PathInjection.ql
@@ -18,9 +18,9 @@
import python
import semmle.python.security.dataflow.PathInjectionQuery
-import DataFlow::PathGraph
+import PathInjectionFlow::PathGraph
-from Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink
-where config.hasFlowPath(source, sink)
+from PathInjectionFlow::PathNode source, PathInjectionFlow::PathNode sink
+where PathInjectionFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "This path depends on a $@.", source.getNode(),
"user-provided value"
diff --git a/python/ql/test/query-tests/Security/CWE-022-PathInjection/PathInjection.expected b/python/ql/test/query-tests/Security/CWE-022-PathInjection/PathInjection.expected
index b0df9a02cc0..b8bcf46ec1e 100644
--- a/python/ql/test/query-tests/Security/CWE-022-PathInjection/PathInjection.expected
+++ b/python/ql/test/query-tests/Security/CWE-022-PathInjection/PathInjection.expected
@@ -53,7 +53,8 @@ edges
| path_injection.py:84:16:84:22 | ControlFlowNode for request | path_injection.py:84:16:84:27 | ControlFlowNode for Attribute |
| path_injection.py:84:16:84:27 | ControlFlowNode for Attribute | path_injection.py:84:16:84:47 | ControlFlowNode for Attribute() |
| path_injection.py:84:16:84:47 | ControlFlowNode for Attribute() | path_injection.py:84:5:84:12 | SSA variable filename |
-| path_injection.py:85:5:85:24 | SSA variable possibly_unsafe_path | path_injection.py:87:18:87:37 | ControlFlowNode for possibly_unsafe_path |
+| path_injection.py:85:5:85:24 | SSA variable possibly_unsafe_path | path_injection.py:86:24:86:43 | ControlFlowNode for possibly_unsafe_path |
+| path_injection.py:86:24:86:43 | ControlFlowNode for possibly_unsafe_path | path_injection.py:87:18:87:37 | ControlFlowNode for possibly_unsafe_path |
| path_injection.py:91:20:91:25 | ControlFlowNode for foo_id | path_injection.py:93:5:93:8 | SSA variable path |
| path_injection.py:93:5:93:8 | SSA variable path | path_injection.py:94:14:94:17 | ControlFlowNode for path |
| path_injection.py:98:20:98:22 | ControlFlowNode for foo | path_injection.py:101:5:101:8 | SSA variable path |
@@ -78,7 +79,8 @@ edges
| path_injection.py:138:16:138:22 | ControlFlowNode for request | path_injection.py:138:16:138:27 | ControlFlowNode for Attribute |
| path_injection.py:138:16:138:27 | ControlFlowNode for Attribute | path_injection.py:138:16:138:47 | ControlFlowNode for Attribute() |
| path_injection.py:138:16:138:47 | ControlFlowNode for Attribute() | path_injection.py:138:5:138:12 | SSA variable filename |
-| path_injection.py:139:5:139:8 | SSA variable path | path_injection.py:142:14:142:17 | ControlFlowNode for path |
+| path_injection.py:139:5:139:8 | SSA variable path | path_injection.py:140:47:140:50 | ControlFlowNode for path |
+| path_injection.py:140:47:140:50 | ControlFlowNode for path | path_injection.py:142:14:142:17 | ControlFlowNode for path |
| path_injection.py:149:5:149:12 | SSA variable filename | path_injection.py:151:9:151:12 | SSA variable path |
| path_injection.py:149:16:149:22 | ControlFlowNode for request | path_injection.py:149:16:149:27 | ControlFlowNode for Attribute |
| path_injection.py:149:16:149:27 | ControlFlowNode for Attribute | path_injection.py:149:16:149:47 | ControlFlowNode for Attribute() |
@@ -171,6 +173,7 @@ nodes
| path_injection.py:84:16:84:27 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| path_injection.py:84:16:84:47 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| path_injection.py:85:5:85:24 | SSA variable possibly_unsafe_path | semmle.label | SSA variable possibly_unsafe_path |
+| path_injection.py:86:24:86:43 | ControlFlowNode for possibly_unsafe_path | semmle.label | ControlFlowNode for possibly_unsafe_path |
| path_injection.py:87:18:87:37 | ControlFlowNode for possibly_unsafe_path | semmle.label | ControlFlowNode for possibly_unsafe_path |
| path_injection.py:91:20:91:25 | ControlFlowNode for foo_id | semmle.label | ControlFlowNode for foo_id |
| path_injection.py:93:5:93:8 | SSA variable path | semmle.label | SSA variable path |
@@ -202,6 +205,7 @@ nodes
| path_injection.py:138:16:138:27 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| path_injection.py:138:16:138:47 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| path_injection.py:139:5:139:8 | SSA variable path | semmle.label | SSA variable path |
+| path_injection.py:140:47:140:50 | ControlFlowNode for path | semmle.label | ControlFlowNode for path |
| path_injection.py:142:14:142:17 | ControlFlowNode for path | semmle.label | ControlFlowNode for path |
| path_injection.py:149:5:149:12 | SSA variable filename | semmle.label | SSA variable filename |
| path_injection.py:149:16:149:22 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
From d4e4e2d4267f9cde6650654598e836bc00963783 Mon Sep 17 00:00:00 2001
From: Rasmus Wriedt Larsen
Date: Fri, 25 Aug 2023 15:37:02 +0200
Subject: [PATCH 085/788] Python: Move `TarSlip` to new dataflow API
---
.../python/security/dataflow/TarSlipQuery.qll | 19 ++++++++++++++++---
python/ql/src/Security/CWE-022/TarSlip.ql | 6 +++---
2 files changed, 19 insertions(+), 6 deletions(-)
diff --git a/python/ql/lib/semmle/python/security/dataflow/TarSlipQuery.qll b/python/ql/lib/semmle/python/security/dataflow/TarSlipQuery.qll
index 6cf41742a66..7bb008f1afb 100644
--- a/python/ql/lib/semmle/python/security/dataflow/TarSlipQuery.qll
+++ b/python/ql/lib/semmle/python/security/dataflow/TarSlipQuery.qll
@@ -1,5 +1,5 @@
/**
- * Provides a taint-tracking configuration for detecting "command injection" vulnerabilities.
+ * Provides a taint-tracking configuration for detecting "tar slip" vulnerabilities.
*
* Note, for performance reasons: only import this file if
* `TarSlip::Configuration` is needed, otherwise
@@ -12,9 +12,11 @@ import semmle.python.dataflow.new.TaintTracking
import TarSlipCustomizations::TarSlip
/**
- * A taint-tracking configuration for detecting "command injection" vulnerabilities.
+ * DEPRECATED: Use `TarSlipFlow` module instead.
+ *
+ * A taint-tracking configuration for detecting "tar slip" vulnerabilities.
*/
-class Configuration extends TaintTracking::Configuration {
+deprecated class Configuration extends TaintTracking::Configuration {
Configuration() { this = "TarSlip" }
override predicate isSource(DataFlow::Node source) { source instanceof Source }
@@ -23,3 +25,14 @@ class Configuration extends TaintTracking::Configuration {
override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer }
}
+
+private module TarSlipConfig 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 "tar slip" vulnerabilities. */
+module TarSlipFlow = TaintTracking::Global;
diff --git a/python/ql/src/Security/CWE-022/TarSlip.ql b/python/ql/src/Security/CWE-022/TarSlip.ql
index 647b41756f8..cb0cd54d19b 100644
--- a/python/ql/src/Security/CWE-022/TarSlip.ql
+++ b/python/ql/src/Security/CWE-022/TarSlip.ql
@@ -14,9 +14,9 @@
import python
import semmle.python.security.dataflow.TarSlipQuery
-import DataFlow::PathGraph
+import TarSlipFlow::PathGraph
-from Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink
-where config.hasFlowPath(source, sink)
+from TarSlipFlow::PathNode source, TarSlipFlow::PathNode sink
+where TarSlipFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "This file extraction depends on a $@.", source.getNode(),
"potentially untrusted source"
From 700841e9b0b44413d4296d04042c9d6169e5157a Mon Sep 17 00:00:00 2001
From: Rasmus Wriedt Larsen
Date: Fri, 25 Aug 2023 15:42:09 +0200
Subject: [PATCH 086/788] Python: Move `UnsafeShellCommandConstruction` to new
dataflow API
---
.../UnsafeShellCommandConstructionQuery.qll | 21 ++++++++++++++++++-
.../CWE-078/UnsafeShellCommandConstruction.ql | 8 ++++---
2 files changed, 25 insertions(+), 4 deletions(-)
diff --git a/python/ql/lib/semmle/python/security/dataflow/UnsafeShellCommandConstructionQuery.qll b/python/ql/lib/semmle/python/security/dataflow/UnsafeShellCommandConstructionQuery.qll
index 0d9ebb8a472..14a702a405e 100644
--- a/python/ql/lib/semmle/python/security/dataflow/UnsafeShellCommandConstructionQuery.qll
+++ b/python/ql/lib/semmle/python/security/dataflow/UnsafeShellCommandConstructionQuery.qll
@@ -14,9 +14,11 @@ private import CommandInjectionCustomizations::CommandInjection as CommandInject
private import semmle.python.dataflow.new.BarrierGuards
/**
+ * DEPRECATED: Use `UnsafeShellCommandConstructionFlow` module instead.
+ *
* A taint-tracking configuration for detecting shell command constructed from library input vulnerabilities.
*/
-class Configuration extends TaintTracking::Configuration {
+deprecated class Configuration extends TaintTracking::Configuration {
Configuration() { this = "UnsafeShellCommandConstruction" }
override predicate isSource(DataFlow::Node source) { source instanceof Source }
@@ -32,3 +34,20 @@ class Configuration extends TaintTracking::Configuration {
result instanceof DataFlow::FeatureHasSourceCallContext
}
}
+
+private module UnsafeShellCommandConstructionConfig 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 CommandInjection::Sanitizer // using all sanitizers from `py/command-injection`
+ }
+
+ // override to require the path doesn't have unmatched return steps
+ DataFlow::FlowFeature getAFeature() { result instanceof DataFlow::FeatureHasSourceCallContext }
+}
+
+/** Global taint-tracking for detecting "shell command constructed from library input" vulnerabilities. */
+module UnsafeShellCommandConstructionFlow =
+ TaintTracking::Global;
diff --git a/python/ql/src/Security/CWE-078/UnsafeShellCommandConstruction.ql b/python/ql/src/Security/CWE-078/UnsafeShellCommandConstruction.ql
index 10f4b771261..561bcf7dd49 100644
--- a/python/ql/src/Security/CWE-078/UnsafeShellCommandConstruction.ql
+++ b/python/ql/src/Security/CWE-078/UnsafeShellCommandConstruction.ql
@@ -16,11 +16,13 @@
import python
import semmle.python.security.dataflow.UnsafeShellCommandConstructionQuery
-import DataFlow::PathGraph
+import UnsafeShellCommandConstructionFlow::PathGraph
-from Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink, Sink sinkNode
+from
+ UnsafeShellCommandConstructionFlow::PathNode source,
+ UnsafeShellCommandConstructionFlow::PathNode sink, Sink sinkNode
where
- config.hasFlowPath(source, sink) and
+ UnsafeShellCommandConstructionFlow::flowPath(source, sink) and
sinkNode = sink.getNode()
select sinkNode.getStringConstruction(), source, sink,
"This " + sinkNode.describe() + " which depends on $@ is later used in a $@.", source.getNode(),
From b30142c1d7195e448ef7dc1d20a94206fdddc02c Mon Sep 17 00:00:00 2001
From: Rasmus Wriedt Larsen
Date: Fri, 25 Aug 2023 15:44:02 +0200
Subject: [PATCH 087/788] Python: Move `CommandInjection` to new dataflow API
---
.../security/dataflow/CommandInjectionQuery.qll | 15 ++++++++++++++-
.../ql/src/Security/CWE-078/CommandInjection.ql | 6 +++---
2 files changed, 17 insertions(+), 4 deletions(-)
diff --git a/python/ql/lib/semmle/python/security/dataflow/CommandInjectionQuery.qll b/python/ql/lib/semmle/python/security/dataflow/CommandInjectionQuery.qll
index 526fd9d0694..b9c1fb09043 100644
--- a/python/ql/lib/semmle/python/security/dataflow/CommandInjectionQuery.qll
+++ b/python/ql/lib/semmle/python/security/dataflow/CommandInjectionQuery.qll
@@ -12,9 +12,11 @@ import semmle.python.dataflow.new.TaintTracking
import CommandInjectionCustomizations::CommandInjection
/**
+ * DEPRECATED: Use `CommandInjectionFlow` module instead.
+ *
* A taint-tracking configuration for detecting "command injection" vulnerabilities.
*/
-class Configuration extends TaintTracking::Configuration {
+deprecated class Configuration extends TaintTracking::Configuration {
Configuration() { this = "CommandInjection" }
override predicate isSource(DataFlow::Node source) { source instanceof Source }
@@ -27,3 +29,14 @@ class Configuration extends TaintTracking::Configuration {
guard instanceof SanitizerGuard
}
}
+
+private module CommandInjectionConfig 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 "command injection" vulnerabilities. */
+module CommandInjectionFlow = TaintTracking::Global;
diff --git a/python/ql/src/Security/CWE-078/CommandInjection.ql b/python/ql/src/Security/CWE-078/CommandInjection.ql
index f8c48714e1a..1c2c5125b32 100644
--- a/python/ql/src/Security/CWE-078/CommandInjection.ql
+++ b/python/ql/src/Security/CWE-078/CommandInjection.ql
@@ -16,9 +16,9 @@
import python
import semmle.python.security.dataflow.CommandInjectionQuery
-import DataFlow::PathGraph
+import CommandInjectionFlow::PathGraph
-from Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink
-where config.hasFlowPath(source, sink)
+from CommandInjectionFlow::PathNode source, CommandInjectionFlow::PathNode sink
+where CommandInjectionFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "This command line depends on a $@.", source.getNode(),
"user-provided value"
From c360346e9e5a1a4962620f044774e96e4da6ead1 Mon Sep 17 00:00:00 2001
From: Rasmus Wriedt Larsen
Date: Fri, 25 Aug 2023 15:44:54 +0200
Subject: [PATCH 088/788] Python: Move `ReflectedXss` to new dataflow API
---
.../security/dataflow/ReflectedXssQuery.qll | 15 ++++++++++++++-
python/ql/src/Security/CWE-079/ReflectedXss.ql | 6 +++---
2 files changed, 17 insertions(+), 4 deletions(-)
diff --git a/python/ql/lib/semmle/python/security/dataflow/ReflectedXssQuery.qll b/python/ql/lib/semmle/python/security/dataflow/ReflectedXssQuery.qll
index d150c80ffb1..d136c9d16b8 100644
--- a/python/ql/lib/semmle/python/security/dataflow/ReflectedXssQuery.qll
+++ b/python/ql/lib/semmle/python/security/dataflow/ReflectedXssQuery.qll
@@ -12,9 +12,11 @@ import semmle.python.dataflow.new.TaintTracking
import ReflectedXSSCustomizations::ReflectedXss
/**
+ * DEPRECATED: Use `ReflectedXssFlow` module instead.
+ *
* A taint-tracking configuration for detecting "reflected server-side cross-site scripting" vulnerabilities.
*/
-class Configuration extends TaintTracking::Configuration {
+deprecated class Configuration extends TaintTracking::Configuration {
Configuration() { this = "ReflectedXSS" }
override predicate isSource(DataFlow::Node source) { source instanceof Source }
@@ -27,3 +29,14 @@ class Configuration extends TaintTracking::Configuration {
guard instanceof SanitizerGuard
}
}
+
+private module ReflectedXssConfig 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 "reflected server-side cross-site scripting" vulnerabilities. */
+module ReflectedXssFlow = TaintTracking::Global;
diff --git a/python/ql/src/Security/CWE-079/ReflectedXss.ql b/python/ql/src/Security/CWE-079/ReflectedXss.ql
index 1189e35be67..11ebad00e37 100644
--- a/python/ql/src/Security/CWE-079/ReflectedXss.ql
+++ b/python/ql/src/Security/CWE-079/ReflectedXss.ql
@@ -15,9 +15,9 @@
import python
import semmle.python.security.dataflow.ReflectedXssQuery
-import DataFlow::PathGraph
+import ReflectedXssFlow::PathGraph
-from Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink
-where config.hasFlowPath(source, sink)
+from ReflectedXssFlow::PathNode source, ReflectedXssFlow::PathNode sink
+where ReflectedXssFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "Cross-site scripting vulnerability due to a $@.",
source.getNode(), "user-provided value"
From 05573904a5584e7da57eb9a963249bce736f8b4f Mon Sep 17 00:00:00 2001
From: Rasmus Wriedt Larsen
Date: Fri, 25 Aug 2023 16:03:53 +0200
Subject: [PATCH 089/788] Python: Move `LdapInjection` to new dataflow API
We could have switched to a stateful config, but I tried to keep changes
as straight forward as possible.
---
.../security/dataflow/LdapInjectionQuery.qll | 35 +++++++++++++++++--
.../ql/src/Security/CWE-090/LdapInjection.ql | 8 ++---
2 files changed, 37 insertions(+), 6 deletions(-)
diff --git a/python/ql/lib/semmle/python/security/dataflow/LdapInjectionQuery.qll b/python/ql/lib/semmle/python/security/dataflow/LdapInjectionQuery.qll
index aa13a8ee6a9..1ebead95418 100644
--- a/python/ql/lib/semmle/python/security/dataflow/LdapInjectionQuery.qll
+++ b/python/ql/lib/semmle/python/security/dataflow/LdapInjectionQuery.qll
@@ -14,10 +14,12 @@ import semmle.python.dataflow.new.RemoteFlowSources
import LdapInjectionCustomizations::LdapInjection
/**
+ * DEPRECATED: Use `LdapInjectionDnFlow` module instead.
+ *
* A taint-tracking configuration for detecting LDAP injection vulnerabilities
* via the distinguished name (DN) parameter of an LDAP search.
*/
-class DnConfiguration extends TaintTracking::Configuration {
+deprecated class DnConfiguration extends TaintTracking::Configuration {
DnConfiguration() { this = "LdapDnInjection" }
override predicate isSource(DataFlow::Node source) { source instanceof Source }
@@ -31,11 +33,24 @@ class DnConfiguration extends TaintTracking::Configuration {
}
}
+private module LdapInjectionDnConfig implements DataFlow::ConfigSig {
+ predicate isSource(DataFlow::Node source) { source instanceof Source }
+
+ predicate isSink(DataFlow::Node sink) { sink instanceof DnSink }
+
+ predicate isBarrier(DataFlow::Node node) { node instanceof DnSanitizer }
+}
+
+/** Global taint-tracking for detecting "LDAP injection via the distinguished name (DN) parameter" vulnerabilities. */
+module LdapInjectionDnFlow = TaintTracking::Global;
+
/**
+ * DEPRECATED: Use `LdapInjectionFilterFlow` module instead.
+ *
* A taint-tracking configuration for detecting LDAP injection vulnerabilities
* via the filter parameter of an LDAP search.
*/
-class FilterConfiguration extends TaintTracking::Configuration {
+deprecated class FilterConfiguration extends TaintTracking::Configuration {
FilterConfiguration() { this = "LdapFilterInjection" }
override predicate isSource(DataFlow::Node source) { source instanceof Source }
@@ -48,3 +63,19 @@ class FilterConfiguration extends TaintTracking::Configuration {
guard instanceof FilterSanitizerGuard
}
}
+
+private module LdapInjectionFilterConfig implements DataFlow::ConfigSig {
+ predicate isSource(DataFlow::Node source) { source instanceof Source }
+
+ predicate isSink(DataFlow::Node sink) { sink instanceof FilterSink }
+
+ predicate isBarrier(DataFlow::Node node) { node instanceof FilterSanitizer }
+}
+
+/** Global taint-tracking for detecting "LDAP injection via the filter parameter" vulnerabilities. */
+module LdapInjectionFilterFlow = TaintTracking::Global;
+
+/** Global taint-tracking for detecting "LDAP injection" vulnerabilities. */
+module LdapInjectionFlow =
+ DataFlow::MergePathGraph;
diff --git a/python/ql/src/Security/CWE-090/LdapInjection.ql b/python/ql/src/Security/CWE-090/LdapInjection.ql
index efcf52eba41..f4943f8a8dc 100644
--- a/python/ql/src/Security/CWE-090/LdapInjection.ql
+++ b/python/ql/src/Security/CWE-090/LdapInjection.ql
@@ -14,14 +14,14 @@
// Determine precision above
import python
import semmle.python.security.dataflow.LdapInjectionQuery
-import DataFlow::PathGraph
+import LdapInjectionFlow::PathGraph
-from DataFlow::PathNode source, DataFlow::PathNode sink, string parameterName
+from LdapInjectionFlow::PathNode source, LdapInjectionFlow::PathNode sink, string parameterName
where
- any(DnConfiguration dnConfig).hasFlowPath(source, sink) and
+ LdapInjectionDnFlow::flowPath(source.asPathNode1(), sink.asPathNode1()) and
parameterName = "DN"
or
- any(FilterConfiguration filterConfig).hasFlowPath(source, sink) and
+ LdapInjectionFilterFlow::flowPath(source.asPathNode2(), sink.asPathNode2()) and
parameterName = "filter"
select sink.getNode(), source, sink,
"LDAP query parameter (" + parameterName + ") depends on a $@.", source.getNode(),
From 88cf9c99b0d34aa5b25bc9d4956e07f67be835f9 Mon Sep 17 00:00:00 2001
From: Rasmus Wriedt Larsen
Date: Fri, 25 Aug 2023 16:05:10 +0200
Subject: [PATCH 090/788] Python: Move `CodeInjection` to new dataflow API
---
.../security/dataflow/CodeInjectionQuery.qll | 15 ++++++++++++++-
python/ql/src/Security/CWE-094/CodeInjection.ql | 6 +++---
2 files changed, 17 insertions(+), 4 deletions(-)
diff --git a/python/ql/lib/semmle/python/security/dataflow/CodeInjectionQuery.qll b/python/ql/lib/semmle/python/security/dataflow/CodeInjectionQuery.qll
index a318ae60aa8..3cdb72c383a 100644
--- a/python/ql/lib/semmle/python/security/dataflow/CodeInjectionQuery.qll
+++ b/python/ql/lib/semmle/python/security/dataflow/CodeInjectionQuery.qll
@@ -12,9 +12,11 @@ import semmle.python.dataflow.new.TaintTracking
import CodeInjectionCustomizations::CodeInjection
/**
+ * DEPRECATED: Use `CodeInjectionFlow` module instead.
+ *
* A taint-tracking configuration for detecting "code injection" vulnerabilities.
*/
-class Configuration extends TaintTracking::Configuration {
+deprecated class Configuration extends TaintTracking::Configuration {
Configuration() { this = "CodeInjection" }
override predicate isSource(DataFlow::Node source) { source instanceof Source }
@@ -27,3 +29,14 @@ class Configuration extends TaintTracking::Configuration {
guard instanceof SanitizerGuard
}
}
+
+private module CodeInjectionConfig 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 "code injection" vulnerabilities. */
+module CodeInjectionFlow = TaintTracking::Global;
diff --git a/python/ql/src/Security/CWE-094/CodeInjection.ql b/python/ql/src/Security/CWE-094/CodeInjection.ql
index 5e5c06b68b7..d0683c7ffca 100644
--- a/python/ql/src/Security/CWE-094/CodeInjection.ql
+++ b/python/ql/src/Security/CWE-094/CodeInjection.ql
@@ -16,9 +16,9 @@
import python
import semmle.python.security.dataflow.CodeInjectionQuery
-import DataFlow::PathGraph
+import CodeInjectionFlow::PathGraph
-from Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink
-where config.hasFlowPath(source, sink)
+from CodeInjectionFlow::PathNode source, CodeInjectionFlow::PathNode sink
+where CodeInjectionFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "This code execution depends on a $@.", source.getNode(),
"user-provided value"
From f75e65c67d69fefeb5ca962aa52d38b961d854b7 Mon Sep 17 00:00:00 2001
From: Rasmus Wriedt Larsen
Date: Fri, 25 Aug 2023 16:06:08 +0200
Subject: [PATCH 091/788] Python: Move `LogInjection` to new dataflow API
---
.../security/dataflow/LogInjectionQuery.qll | 17 +++++++++++++++--
python/ql/src/Security/CWE-117/LogInjection.ql | 6 +++---
2 files changed, 18 insertions(+), 5 deletions(-)
diff --git a/python/ql/lib/semmle/python/security/dataflow/LogInjectionQuery.qll b/python/ql/lib/semmle/python/security/dataflow/LogInjectionQuery.qll
index 4679c2c154b..8f91c6e85ee 100644
--- a/python/ql/lib/semmle/python/security/dataflow/LogInjectionQuery.qll
+++ b/python/ql/lib/semmle/python/security/dataflow/LogInjectionQuery.qll
@@ -1,5 +1,5 @@
/**
- * Provides a taint-tracking configuration for tracking untrusted user input used in log entries.
+ * Provides a taint-tracking configuration for tracking "log injection" vulnerabilities.
*
* Note, for performance reasons: only import this file if
* `LogInjection::Configuration` is needed, otherwise
@@ -12,9 +12,11 @@ import semmle.python.dataflow.new.TaintTracking
import LogInjectionCustomizations::LogInjection
/**
+ * DEPRECATED: Use `LogInjectionFlow` module instead.
+ *
* A taint-tracking configuration for tracking untrusted user input used in log entries.
*/
-class Configuration extends TaintTracking::Configuration {
+deprecated class Configuration extends TaintTracking::Configuration {
Configuration() { this = "LogInjection" }
override predicate isSource(DataFlow::Node source) { source instanceof Source }
@@ -27,3 +29,14 @@ class Configuration extends TaintTracking::Configuration {
guard instanceof SanitizerGuard
}
}
+
+private module LogInjectionConfig 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 "log injection" vulnerabilities. */
+module LogInjectionFlow = TaintTracking::Global;
diff --git a/python/ql/src/Security/CWE-117/LogInjection.ql b/python/ql/src/Security/CWE-117/LogInjection.ql
index 3c380321af2..f1b72faaccb 100644
--- a/python/ql/src/Security/CWE-117/LogInjection.ql
+++ b/python/ql/src/Security/CWE-117/LogInjection.ql
@@ -13,9 +13,9 @@
import python
import semmle.python.security.dataflow.LogInjectionQuery
-import DataFlow::PathGraph
+import LogInjectionFlow::PathGraph
-from Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink
-where config.hasFlowPath(source, sink)
+from LogInjectionFlow::PathNode source, LogInjectionFlow::PathNode sink
+where LogInjectionFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "This log entry depends on a $@.", source.getNode(),
"user-provided value"
From dcd96083e8d48a27e6bedf8f0a1e5ee30a3f9720 Mon Sep 17 00:00:00 2001
From: Rasmus Wriedt Larsen
Date: Fri, 25 Aug 2023 16:07:59 +0200
Subject: [PATCH 092/788] Python: Move `StackTraceExposure` to new dataflow API
---
.../dataflow/StackTraceExposureQuery.qll | 24 ++++++++++++++++++-
.../Security/CWE-209/StackTraceExposure.ql | 6 ++---
.../StackTraceExposure.expected | 4 +++-
3 files changed, 29 insertions(+), 5 deletions(-)
diff --git a/python/ql/lib/semmle/python/security/dataflow/StackTraceExposureQuery.qll b/python/ql/lib/semmle/python/security/dataflow/StackTraceExposureQuery.qll
index 3975985fce1..22404903c48 100644
--- a/python/ql/lib/semmle/python/security/dataflow/StackTraceExposureQuery.qll
+++ b/python/ql/lib/semmle/python/security/dataflow/StackTraceExposureQuery.qll
@@ -12,9 +12,11 @@ import semmle.python.dataflow.new.TaintTracking
import StackTraceExposureCustomizations::StackTraceExposure
/**
+ * DEPRECATED: Use `StackTraceExposureFlow` module instead.
+ *
* A taint-tracking configuration for detecting "stack trace exposure" vulnerabilities.
*/
-class Configuration extends TaintTracking::Configuration {
+deprecated class Configuration extends TaintTracking::Configuration {
Configuration() { this = "StackTraceExposure" }
override predicate isSource(DataFlow::Node source) { source instanceof Source }
@@ -36,3 +38,23 @@ class Configuration extends TaintTracking::Configuration {
)
}
}
+
+private module StackTraceExposureConfig 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 }
+
+ // A stack trace is accessible as the `__traceback__` attribute of a caught exception.
+ // see https://docs.python.org/3/reference/datamodel.html#traceback-objects
+ predicate isAdditionalFlowStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
+ exists(DataFlow::AttrRead attr | attr.getAttributeName() = "__traceback__" |
+ nodeFrom = attr.getObject() and
+ nodeTo = attr
+ )
+ }
+}
+
+/** Global taint-tracking for detecting "stack trace exposure" vulnerabilities. */
+module StackTraceExposureFlow = TaintTracking::Global;
diff --git a/python/ql/src/Security/CWE-209/StackTraceExposure.ql b/python/ql/src/Security/CWE-209/StackTraceExposure.ql
index 7b8cf74c597..1feed997e25 100644
--- a/python/ql/src/Security/CWE-209/StackTraceExposure.ql
+++ b/python/ql/src/Security/CWE-209/StackTraceExposure.ql
@@ -15,10 +15,10 @@
import python
import semmle.python.security.dataflow.StackTraceExposureQuery
-import DataFlow::PathGraph
+import StackTraceExposureFlow::PathGraph
-from Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink
-where config.hasFlowPath(source, sink)
+from StackTraceExposureFlow::PathNode source, StackTraceExposureFlow::PathNode sink
+where StackTraceExposureFlow::flowPath(source, sink)
select sink.getNode(), source, sink,
"$@ flows to this location and may be exposed to an external user.", source.getNode(),
"Stack trace information"
diff --git a/python/ql/test/query-tests/Security/CWE-209-StackTraceExposure/StackTraceExposure.expected b/python/ql/test/query-tests/Security/CWE-209-StackTraceExposure/StackTraceExposure.expected
index 5cc3f3eef6d..90b58f8e319 100644
--- a/python/ql/test/query-tests/Security/CWE-209-StackTraceExposure/StackTraceExposure.expected
+++ b/python/ql/test/query-tests/Security/CWE-209-StackTraceExposure/StackTraceExposure.expected
@@ -1,6 +1,7 @@
edges
| test.py:23:25:23:25 | SSA variable e | test.py:24:16:24:16 | ControlFlowNode for e |
-| test.py:31:25:31:25 | SSA variable e | test.py:32:16:32:30 | ControlFlowNode for Attribute |
+| test.py:31:25:31:25 | SSA variable e | test.py:32:16:32:16 | ControlFlowNode for e |
+| test.py:32:16:32:16 | ControlFlowNode for e | test.py:32:16:32:30 | ControlFlowNode for Attribute |
| test.py:49:9:49:11 | SSA variable err | test.py:50:29:50:31 | ControlFlowNode for err |
| test.py:49:15:49:36 | ControlFlowNode for Attribute() | test.py:49:9:49:11 | SSA variable err |
| test.py:50:29:50:31 | ControlFlowNode for err | test.py:50:16:50:32 | ControlFlowNode for format_error() |
@@ -12,6 +13,7 @@ nodes
| test.py:23:25:23:25 | SSA variable e | semmle.label | SSA variable e |
| test.py:24:16:24:16 | ControlFlowNode for e | semmle.label | ControlFlowNode for e |
| test.py:31:25:31:25 | SSA variable e | semmle.label | SSA variable e |
+| test.py:32:16:32:16 | ControlFlowNode for e | semmle.label | ControlFlowNode for e |
| test.py:32:16:32:30 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| test.py:49:9:49:11 | SSA variable err | semmle.label | SSA variable err |
| test.py:49:15:49:36 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
From cca78f31ff032087f72e4181d896312430f177d3 Mon Sep 17 00:00:00 2001
From: Rasmus Wriedt Larsen
Date: Fri, 25 Aug 2023 16:10:26 +0200
Subject: [PATCH 093/788] Python: Move `PamAuthorization` to new dataflow API
---
.../dataflow/PamAuthorizationQuery.qll | 29 ++++++++++++++++++-
.../src/Security/CWE-285/PamAuthorization.ql | 6 ++--
.../PamAuthorization.expected | 8 ++++-
3 files changed, 38 insertions(+), 5 deletions(-)
diff --git a/python/ql/lib/semmle/python/security/dataflow/PamAuthorizationQuery.qll b/python/ql/lib/semmle/python/security/dataflow/PamAuthorizationQuery.qll
index 18dc29a4a71..4b150299b31 100644
--- a/python/ql/lib/semmle/python/security/dataflow/PamAuthorizationQuery.qll
+++ b/python/ql/lib/semmle/python/security/dataflow/PamAuthorizationQuery.qll
@@ -12,9 +12,11 @@ import semmle.python.dataflow.new.TaintTracking
import PamAuthorizationCustomizations::PamAuthorizationCustomizations
/**
+ * DEPRECATED: Use `PamAuthorizationFlow` module instead.
+ *
* A taint-tracking configuration for detecting "PAM Authorization" vulnerabilities.
*/
-class Configuration extends TaintTracking::Configuration {
+deprecated class Configuration extends TaintTracking::Configuration {
Configuration() { this = "PamAuthorization" }
override predicate isSource(DataFlow::Node node) { node instanceof Source }
@@ -37,3 +39,28 @@ class Configuration extends TaintTracking::Configuration {
exists(VulnPamAuthCall c | c.getArg(0) = node1 | node2 = c)
}
}
+
+private module PamAuthorizationConfig implements DataFlow::ConfigSig {
+ predicate isSource(DataFlow::Node source) { source instanceof Source }
+
+ predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
+
+ predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
+ // Models flow from a remotely supplied username field to a PAM `handle`.
+ // `retval = pam_start(service, username, byref(conv), byref(handle))`
+ exists(API::CallNode pamStart, DataFlow::Node handle, API::CallNode pointer |
+ pointer = API::moduleImport("ctypes").getMember(["pointer", "byref"]).getACall() and
+ pamStart = libPam().getMember("pam_start").getACall() and
+ pointer = pamStart.getArg(3) and
+ handle = pointer.getArg(0) and
+ pamStart.getArg(1) = node1 and
+ handle = node2
+ )
+ or
+ // Flow from handle to the authenticate call in the final step
+ exists(VulnPamAuthCall c | c.getArg(0) = node1 | node2 = c)
+ }
+}
+
+/** Global taint-tracking for detecting "PAM Authorization" vulnerabilities. */
+module PamAuthorizationFlow = TaintTracking::Global;
diff --git a/python/ql/src/Security/CWE-285/PamAuthorization.ql b/python/ql/src/Security/CWE-285/PamAuthorization.ql
index 43cbc33917a..1da0b8c9b10 100644
--- a/python/ql/src/Security/CWE-285/PamAuthorization.ql
+++ b/python/ql/src/Security/CWE-285/PamAuthorization.ql
@@ -11,12 +11,12 @@
*/
import python
-import DataFlow::PathGraph
+import PamAuthorizationFlow::PathGraph
import semmle.python.ApiGraphs
import semmle.python.security.dataflow.PamAuthorizationQuery
-from Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink
-where config.hasFlowPath(source, sink)
+from PamAuthorizationFlow::PathNode source, PamAuthorizationFlow::PathNode sink
+where PamAuthorizationFlow::flowPath(source, sink)
select sink.getNode(), source, sink,
"This PAM authentication depends on a $@, and 'pam_acct_mgmt' is not called afterwards.",
source.getNode(), "user-provided value"
diff --git a/python/ql/test/query-tests/Security/CWE-285-PamAuthorization/PamAuthorization.expected b/python/ql/test/query-tests/Security/CWE-285-PamAuthorization/PamAuthorization.expected
index f259cfab561..9379464e1c1 100644
--- a/python/ql/test/query-tests/Security/CWE-285-PamAuthorization/PamAuthorization.expected
+++ b/python/ql/test/query-tests/Security/CWE-285-PamAuthorization/PamAuthorization.expected
@@ -1,10 +1,13 @@
edges
| pam_test.py:4:26:4:32 | ControlFlowNode for ImportMember | pam_test.py:4:26:4:32 | GSSA Variable request |
| pam_test.py:4:26:4:32 | GSSA Variable request | pam_test.py:71:16:71:22 | ControlFlowNode for request |
-| pam_test.py:71:5:71:12 | SSA variable username | pam_test.py:76:14:76:40 | ControlFlowNode for pam_authenticate() |
+| pam_test.py:71:5:71:12 | SSA variable username | pam_test.py:74:33:74:40 | ControlFlowNode for username |
| pam_test.py:71:16:71:22 | ControlFlowNode for request | pam_test.py:71:16:71:27 | ControlFlowNode for Attribute |
| pam_test.py:71:16:71:27 | ControlFlowNode for Attribute | pam_test.py:71:16:71:47 | ControlFlowNode for Attribute() |
| pam_test.py:71:16:71:47 | ControlFlowNode for Attribute() | pam_test.py:71:5:71:12 | SSA variable username |
+| pam_test.py:74:33:74:40 | ControlFlowNode for username | pam_test.py:74:62:74:67 | ControlFlowNode for handle |
+| pam_test.py:74:62:74:67 | ControlFlowNode for handle | pam_test.py:76:31:76:36 | ControlFlowNode for handle |
+| pam_test.py:76:31:76:36 | ControlFlowNode for handle | pam_test.py:76:14:76:40 | ControlFlowNode for pam_authenticate() |
nodes
| pam_test.py:4:26:4:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember |
| pam_test.py:4:26:4:32 | GSSA Variable request | semmle.label | GSSA Variable request |
@@ -12,7 +15,10 @@ nodes
| pam_test.py:71:16:71:22 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| pam_test.py:71:16:71:27 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| pam_test.py:71:16:71:47 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
+| pam_test.py:74:33:74:40 | ControlFlowNode for username | semmle.label | ControlFlowNode for username |
+| pam_test.py:74:62:74:67 | ControlFlowNode for handle | semmle.label | ControlFlowNode for handle |
| pam_test.py:76:14:76:40 | ControlFlowNode for pam_authenticate() | semmle.label | ControlFlowNode for pam_authenticate() |
+| pam_test.py:76:31:76:36 | ControlFlowNode for handle | semmle.label | ControlFlowNode for handle |
subpaths
#select
| pam_test.py:76:14:76:40 | ControlFlowNode for pam_authenticate() | pam_test.py:4:26:4:32 | ControlFlowNode for ImportMember | pam_test.py:76:14:76:40 | ControlFlowNode for pam_authenticate() | This PAM authentication depends on a $@, and 'pam_acct_mgmt' is not called afterwards. | pam_test.py:4:26:4:32 | ControlFlowNode for ImportMember | user-provided value |
From 70095446b66704f7ed35d96055d5dd0be05a941d Mon Sep 17 00:00:00 2001
From: Rasmus Wriedt Larsen
Date: Fri, 25 Aug 2023 16:12:01 +0200
Subject: [PATCH 094/788] Python: Move `CleartextLogging` to new dataflow API
---
.../security/dataflow/CleartextLoggingQuery.qll | 15 ++++++++++++++-
.../ql/src/Security/CWE-312/CleartextLogging.ql | 7 ++++---
2 files changed, 18 insertions(+), 4 deletions(-)
diff --git a/python/ql/lib/semmle/python/security/dataflow/CleartextLoggingQuery.qll b/python/ql/lib/semmle/python/security/dataflow/CleartextLoggingQuery.qll
index 7479c24fc53..0b0cb046820 100644
--- a/python/ql/lib/semmle/python/security/dataflow/CleartextLoggingQuery.qll
+++ b/python/ql/lib/semmle/python/security/dataflow/CleartextLoggingQuery.qll
@@ -16,9 +16,11 @@ private import semmle.python.dataflow.new.SensitiveDataSources
import CleartextLoggingCustomizations::CleartextLogging
/**
+ * DEPRECATED: Use `CleartextLoggingFlow` module instead.
+ *
* A taint-tracking configuration for detecting "Clear-text logging of sensitive information".
*/
-class Configuration extends TaintTracking::Configuration {
+deprecated class Configuration extends TaintTracking::Configuration {
Configuration() { this = "CleartextLogging" }
override predicate isSource(DataFlow::Node source) { source instanceof Source }
@@ -31,3 +33,14 @@ class Configuration extends TaintTracking::Configuration {
node instanceof Sanitizer
}
}
+
+private module CleartextLoggingConfig 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 "Clear-text logging of sensitive information" vulnerabilities. */
+module CleartextLoggingFlow = TaintTracking::Global;
diff --git a/python/ql/src/Security/CWE-312/CleartextLogging.ql b/python/ql/src/Security/CWE-312/CleartextLogging.ql
index 0c2591eaec4..500a2b5f9b7 100644
--- a/python/ql/src/Security/CWE-312/CleartextLogging.ql
+++ b/python/ql/src/Security/CWE-312/CleartextLogging.ql
@@ -15,12 +15,13 @@
import python
private import semmle.python.dataflow.new.DataFlow
-import DataFlow::PathGraph
+import CleartextLoggingFlow::PathGraph
import semmle.python.security.dataflow.CleartextLoggingQuery
-from Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink, string classification
+from
+ CleartextLoggingFlow::PathNode source, CleartextLoggingFlow::PathNode sink, string classification
where
- config.hasFlowPath(source, sink) and
+ CleartextLoggingFlow::flowPath(source, sink) and
classification = source.getNode().(Source).getClassification()
select sink.getNode(), source, sink, "This expression logs $@ as clear text.", source.getNode(),
"sensitive data (" + classification + ")"
From 9d6b96dfd286901ef7c4452586345badb5ba4a64 Mon Sep 17 00:00:00 2001
From: Rasmus Wriedt Larsen
Date: Fri, 25 Aug 2023 16:15:03 +0200
Subject: [PATCH 095/788] Python: Move `CleartextStorage` to new dataflow API
---
.../security/dataflow/CleartextStorageQuery.qll | 15 ++++++++++++++-
.../ql/src/Security/CWE-312/CleartextStorage.ql | 7 ++++---
2 files changed, 18 insertions(+), 4 deletions(-)
diff --git a/python/ql/lib/semmle/python/security/dataflow/CleartextStorageQuery.qll b/python/ql/lib/semmle/python/security/dataflow/CleartextStorageQuery.qll
index e5320c76d34..ef9c8c13b56 100644
--- a/python/ql/lib/semmle/python/security/dataflow/CleartextStorageQuery.qll
+++ b/python/ql/lib/semmle/python/security/dataflow/CleartextStorageQuery.qll
@@ -16,9 +16,11 @@ private import semmle.python.dataflow.new.SensitiveDataSources
import CleartextStorageCustomizations::CleartextStorage
/**
+ * DEPRECATED: Use `CleartextStorageFlow` module instead.
+ *
* A taint-tracking configuration for detecting "Clear-text storage of sensitive information".
*/
-class Configuration extends TaintTracking::Configuration {
+deprecated class Configuration extends TaintTracking::Configuration {
Configuration() { this = "CleartextStorage" }
override predicate isSource(DataFlow::Node source) { source instanceof Source }
@@ -31,3 +33,14 @@ class Configuration extends TaintTracking::Configuration {
node instanceof Sanitizer
}
}
+
+private module CleartextStorageConfig 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 "Clear-text storage of sensitive information" vulnerabilities. */
+module CleartextStorageFlow = TaintTracking::Global;
diff --git a/python/ql/src/Security/CWE-312/CleartextStorage.ql b/python/ql/src/Security/CWE-312/CleartextStorage.ql
index 9a8d5de3331..f83097d6e0b 100644
--- a/python/ql/src/Security/CWE-312/CleartextStorage.ql
+++ b/python/ql/src/Security/CWE-312/CleartextStorage.ql
@@ -15,12 +15,13 @@
import python
private import semmle.python.dataflow.new.DataFlow
-import DataFlow::PathGraph
+import CleartextStorageFlow::PathGraph
import semmle.python.security.dataflow.CleartextStorageQuery
-from Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink, string classification
+from
+ CleartextStorageFlow::PathNode source, CleartextStorageFlow::PathNode sink, string classification
where
- config.hasFlowPath(source, sink) and
+ CleartextStorageFlow::flowPath(source, sink) and
classification = source.getNode().(Source).getClassification()
select sink.getNode(), source, sink, "This expression stores $@ as clear text.", source.getNode(),
"sensitive data (" + classification + ")"
From dd074173d2d3f60b68f634f8f128b5487671c711 Mon Sep 17 00:00:00 2001
From: Rasmus Wriedt Larsen
Date: Fri, 25 Aug 2023 16:25:45 +0200
Subject: [PATCH 096/788] Python: Move `WeakSensitiveDataHashing` to new
dataflow API
I adopted helper predicates to do the "heavy" lifting of .asPathNode1(), maybe I like this approach better... let me know what you think :blush:
---
.../WeakSensitiveDataHashingQuery.qll | 68 ++++++++++++++++++-
.../CWE-327/WeakSensitiveDataHashing.ql | 42 ++++++------
.../WeakSensitiveDataHashing.expected | 12 ++--
3 files changed, 91 insertions(+), 31 deletions(-)
diff --git a/python/ql/lib/semmle/python/security/dataflow/WeakSensitiveDataHashingQuery.qll b/python/ql/lib/semmle/python/security/dataflow/WeakSensitiveDataHashingQuery.qll
index f7aec512772..9e2803b3369 100644
--- a/python/ql/lib/semmle/python/security/dataflow/WeakSensitiveDataHashingQuery.qll
+++ b/python/ql/lib/semmle/python/security/dataflow/WeakSensitiveDataHashingQuery.qll
@@ -24,10 +24,12 @@ module NormalHashFunction {
import WeakSensitiveDataHashingCustomizations::NormalHashFunction
/**
+ * DEPRECATED: Use `Flow` module instead.
+ *
* A taint-tracking configuration for detecting use of a broken or weak
* cryptographic hashing algorithm on sensitive data.
*/
- class Configuration extends TaintTracking::Configuration {
+ deprecated class Configuration extends TaintTracking::Configuration {
Configuration() { this = "NormalHashFunction" }
override predicate isSource(DataFlow::Node source) { source instanceof Source }
@@ -44,6 +46,21 @@ module NormalHashFunction {
sensitiveDataExtraStepForCalls(node1, node2)
}
}
+
+ 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 }
+
+ predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
+ sensitiveDataExtraStepForCalls(node1, node2)
+ }
+ }
+
+ /** Global taint-tracking for detecting "use of a broken or weak cryptographic hashing algorithm on sensitive data" vulnerabilities. */
+ module Flow = TaintTracking::Global;
}
/**
@@ -57,13 +74,15 @@ module ComputationallyExpensiveHashFunction {
import WeakSensitiveDataHashingCustomizations::ComputationallyExpensiveHashFunction
/**
+ * DEPRECATED: Use `Flow` module instead.
+ *
* 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).
*/
- class Configuration extends TaintTracking::Configuration {
+ deprecated class Configuration extends TaintTracking::Configuration {
Configuration() { this = "ComputationallyExpensiveHashFunction" }
override predicate isSource(DataFlow::Node source) { source instanceof Source }
@@ -80,4 +99,49 @@ module ComputationallyExpensiveHashFunction {
sensitiveDataExtraStepForCalls(node1, node2)
}
}
+
+ /**
+ * 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 }
+
+ predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
+ sensitiveDataExtraStepForCalls(node1, node2)
+ }
+ }
+
+ /** 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/python/ql/src/Security/CWE-327/WeakSensitiveDataHashing.ql b/python/ql/src/Security/CWE-327/WeakSensitiveDataHashing.ql
index ce46a21fe71..ef72ae1fdbc 100644
--- a/python/ql/src/Security/CWE-327/WeakSensitiveDataHashing.ql
+++ b/python/ql/src/Security/CWE-327/WeakSensitiveDataHashing.ql
@@ -16,33 +16,29 @@ import python
import semmle.python.security.dataflow.WeakSensitiveDataHashingQuery
import semmle.python.dataflow.new.DataFlow
import semmle.python.dataflow.new.TaintTracking
-import DataFlow::PathGraph
+import WeakSensitiveDataHashingFlow::PathGraph
from
- DataFlow::PathNode source, DataFlow::PathNode sink, string ending, string algorithmName,
- string classification
+ WeakSensitiveDataHashingFlow::PathNode source, WeakSensitiveDataHashingFlow::PathNode sink,
+ string ending, string algorithmName, string classification
where
- exists(NormalHashFunction::Configuration config |
- config.hasFlowPath(source, sink) and
- algorithmName = sink.getNode().(NormalHashFunction::Sink).getAlgorithmName() and
- classification = source.getNode().(NormalHashFunction::Source).getClassification() and
- ending = "."
- )
+ normalHashFunctionFlowPath(source, sink) and
+ algorithmName = sink.getNode().(NormalHashFunction::Sink).getAlgorithmName() and
+ classification = source.getNode().(NormalHashFunction::Source).getClassification() and
+ ending = "."
or
- exists(ComputationallyExpensiveHashFunction::Configuration config |
- config.hasFlowPath(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."
- )
+ 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,
diff --git a/python/ql/test/query-tests/Security/CWE-327-WeakSensitiveDataHashing/WeakSensitiveDataHashing.expected b/python/ql/test/query-tests/Security/CWE-327-WeakSensitiveDataHashing/WeakSensitiveDataHashing.expected
index 30a04916e7f..6be594dae63 100644
--- a/python/ql/test/query-tests/Security/CWE-327-WeakSensitiveDataHashing/WeakSensitiveDataHashing.expected
+++ b/python/ql/test/query-tests/Security/CWE-327-WeakSensitiveDataHashing/WeakSensitiveDataHashing.expected
@@ -5,13 +5,13 @@ edges
| test_cryptodome.py:2:37:2:51 | ControlFlowNode for ImportMember | test_cryptodome.py:2:37:2:51 | GSSA Variable get_certificate |
| test_cryptodome.py:2:37:2:51 | GSSA Variable get_certificate | test_cryptodome.py:6:17:6:31 | ControlFlowNode for get_certificate |
| test_cryptodome.py:6:5:6:13 | SSA variable dangerous | test_cryptodome.py:8:19:8:27 | ControlFlowNode for dangerous |
-| test_cryptodome.py:6:17:6:31 | ControlFlowNode for get_certificate | test_cryptodome.py:6:5:6:13 | SSA variable dangerous |
+| test_cryptodome.py:6:17:6:31 | ControlFlowNode for get_certificate | test_cryptodome.py:6:17:6:33 | ControlFlowNode for get_certificate() |
| test_cryptodome.py:6:17:6:33 | ControlFlowNode for get_certificate() | test_cryptodome.py:6:5:6:13 | SSA variable dangerous |
| test_cryptodome.py:13:5:13:13 | SSA variable dangerous | test_cryptodome.py:15:19:15:27 | ControlFlowNode for dangerous |
-| test_cryptodome.py:13:17:13:28 | ControlFlowNode for get_password | test_cryptodome.py:13:5:13:13 | SSA variable dangerous |
+| test_cryptodome.py:13:17:13:28 | ControlFlowNode for get_password | test_cryptodome.py:13:17:13:30 | ControlFlowNode for get_password() |
| test_cryptodome.py:13:17:13:30 | ControlFlowNode for get_password() | test_cryptodome.py:13:5:13:13 | SSA variable dangerous |
| test_cryptodome.py:20:5:20:13 | SSA variable dangerous | test_cryptodome.py:24:19:24:27 | ControlFlowNode for dangerous |
-| test_cryptodome.py:20:17:20:28 | ControlFlowNode for get_password | test_cryptodome.py:20:5:20:13 | SSA variable dangerous |
+| test_cryptodome.py:20:17:20:28 | ControlFlowNode for get_password | test_cryptodome.py:20:17:20:30 | ControlFlowNode for get_password() |
| test_cryptodome.py:20:17:20:30 | ControlFlowNode for get_password() | test_cryptodome.py:20:5:20:13 | SSA variable dangerous |
| test_cryptography.py:3:23:3:34 | ControlFlowNode for ImportMember | test_cryptography.py:3:23:3:34 | GSSA Variable get_password |
| test_cryptography.py:3:23:3:34 | GSSA Variable get_password | test_cryptography.py:15:17:15:28 | ControlFlowNode for get_password |
@@ -19,13 +19,13 @@ edges
| test_cryptography.py:3:37:3:51 | ControlFlowNode for ImportMember | test_cryptography.py:3:37:3:51 | GSSA Variable get_certificate |
| test_cryptography.py:3:37:3:51 | GSSA Variable get_certificate | test_cryptography.py:7:17:7:31 | ControlFlowNode for get_certificate |
| test_cryptography.py:7:5:7:13 | SSA variable dangerous | test_cryptography.py:9:19:9:27 | ControlFlowNode for dangerous |
-| test_cryptography.py:7:17:7:31 | ControlFlowNode for get_certificate | test_cryptography.py:7:5:7:13 | SSA variable dangerous |
+| test_cryptography.py:7:17:7:31 | ControlFlowNode for get_certificate | test_cryptography.py:7:17:7:33 | ControlFlowNode for get_certificate() |
| test_cryptography.py:7:17:7:33 | ControlFlowNode for get_certificate() | test_cryptography.py:7:5:7:13 | SSA variable dangerous |
| test_cryptography.py:15:5:15:13 | SSA variable dangerous | test_cryptography.py:17:19:17:27 | ControlFlowNode for dangerous |
-| test_cryptography.py:15:17:15:28 | ControlFlowNode for get_password | test_cryptography.py:15:5:15:13 | SSA variable dangerous |
+| test_cryptography.py:15:17:15:28 | ControlFlowNode for get_password | test_cryptography.py:15:17:15:30 | ControlFlowNode for get_password() |
| test_cryptography.py:15:17:15:30 | ControlFlowNode for get_password() | test_cryptography.py:15:5:15:13 | SSA variable dangerous |
| test_cryptography.py:23:5:23:13 | SSA variable dangerous | test_cryptography.py:27:19:27:27 | ControlFlowNode for dangerous |
-| test_cryptography.py:23:17:23:28 | ControlFlowNode for get_password | test_cryptography.py:23:5:23:13 | SSA variable dangerous |
+| test_cryptography.py:23:17:23:28 | ControlFlowNode for get_password | test_cryptography.py:23:17:23:30 | ControlFlowNode for get_password() |
| test_cryptography.py:23:17:23:30 | ControlFlowNode for get_password() | test_cryptography.py:23:5:23:13 | SSA variable dangerous |
nodes
| test_cryptodome.py:2:23:2:34 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember |
From 6f08e73dbc874d11228d22dfd10b587618203be3 Mon Sep 17 00:00:00 2001
From: Rasmus Wriedt Larsen
Date: Fri, 25 Aug 2023 16:27:19 +0200
Subject: [PATCH 097/788] Python: Move `UnsafeDeserialization` to new dataflow
API
---
.../dataflow/UnsafeDeserializationQuery.qll | 15 ++++++++++++++-
.../src/Security/CWE-502/UnsafeDeserialization.ql | 6 +++---
2 files changed, 17 insertions(+), 4 deletions(-)
diff --git a/python/ql/lib/semmle/python/security/dataflow/UnsafeDeserializationQuery.qll b/python/ql/lib/semmle/python/security/dataflow/UnsafeDeserializationQuery.qll
index 0a2046b8a4b..d9dfde62bcb 100644
--- a/python/ql/lib/semmle/python/security/dataflow/UnsafeDeserializationQuery.qll
+++ b/python/ql/lib/semmle/python/security/dataflow/UnsafeDeserializationQuery.qll
@@ -12,9 +12,11 @@ import semmle.python.dataflow.new.TaintTracking
import UnsafeDeserializationCustomizations::UnsafeDeserialization
/**
+ * DEPRECATED: Use `UnsafeDeserializationFlow` module instead.
+ *
* A taint-tracking configuration for detecting "code execution from deserialization" vulnerabilities.
*/
-class Configuration extends TaintTracking::Configuration {
+deprecated class Configuration extends TaintTracking::Configuration {
Configuration() { this = "UnsafeDeserialization" }
override predicate isSource(DataFlow::Node source) { source instanceof Source }
@@ -27,3 +29,14 @@ class Configuration extends TaintTracking::Configuration {
guard instanceof SanitizerGuard
}
}
+
+private module UnsafeDeserializationConfig 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 "code execution from deserialization" vulnerabilities. */
+module UnsafeDeserializationFlow = TaintTracking::Global;
diff --git a/python/ql/src/Security/CWE-502/UnsafeDeserialization.ql b/python/ql/src/Security/CWE-502/UnsafeDeserialization.ql
index a15838cdabd..395101de78f 100644
--- a/python/ql/src/Security/CWE-502/UnsafeDeserialization.ql
+++ b/python/ql/src/Security/CWE-502/UnsafeDeserialization.ql
@@ -14,9 +14,9 @@
import python
import semmle.python.security.dataflow.UnsafeDeserializationQuery
-import DataFlow::PathGraph
+import UnsafeDeserializationFlow::PathGraph
-from Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink
-where config.hasFlowPath(source, sink)
+from UnsafeDeserializationFlow::PathNode source, UnsafeDeserializationFlow::PathNode sink
+where UnsafeDeserializationFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "Unsafe deserialization depends on a $@.", source.getNode(),
"user-provided value"
From 4c76ca6127b3887e27759e2380e1275e18f4d801 Mon Sep 17 00:00:00 2001
From: Rasmus Wriedt Larsen
Date: Fri, 25 Aug 2023 16:27:55 +0200
Subject: [PATCH 098/788] Python: Move `UrlRedirect` to new dataflow API
---
.../python/security/dataflow/UrlRedirectQuery.qll | 15 ++++++++++++++-
python/ql/src/Security/CWE-601/UrlRedirect.ql | 6 +++---
2 files changed, 17 insertions(+), 4 deletions(-)
diff --git a/python/ql/lib/semmle/python/security/dataflow/UrlRedirectQuery.qll b/python/ql/lib/semmle/python/security/dataflow/UrlRedirectQuery.qll
index 599f08d133a..cb1adc21135 100644
--- a/python/ql/lib/semmle/python/security/dataflow/UrlRedirectQuery.qll
+++ b/python/ql/lib/semmle/python/security/dataflow/UrlRedirectQuery.qll
@@ -12,9 +12,11 @@ import semmle.python.dataflow.new.TaintTracking
import UrlRedirectCustomizations::UrlRedirect
/**
+ * DEPRECATED: Use `UrlRedirectFlow` module instead.
+ *
* A taint-tracking configuration for detecting "URL redirection" vulnerabilities.
*/
-class Configuration extends TaintTracking::Configuration {
+deprecated class Configuration extends TaintTracking::Configuration {
Configuration() { this = "UrlRedirect" }
override predicate isSource(DataFlow::Node source) { source instanceof Source }
@@ -27,3 +29,14 @@ class Configuration extends TaintTracking::Configuration {
guard instanceof SanitizerGuard
}
}
+
+private module UrlRedirectConfig 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 "URL redirection" vulnerabilities. */
+module UrlRedirectFlow = TaintTracking::Global;
diff --git a/python/ql/src/Security/CWE-601/UrlRedirect.ql b/python/ql/src/Security/CWE-601/UrlRedirect.ql
index fbe3f3349ce..813cb4a997a 100644
--- a/python/ql/src/Security/CWE-601/UrlRedirect.ql
+++ b/python/ql/src/Security/CWE-601/UrlRedirect.ql
@@ -14,9 +14,9 @@
import python
import semmle.python.security.dataflow.UrlRedirectQuery
-import DataFlow::PathGraph
+import UrlRedirectFlow::PathGraph
-from Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink
-where config.hasFlowPath(source, sink)
+from UrlRedirectFlow::PathNode source, UrlRedirectFlow::PathNode sink
+where UrlRedirectFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "Untrusted URL redirection depends on a $@.", source.getNode(),
"user-provided value"
From 60e45335dd420717ac7fe272f57a98ebfd94a830 Mon Sep 17 00:00:00 2001
From: Rasmus Wriedt Larsen
Date: Fri, 25 Aug 2023 16:29:01 +0200
Subject: [PATCH 099/788] Python: Move `Xxe` to new dataflow API
---
.../semmle/python/security/dataflow/XxeQuery.qll | 15 ++++++++++++++-
python/ql/src/Security/CWE-611/Xxe.ql | 6 +++---
2 files changed, 17 insertions(+), 4 deletions(-)
diff --git a/python/ql/lib/semmle/python/security/dataflow/XxeQuery.qll b/python/ql/lib/semmle/python/security/dataflow/XxeQuery.qll
index dd2409f2a3c..8d85d275f1e 100644
--- a/python/ql/lib/semmle/python/security/dataflow/XxeQuery.qll
+++ b/python/ql/lib/semmle/python/security/dataflow/XxeQuery.qll
@@ -12,9 +12,11 @@ import semmle.python.dataflow.new.TaintTracking
import XxeCustomizations::Xxe
/**
+ * DEPRECATED: Use `XxeFlow` module instead.
+ *
* A taint-tracking configuration for detecting "XML External Entity (XXE)" vulnerabilities.
*/
-class Configuration extends TaintTracking::Configuration {
+deprecated class Configuration extends TaintTracking::Configuration {
Configuration() { this = "Xxe" }
override predicate isSource(DataFlow::Node source) { source instanceof Source }
@@ -26,3 +28,14 @@ class Configuration extends TaintTracking::Configuration {
node instanceof Sanitizer
}
}
+
+private module XxeConfig 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 "XML External Entity (XXE)" vulnerabilities. */
+module XxeFlow = TaintTracking::Global;
diff --git a/python/ql/src/Security/CWE-611/Xxe.ql b/python/ql/src/Security/CWE-611/Xxe.ql
index b361f6ffcfb..948e0f8a5f9 100644
--- a/python/ql/src/Security/CWE-611/Xxe.ql
+++ b/python/ql/src/Security/CWE-611/Xxe.ql
@@ -14,10 +14,10 @@
import python
import semmle.python.security.dataflow.XxeQuery
-import DataFlow::PathGraph
+import XxeFlow::PathGraph
-from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
-where cfg.hasFlowPath(source, sink)
+from XxeFlow::PathNode source, XxeFlow::PathNode sink
+where XxeFlow::flowPath(source, sink)
select sink.getNode(), source, sink,
"XML parsing depends on a $@ without guarding against external entity expansion.",
source.getNode(), "user-provided value"
From 4c336990e52ac3bdcd9214b0a2ed84df812b6d99 Mon Sep 17 00:00:00 2001
From: Rasmus Wriedt Larsen
Date: Fri, 25 Aug 2023 16:30:00 +0200
Subject: [PATCH 100/788] Python: Move `XpathInjection` to new dataflow API
---
.../security/dataflow/XpathInjectionQuery.qll | 15 ++++++++++++++-
python/ql/src/Security/CWE-643/XpathInjection.ql | 6 +++---
2 files changed, 17 insertions(+), 4 deletions(-)
diff --git a/python/ql/lib/semmle/python/security/dataflow/XpathInjectionQuery.qll b/python/ql/lib/semmle/python/security/dataflow/XpathInjectionQuery.qll
index aa5a27c5392..34a34e49ba2 100644
--- a/python/ql/lib/semmle/python/security/dataflow/XpathInjectionQuery.qll
+++ b/python/ql/lib/semmle/python/security/dataflow/XpathInjectionQuery.qll
@@ -12,9 +12,11 @@ import semmle.python.dataflow.new.TaintTracking
import XpathInjectionCustomizations::XpathInjection
/**
+ * DEPRECATED: Use `XpathInjectionFlow` module instead.
+ *
* A taint-tracking configuration for detecting "Xpath Injection" vulnerabilities.
*/
-class Configuration extends TaintTracking::Configuration {
+deprecated class Configuration extends TaintTracking::Configuration {
Configuration() { this = "Xpath Injection" }
override predicate isSource(DataFlow::Node source) { source instanceof Source }
@@ -27,3 +29,14 @@ class Configuration extends TaintTracking::Configuration {
guard instanceof SanitizerGuard
}
}
+
+private module XpathInjectionConfig 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 "Xpath Injection" vulnerabilities. */
+module XpathInjectionFlow = TaintTracking::Global;
diff --git a/python/ql/src/Security/CWE-643/XpathInjection.ql b/python/ql/src/Security/CWE-643/XpathInjection.ql
index 07df47624e7..90d4bcbd2c3 100644
--- a/python/ql/src/Security/CWE-643/XpathInjection.ql
+++ b/python/ql/src/Security/CWE-643/XpathInjection.ql
@@ -13,9 +13,9 @@
import python
import semmle.python.security.dataflow.XpathInjectionQuery
-import DataFlow::PathGraph
+import XpathInjectionFlow::PathGraph
-from Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink
-where config.hasFlowPath(source, sink)
+from XpathInjectionFlow::PathNode source, XpathInjectionFlow::PathNode sink
+where XpathInjectionFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "XPath expression depends on a $@.", source.getNode(),
"user-provided value"
From c6caf83dfe0b9a86f032821909e9936626265343 Mon Sep 17 00:00:00 2001
From: Rasmus Wriedt Larsen
Date: Fri, 25 Aug 2023 16:30:40 +0200
Subject: [PATCH 101/788] Python: Move `PolynomialReDoS` to new dataflow API
---
.../security/dataflow/PolynomialReDoSQuery.qll | 15 ++++++++++++++-
python/ql/src/Security/CWE-730/PolynomialReDoS.ql | 6 +++---
2 files changed, 17 insertions(+), 4 deletions(-)
diff --git a/python/ql/lib/semmle/python/security/dataflow/PolynomialReDoSQuery.qll b/python/ql/lib/semmle/python/security/dataflow/PolynomialReDoSQuery.qll
index d9fd1e843e8..2279814e49e 100644
--- a/python/ql/lib/semmle/python/security/dataflow/PolynomialReDoSQuery.qll
+++ b/python/ql/lib/semmle/python/security/dataflow/PolynomialReDoSQuery.qll
@@ -12,9 +12,11 @@ import semmle.python.dataflow.new.TaintTracking
import PolynomialReDoSCustomizations::PolynomialReDoS
/**
+ * DEPRECATED: Use `PolynomialReDoSFlow` module instead.
+ *
* A taint-tracking configuration for detecting "polynomial regular expression denial of service (ReDoS)" vulnerabilities.
*/
-class Configuration extends TaintTracking::Configuration {
+deprecated class Configuration extends TaintTracking::Configuration {
Configuration() { this = "PolynomialReDoS" }
override predicate isSource(DataFlow::Node source) { source instanceof Source }
@@ -27,3 +29,14 @@ class Configuration extends TaintTracking::Configuration {
guard instanceof SanitizerGuard
}
}
+
+private module PolynomialReDoSConfig 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 "polynomial regular expression denial of service (ReDoS)" vulnerabilities. */
+module PolynomialReDoSFlow = TaintTracking::Global;
diff --git a/python/ql/src/Security/CWE-730/PolynomialReDoS.ql b/python/ql/src/Security/CWE-730/PolynomialReDoS.ql
index 1b315c651c3..b3b4a8cac92 100644
--- a/python/ql/src/Security/CWE-730/PolynomialReDoS.ql
+++ b/python/ql/src/Security/CWE-730/PolynomialReDoS.ql
@@ -15,13 +15,13 @@
import python
import semmle.python.security.dataflow.PolynomialReDoSQuery
-import DataFlow::PathGraph
+import PolynomialReDoSFlow::PathGraph
from
- Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink, Sink sinkNode,
+ PolynomialReDoSFlow::PathNode source, PolynomialReDoSFlow::PathNode sink, Sink sinkNode,
PolynomialBackTrackingTerm regexp
where
- config.hasFlowPath(source, sink) and
+ PolynomialReDoSFlow::flowPath(source, sink) and
sinkNode = sink.getNode() and
regexp.getRootTerm() = sinkNode.getRegExp()
// not (
From add1077532161435c90af9e2257efd2f2e9098e8 Mon Sep 17 00:00:00 2001
From: Rasmus Wriedt Larsen
Date: Fri, 25 Aug 2023 16:31:47 +0200
Subject: [PATCH 102/788] Python: Move `RegexInjection` to new dataflow API
---
.../security/dataflow/RegexInjectionQuery.qll | 17 +++++++++++++++--
.../ql/src/Security/CWE-730/RegexInjection.ql | 6 +++---
2 files changed, 18 insertions(+), 5 deletions(-)
diff --git a/python/ql/lib/semmle/python/security/dataflow/RegexInjectionQuery.qll b/python/ql/lib/semmle/python/security/dataflow/RegexInjectionQuery.qll
index c8287b22c75..168091bf212 100644
--- a/python/ql/lib/semmle/python/security/dataflow/RegexInjectionQuery.qll
+++ b/python/ql/lib/semmle/python/security/dataflow/RegexInjectionQuery.qll
@@ -1,5 +1,5 @@
/**
- * Provides a taint-tracking configuration for detecting regular expression injection
+ * Provides a taint-tracking configuration for detecting "regular expression injection"
* vulnerabilities.
*
* Note, for performance reasons: only import this file if
@@ -13,9 +13,11 @@ import semmle.python.dataflow.new.TaintTracking
import RegexInjectionCustomizations::RegexInjection
/**
+ * DEPRECATED: Use `RegexInjectionFlow` module instead.
+ *
* A taint-tracking configuration for detecting "reflected server-side cross-site scripting" vulnerabilities.
*/
-class Configuration extends TaintTracking::Configuration {
+deprecated class Configuration extends TaintTracking::Configuration {
Configuration() { this = "RegexInjection" }
override predicate isSource(DataFlow::Node source) { source instanceof Source }
@@ -28,3 +30,14 @@ class Configuration extends TaintTracking::Configuration {
guard instanceof SanitizerGuard
}
}
+
+private module RegexInjectionConfig 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 "regular expression injection" vulnerabilities. */
+module RegexInjectionFlow = TaintTracking::Global;
diff --git a/python/ql/src/Security/CWE-730/RegexInjection.ql b/python/ql/src/Security/CWE-730/RegexInjection.ql
index 5075c7a675d..fe1dc1dfe66 100644
--- a/python/ql/src/Security/CWE-730/RegexInjection.ql
+++ b/python/ql/src/Security/CWE-730/RegexInjection.ql
@@ -16,13 +16,13 @@
import python
private import semmle.python.Concepts
import semmle.python.security.dataflow.RegexInjectionQuery
-import DataFlow::PathGraph
+import RegexInjectionFlow::PathGraph
from
- Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink,
+ RegexInjectionFlow::PathNode source, RegexInjectionFlow::PathNode sink,
RegexExecution regexExecution
where
- config.hasFlowPath(source, sink) and
+ RegexInjectionFlow::flowPath(source, sink) and
regexExecution = sink.getNode().(Sink).getRegexExecution()
select sink.getNode(), source, sink,
"This regular expression depends on a $@ and is executed by $@.", source.getNode(),
From 46322b717a9c33c78cb2f7d8e9658850d9545eb7 Mon Sep 17 00:00:00 2001
From: Rasmus Wriedt Larsen
Date: Fri, 25 Aug 2023 16:32:18 +0200
Subject: [PATCH 103/788] Python: Move `XmlBomb` to new dataflow API
---
.../python/security/dataflow/XmlBombQuery.qll | 15 ++++++++++++++-
python/ql/src/Security/CWE-776/XmlBomb.ql | 6 +++---
2 files changed, 17 insertions(+), 4 deletions(-)
diff --git a/python/ql/lib/semmle/python/security/dataflow/XmlBombQuery.qll b/python/ql/lib/semmle/python/security/dataflow/XmlBombQuery.qll
index d0c0b85d84f..dcf3939bc78 100644
--- a/python/ql/lib/semmle/python/security/dataflow/XmlBombQuery.qll
+++ b/python/ql/lib/semmle/python/security/dataflow/XmlBombQuery.qll
@@ -12,9 +12,11 @@ import semmle.python.dataflow.new.TaintTracking
import XmlBombCustomizations::XmlBomb
/**
+ * DEPRECATED: Use `XmlBombFlow` module instead.
+ *
* A taint-tracking configuration for detecting "XML bomb" vulnerabilities.
*/
-class Configuration extends TaintTracking::Configuration {
+deprecated class Configuration extends TaintTracking::Configuration {
Configuration() { this = "XmlBomb" }
override predicate isSource(DataFlow::Node source) { source instanceof Source }
@@ -26,3 +28,14 @@ class Configuration extends TaintTracking::Configuration {
node instanceof Sanitizer
}
}
+
+private module XmlBombConfig 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 "XML bomb" vulnerabilities. */
+module XmlBombFlow = TaintTracking::Global;
diff --git a/python/ql/src/Security/CWE-776/XmlBomb.ql b/python/ql/src/Security/CWE-776/XmlBomb.ql
index f943aa58c44..c92d4f289f5 100644
--- a/python/ql/src/Security/CWE-776/XmlBomb.ql
+++ b/python/ql/src/Security/CWE-776/XmlBomb.ql
@@ -14,10 +14,10 @@
import python
import semmle.python.security.dataflow.XmlBombQuery
-import DataFlow::PathGraph
+import XmlBombFlow::PathGraph
-from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
-where cfg.hasFlowPath(source, sink)
+from XmlBombFlow::PathNode source, XmlBombFlow::PathNode sink
+where XmlBombFlow::flowPath(source, sink)
select sink.getNode(), source, sink,
"XML parsing depends on a $@ without guarding against uncontrolled entity expansion.",
source.getNode(), "user-provided value"
From dbfe5175555ee4d95c630d738132daf9d6b3826f Mon Sep 17 00:00:00 2001
From: Rasmus Wriedt Larsen
Date: Fri, 25 Aug 2023 16:34:36 +0200
Subject: [PATCH 104/788] Python: Move `HardcodedCredentials` to new dataflow
API
---
.../Security/CWE-798/HardcodedCredentials.ql | 17 +++++++++--------
1 file changed, 9 insertions(+), 8 deletions(-)
diff --git a/python/ql/src/Security/CWE-798/HardcodedCredentials.ql b/python/ql/src/Security/CWE-798/HardcodedCredentials.ql
index d1d29a78ff5..0a92427ec23 100644
--- a/python/ql/src/Security/CWE-798/HardcodedCredentials.ql
+++ b/python/ql/src/Security/CWE-798/HardcodedCredentials.ql
@@ -16,7 +16,6 @@ import python
import semmle.python.dataflow.new.DataFlow
import semmle.python.dataflow.new.TaintTracking
import semmle.python.filters.Tests
-import DataFlow::PathGraph
bindingset[char, fraction]
predicate fewer_characters_than(StrConst str, string char, float fraction) {
@@ -108,17 +107,19 @@ private string getACredentialRegex() {
result = "(?i).*(cert)(?!.*(format|name)).*"
}
-class HardcodedCredentialsConfiguration extends TaintTracking::Configuration {
- HardcodedCredentialsConfiguration() { this = "Hardcoded credentials configuration" }
+private module HardcodedCredentialsConfig implements DataFlow::ConfigSig {
+ predicate isSource(DataFlow::Node source) { source instanceof HardcodedValueSource }
- override predicate isSource(DataFlow::Node source) { source instanceof HardcodedValueSource }
-
- override predicate isSink(DataFlow::Node sink) { sink instanceof CredentialSink }
+ predicate isSink(DataFlow::Node sink) { sink instanceof CredentialSink }
}
-from HardcodedCredentialsConfiguration config, DataFlow::PathNode src, DataFlow::PathNode sink
+module HardcodedCredentialsFlow = TaintTracking::Global;
+
+import HardcodedCredentialsFlow::PathGraph
+
+from HardcodedCredentialsFlow::PathNode src, HardcodedCredentialsFlow::PathNode sink
where
- config.hasFlowPath(src, sink) and
+ HardcodedCredentialsFlow::flowPath(src, sink) and
not any(TestScope test).contains(src.getNode().asCfgNode().getNode())
select src.getNode(), src, sink, "This hardcoded value is $@.", sink.getNode(),
"used as credentials"
From 657b1997cc7a207cdbb64b10c51950ba76e5fffa Mon Sep 17 00:00:00 2001
From: Rasmus Wriedt Larsen
Date: Fri, 25 Aug 2023 16:41:14 +0200
Subject: [PATCH 105/788] Python: Move `FullServerSideRequestForgery` and
`PartialServerSideRequestForgery` to new dataflow API
---
.../ServerSideRequestForgeryQuery.qll | 59 +++++-
.../CWE-918/FullServerSideRequestForgery.ql | 8 +-
.../PartialServerSideRequestForgery.ql | 8 +-
.../FullServerSideRequestForgery.expected | 196 ------------------
.../PartialServerSideRequestForgery.expected | 106 ----------
5 files changed, 61 insertions(+), 316 deletions(-)
diff --git a/python/ql/lib/semmle/python/security/dataflow/ServerSideRequestForgeryQuery.qll b/python/ql/lib/semmle/python/security/dataflow/ServerSideRequestForgeryQuery.qll
index 36ec416cca2..a6c08185bd1 100644
--- a/python/ql/lib/semmle/python/security/dataflow/ServerSideRequestForgeryQuery.qll
+++ b/python/ql/lib/semmle/python/security/dataflow/ServerSideRequestForgeryQuery.qll
@@ -13,6 +13,8 @@ import semmle.python.Concepts
import ServerSideRequestForgeryCustomizations::ServerSideRequestForgery
/**
+ * DEPRECATED: Use `FullServerSideRequestForgeryFlow` module instead.
+ *
* A taint-tracking configuration for detecting "Server-side request forgery" vulnerabilities.
*
* This configuration has a sanitizer to limit results to cases where attacker has full control of URL.
@@ -21,7 +23,7 @@ import ServerSideRequestForgeryCustomizations::ServerSideRequestForgery
* You should use the `fullyControlledRequest` to only select results where all
* URL parts are fully controlled.
*/
-class FullServerSideRequestForgeryConfiguration extends TaintTracking::Configuration {
+deprecated class FullServerSideRequestForgeryConfiguration extends TaintTracking::Configuration {
FullServerSideRequestForgeryConfiguration() { this = "FullServerSideRequestForgery" }
override predicate isSource(DataFlow::Node source) { source instanceof Source }
@@ -39,24 +41,51 @@ class FullServerSideRequestForgeryConfiguration extends TaintTracking::Configura
}
}
+/**
+ * This configuration has a sanitizer to limit results to cases where attacker has full control of URL.
+ * See `PartialServerSideRequestForgery` for a variant without this requirement.
+ *
+ * You should use the `fullyControlledRequest` to only select results where all
+ * URL parts are fully controlled.
+ */
+private module FullServerSideRequestForgeryConfig 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
+ or
+ node instanceof FullUrlControlSanitizer
+ }
+}
+
+/**
+ * Global taint-tracking for detecting "Full server-side request forgery" vulnerabilities.
+ *
+ * You should use the `fullyControlledRequest` to only select results where all
+ * URL parts are fully controlled.
+ */
+module FullServerSideRequestForgeryFlow = TaintTracking::Global;
+
/**
* Holds if all URL parts of `request` is fully user controlled.
*/
predicate fullyControlledRequest(Http::Client::Request request) {
- exists(FullServerSideRequestForgeryConfiguration fullConfig |
- forall(DataFlow::Node urlPart | urlPart = request.getAUrlPart() |
- fullConfig.hasFlow(_, urlPart)
- )
+ forall(DataFlow::Node urlPart | urlPart = request.getAUrlPart() |
+ FullServerSideRequestForgeryFlow::flow(_, urlPart)
)
}
/**
+ * DEPRECATED: Use `FullServerSideRequestForgeryFlow` module instead.
+ *
* A taint-tracking configuration for detecting "Server-side request forgery" vulnerabilities.
*
* This configuration has results, even when the attacker does not have full control over the URL.
* See `FullServerSideRequestForgeryConfiguration`, and the `fullyControlledRequest` predicate.
*/
-class PartialServerSideRequestForgeryConfiguration extends TaintTracking::Configuration {
+deprecated class PartialServerSideRequestForgeryConfiguration extends TaintTracking::Configuration {
PartialServerSideRequestForgeryConfiguration() { this = "PartialServerSideRequestForgery" }
override predicate isSource(DataFlow::Node source) { source instanceof Source }
@@ -69,3 +98,21 @@ class PartialServerSideRequestForgeryConfiguration extends TaintTracking::Config
guard instanceof SanitizerGuard
}
}
+
+/**
+ * This configuration has results, even when the attacker does not have full control over the URL.
+ * See `FullServerSideRequestForgeryConfiguration`, and the `fullyControlledRequest` predicate.
+ */
+private module PartialServerSideRequestForgeryConfig 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 "partial server-side request forgery" vulnerabilities.
+ */
+module PartialServerSideRequestForgeryFlow =
+ TaintTracking::Global;
diff --git a/python/ql/src/Security/CWE-918/FullServerSideRequestForgery.ql b/python/ql/src/Security/CWE-918/FullServerSideRequestForgery.ql
index a29f9e775a1..4114ff31ce0 100644
--- a/python/ql/src/Security/CWE-918/FullServerSideRequestForgery.ql
+++ b/python/ql/src/Security/CWE-918/FullServerSideRequestForgery.ql
@@ -12,14 +12,14 @@
import python
import semmle.python.security.dataflow.ServerSideRequestForgeryQuery
-import DataFlow::PathGraph
+import FullServerSideRequestForgeryFlow::PathGraph
from
- FullServerSideRequestForgeryConfiguration fullConfig, DataFlow::PathNode source,
- DataFlow::PathNode sink, Http::Client::Request request
+ FullServerSideRequestForgeryFlow::PathNode source,
+ FullServerSideRequestForgeryFlow::PathNode sink, Http::Client::Request request
where
request = sink.getNode().(Sink).getRequest() and
- fullConfig.hasFlowPath(source, sink) and
+ FullServerSideRequestForgeryFlow::flowPath(source, sink) and
fullyControlledRequest(request)
select request, source, sink, "The full URL of this request depends on a $@.", source.getNode(),
"user-provided value"
diff --git a/python/ql/src/Security/CWE-918/PartialServerSideRequestForgery.ql b/python/ql/src/Security/CWE-918/PartialServerSideRequestForgery.ql
index 3bbeaabcce6..c6c679ca5e3 100644
--- a/python/ql/src/Security/CWE-918/PartialServerSideRequestForgery.ql
+++ b/python/ql/src/Security/CWE-918/PartialServerSideRequestForgery.ql
@@ -12,14 +12,14 @@
import python
import semmle.python.security.dataflow.ServerSideRequestForgeryQuery
-import DataFlow::PathGraph
+import PartialServerSideRequestForgeryFlow::PathGraph
from
- PartialServerSideRequestForgeryConfiguration partialConfig, DataFlow::PathNode source,
- DataFlow::PathNode sink, Http::Client::Request request
+ PartialServerSideRequestForgeryFlow::PathNode source,
+ PartialServerSideRequestForgeryFlow::PathNode sink, Http::Client::Request request
where
request = sink.getNode().(Sink).getRequest() and
- partialConfig.hasFlowPath(source, sink) and
+ PartialServerSideRequestForgeryFlow::flowPath(source, sink) and
not fullyControlledRequest(request)
select request, source, sink, "Part of the URL of this request depends on a $@.", source.getNode(),
"user-provided value"
diff --git a/python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/FullServerSideRequestForgery.expected b/python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/FullServerSideRequestForgery.expected
index a5c9c706518..3db6c82b96c 100644
--- a/python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/FullServerSideRequestForgery.expected
+++ b/python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/FullServerSideRequestForgery.expected
@@ -1,306 +1,110 @@
edges
| full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:1:19:1:25 | GSSA Variable request |
-| full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:1:19:1:25 | GSSA Variable request |
| full_partial_test.py:1:19:1:25 | GSSA Variable request | full_partial_test.py:7:18:7:24 | ControlFlowNode for request |
-| full_partial_test.py:1:19:1:25 | GSSA Variable request | full_partial_test.py:7:18:7:24 | ControlFlowNode for request |
-| full_partial_test.py:1:19:1:25 | GSSA Variable request | full_partial_test.py:8:17:8:23 | ControlFlowNode for request |
| full_partial_test.py:1:19:1:25 | GSSA Variable request | full_partial_test.py:37:18:37:24 | ControlFlowNode for request |
-| full_partial_test.py:1:19:1:25 | GSSA Variable request | full_partial_test.py:37:18:37:24 | ControlFlowNode for request |
-| full_partial_test.py:1:19:1:25 | GSSA Variable request | full_partial_test.py:38:17:38:23 | ControlFlowNode for request |
| full_partial_test.py:1:19:1:25 | GSSA Variable request | full_partial_test.py:57:18:57:24 | ControlFlowNode for request |
-| full_partial_test.py:1:19:1:25 | GSSA Variable request | full_partial_test.py:57:18:57:24 | ControlFlowNode for request |
-| full_partial_test.py:1:19:1:25 | GSSA Variable request | full_partial_test.py:58:17:58:23 | ControlFlowNode for request |
| full_partial_test.py:1:19:1:25 | GSSA Variable request | full_partial_test.py:71:18:71:24 | ControlFlowNode for request |
-| full_partial_test.py:1:19:1:25 | GSSA Variable request | full_partial_test.py:71:18:71:24 | ControlFlowNode for request |
-| full_partial_test.py:1:19:1:25 | GSSA Variable request | full_partial_test.py:72:17:72:23 | ControlFlowNode for request |
-| full_partial_test.py:1:19:1:25 | GSSA Variable request | full_partial_test.py:86:18:86:24 | ControlFlowNode for request |
-| full_partial_test.py:1:19:1:25 | GSSA Variable request | full_partial_test.py:92:18:92:24 | ControlFlowNode for request |
-| full_partial_test.py:1:19:1:25 | GSSA Variable request | full_partial_test.py:98:18:98:24 | ControlFlowNode for request |
-| full_partial_test.py:1:19:1:25 | GSSA Variable request | full_partial_test.py:104:18:104:24 | ControlFlowNode for request |
-| full_partial_test.py:1:19:1:25 | GSSA Variable request | full_partial_test.py:110:18:110:24 | ControlFlowNode for request |
-| full_partial_test.py:1:19:1:25 | GSSA Variable request | full_partial_test.py:119:18:119:24 | ControlFlowNode for request |
-| full_partial_test.py:7:5:7:14 | SSA variable user_input | full_partial_test.py:10:18:10:27 | ControlFlowNode for user_input |
| full_partial_test.py:7:5:7:14 | SSA variable user_input | full_partial_test.py:10:18:10:27 | ControlFlowNode for user_input |
| full_partial_test.py:7:5:7:14 | SSA variable user_input | full_partial_test.py:12:5:12:7 | SSA variable url |
-| full_partial_test.py:7:5:7:14 | SSA variable user_input | full_partial_test.py:12:5:12:7 | SSA variable url |
-| full_partial_test.py:7:5:7:14 | SSA variable user_input | full_partial_test.py:18:5:18:7 | SSA variable url |
| full_partial_test.py:7:5:7:14 | SSA variable user_input | full_partial_test.py:18:5:18:7 | SSA variable url |
| full_partial_test.py:7:5:7:14 | SSA variable user_input | full_partial_test.py:22:5:22:7 | SSA variable url |
-| full_partial_test.py:7:5:7:14 | SSA variable user_input | full_partial_test.py:22:5:22:7 | SSA variable url |
| full_partial_test.py:7:18:7:24 | ControlFlowNode for request | full_partial_test.py:7:5:7:14 | SSA variable user_input |
-| full_partial_test.py:7:18:7:24 | ControlFlowNode for request | full_partial_test.py:7:5:7:14 | SSA variable user_input |
-| full_partial_test.py:7:18:7:24 | ControlFlowNode for request | full_partial_test.py:8:5:8:13 | SSA variable query_val |
-| full_partial_test.py:8:5:8:13 | SSA variable query_val | full_partial_test.py:22:5:22:7 | SSA variable url |
-| full_partial_test.py:8:17:8:23 | ControlFlowNode for request | full_partial_test.py:8:5:8:13 | SSA variable query_val |
-| full_partial_test.py:12:5:12:7 | SSA variable url | full_partial_test.py:13:18:13:20 | ControlFlowNode for url |
| full_partial_test.py:12:5:12:7 | SSA variable url | full_partial_test.py:13:18:13:20 | ControlFlowNode for url |
| full_partial_test.py:18:5:18:7 | SSA variable url | full_partial_test.py:19:18:19:20 | ControlFlowNode for url |
-| full_partial_test.py:18:5:18:7 | SSA variable url | full_partial_test.py:19:18:19:20 | ControlFlowNode for url |
-| full_partial_test.py:22:5:22:7 | SSA variable url | full_partial_test.py:23:18:23:20 | ControlFlowNode for url |
| full_partial_test.py:22:5:22:7 | SSA variable url | full_partial_test.py:23:18:23:20 | ControlFlowNode for url |
| full_partial_test.py:37:5:37:14 | SSA variable user_input | full_partial_test.py:41:5:41:7 | SSA variable url |
-| full_partial_test.py:37:5:37:14 | SSA variable user_input | full_partial_test.py:41:5:41:7 | SSA variable url |
-| full_partial_test.py:37:5:37:14 | SSA variable user_input | full_partial_test.py:44:5:44:7 | SSA variable url |
| full_partial_test.py:37:5:37:14 | SSA variable user_input | full_partial_test.py:44:5:44:7 | SSA variable url |
| full_partial_test.py:37:5:37:14 | SSA variable user_input | full_partial_test.py:47:5:47:7 | SSA variable url |
-| full_partial_test.py:37:5:37:14 | SSA variable user_input | full_partial_test.py:47:5:47:7 | SSA variable url |
-| full_partial_test.py:37:5:37:14 | SSA variable user_input | full_partial_test.py:50:5:50:7 | SSA variable url |
| full_partial_test.py:37:5:37:14 | SSA variable user_input | full_partial_test.py:50:5:50:7 | SSA variable url |
| full_partial_test.py:37:5:37:14 | SSA variable user_input | full_partial_test.py:53:5:53:7 | SSA variable url |
-| full_partial_test.py:37:5:37:14 | SSA variable user_input | full_partial_test.py:53:5:53:7 | SSA variable url |
| full_partial_test.py:37:18:37:24 | ControlFlowNode for request | full_partial_test.py:37:5:37:14 | SSA variable user_input |
-| full_partial_test.py:37:18:37:24 | ControlFlowNode for request | full_partial_test.py:37:5:37:14 | SSA variable user_input |
-| full_partial_test.py:37:18:37:24 | ControlFlowNode for request | full_partial_test.py:38:5:38:13 | SSA variable query_val |
-| full_partial_test.py:38:5:38:13 | SSA variable query_val | full_partial_test.py:47:5:47:7 | SSA variable url |
-| full_partial_test.py:38:17:38:23 | ControlFlowNode for request | full_partial_test.py:38:5:38:13 | SSA variable query_val |
-| full_partial_test.py:41:5:41:7 | SSA variable url | full_partial_test.py:42:18:42:20 | ControlFlowNode for url |
| full_partial_test.py:41:5:41:7 | SSA variable url | full_partial_test.py:42:18:42:20 | ControlFlowNode for url |
| full_partial_test.py:44:5:44:7 | SSA variable url | full_partial_test.py:45:18:45:20 | ControlFlowNode for url |
-| full_partial_test.py:44:5:44:7 | SSA variable url | full_partial_test.py:45:18:45:20 | ControlFlowNode for url |
-| full_partial_test.py:47:5:47:7 | SSA variable url | full_partial_test.py:48:18:48:20 | ControlFlowNode for url |
| full_partial_test.py:47:5:47:7 | SSA variable url | full_partial_test.py:48:18:48:20 | ControlFlowNode for url |
| full_partial_test.py:50:5:50:7 | SSA variable url | full_partial_test.py:51:18:51:20 | ControlFlowNode for url |
-| full_partial_test.py:50:5:50:7 | SSA variable url | full_partial_test.py:51:18:51:20 | ControlFlowNode for url |
-| full_partial_test.py:53:5:53:7 | SSA variable url | full_partial_test.py:54:18:54:20 | ControlFlowNode for url |
| full_partial_test.py:53:5:53:7 | SSA variable url | full_partial_test.py:54:18:54:20 | ControlFlowNode for url |
| full_partial_test.py:57:5:57:14 | SSA variable user_input | full_partial_test.py:61:5:61:7 | SSA variable url |
-| full_partial_test.py:57:5:57:14 | SSA variable user_input | full_partial_test.py:61:5:61:7 | SSA variable url |
| full_partial_test.py:57:5:57:14 | SSA variable user_input | full_partial_test.py:64:5:64:7 | SSA variable url |
-| full_partial_test.py:57:5:57:14 | SSA variable user_input | full_partial_test.py:64:5:64:7 | SSA variable url |
-| full_partial_test.py:57:5:57:14 | SSA variable user_input | full_partial_test.py:67:5:67:7 | SSA variable url |
| full_partial_test.py:57:18:57:24 | ControlFlowNode for request | full_partial_test.py:57:5:57:14 | SSA variable user_input |
-| full_partial_test.py:57:18:57:24 | ControlFlowNode for request | full_partial_test.py:57:5:57:14 | SSA variable user_input |
-| full_partial_test.py:57:18:57:24 | ControlFlowNode for request | full_partial_test.py:58:5:58:13 | SSA variable query_val |
-| full_partial_test.py:58:5:58:13 | SSA variable query_val | full_partial_test.py:67:5:67:7 | SSA variable url |
-| full_partial_test.py:58:17:58:23 | ControlFlowNode for request | full_partial_test.py:58:5:58:13 | SSA variable query_val |
-| full_partial_test.py:61:5:61:7 | SSA variable url | full_partial_test.py:62:18:62:20 | ControlFlowNode for url |
| full_partial_test.py:61:5:61:7 | SSA variable url | full_partial_test.py:62:18:62:20 | ControlFlowNode for url |
| full_partial_test.py:64:5:64:7 | SSA variable url | full_partial_test.py:65:18:65:20 | ControlFlowNode for url |
-| full_partial_test.py:64:5:64:7 | SSA variable url | full_partial_test.py:65:18:65:20 | ControlFlowNode for url |
-| full_partial_test.py:67:5:67:7 | SSA variable url | full_partial_test.py:68:18:68:20 | ControlFlowNode for url |
-| full_partial_test.py:71:5:71:14 | SSA variable user_input | full_partial_test.py:75:5:75:7 | SSA variable url |
| full_partial_test.py:71:5:71:14 | SSA variable user_input | full_partial_test.py:75:5:75:7 | SSA variable url |
| full_partial_test.py:71:5:71:14 | SSA variable user_input | full_partial_test.py:78:5:78:7 | SSA variable url |
-| full_partial_test.py:71:5:71:14 | SSA variable user_input | full_partial_test.py:78:5:78:7 | SSA variable url |
-| full_partial_test.py:71:5:71:14 | SSA variable user_input | full_partial_test.py:81:5:81:7 | SSA variable url |
| full_partial_test.py:71:5:71:14 | SSA variable user_input | full_partial_test.py:81:5:81:7 | SSA variable url |
| full_partial_test.py:71:18:71:24 | ControlFlowNode for request | full_partial_test.py:71:5:71:14 | SSA variable user_input |
-| full_partial_test.py:71:18:71:24 | ControlFlowNode for request | full_partial_test.py:71:5:71:14 | SSA variable user_input |
-| full_partial_test.py:71:18:71:24 | ControlFlowNode for request | full_partial_test.py:72:5:72:13 | SSA variable query_val |
-| full_partial_test.py:72:5:72:13 | SSA variable query_val | full_partial_test.py:81:5:81:7 | SSA variable url |
-| full_partial_test.py:72:17:72:23 | ControlFlowNode for request | full_partial_test.py:72:5:72:13 | SSA variable query_val |
-| full_partial_test.py:75:5:75:7 | SSA variable url | full_partial_test.py:76:18:76:20 | ControlFlowNode for url |
| full_partial_test.py:75:5:75:7 | SSA variable url | full_partial_test.py:76:18:76:20 | ControlFlowNode for url |
| full_partial_test.py:78:5:78:7 | SSA variable url | full_partial_test.py:79:18:79:20 | ControlFlowNode for url |
-| full_partial_test.py:78:5:78:7 | SSA variable url | full_partial_test.py:79:18:79:20 | ControlFlowNode for url |
| full_partial_test.py:81:5:81:7 | SSA variable url | full_partial_test.py:82:18:82:20 | ControlFlowNode for url |
-| full_partial_test.py:81:5:81:7 | SSA variable url | full_partial_test.py:82:18:82:20 | ControlFlowNode for url |
-| full_partial_test.py:86:5:86:14 | SSA variable user_input | full_partial_test.py:88:5:88:7 | SSA variable url |
-| full_partial_test.py:86:18:86:24 | ControlFlowNode for request | full_partial_test.py:86:5:86:14 | SSA variable user_input |
-| full_partial_test.py:88:5:88:7 | SSA variable url | full_partial_test.py:89:18:89:20 | ControlFlowNode for url |
-| full_partial_test.py:92:5:92:14 | SSA variable user_input | full_partial_test.py:94:5:94:7 | SSA variable url |
-| full_partial_test.py:92:18:92:24 | ControlFlowNode for request | full_partial_test.py:92:5:92:14 | SSA variable user_input |
-| full_partial_test.py:94:5:94:7 | SSA variable url | full_partial_test.py:95:18:95:20 | ControlFlowNode for url |
-| full_partial_test.py:98:5:98:14 | SSA variable user_input | full_partial_test.py:100:5:100:7 | SSA variable url |
-| full_partial_test.py:98:18:98:24 | ControlFlowNode for request | full_partial_test.py:98:5:98:14 | SSA variable user_input |
-| full_partial_test.py:100:5:100:7 | SSA variable url | full_partial_test.py:101:18:101:20 | ControlFlowNode for url |
-| full_partial_test.py:104:5:104:14 | SSA variable user_input | full_partial_test.py:106:5:106:7 | SSA variable url |
-| full_partial_test.py:104:18:104:24 | ControlFlowNode for request | full_partial_test.py:104:5:104:14 | SSA variable user_input |
-| full_partial_test.py:106:5:106:7 | SSA variable url | full_partial_test.py:107:18:107:20 | ControlFlowNode for url |
-| full_partial_test.py:110:5:110:14 | SSA variable user_input | full_partial_test.py:115:5:115:7 | SSA variable url |
-| full_partial_test.py:110:18:110:24 | ControlFlowNode for request | full_partial_test.py:110:5:110:14 | SSA variable user_input |
-| full_partial_test.py:115:5:115:7 | SSA variable url | full_partial_test.py:116:18:116:20 | ControlFlowNode for url |
-| full_partial_test.py:119:5:119:14 | SSA variable user_input | full_partial_test.py:121:5:121:7 | SSA variable url |
-| full_partial_test.py:119:18:119:24 | ControlFlowNode for request | full_partial_test.py:119:5:119:14 | SSA variable user_input |
-| full_partial_test.py:121:5:121:7 | SSA variable url | full_partial_test.py:122:18:122:20 | ControlFlowNode for url |
-| test_http_client.py:1:26:1:32 | ControlFlowNode for ImportMember | test_http_client.py:1:26:1:32 | GSSA Variable request |
| test_http_client.py:1:26:1:32 | ControlFlowNode for ImportMember | test_http_client.py:1:26:1:32 | GSSA Variable request |
| test_http_client.py:1:26:1:32 | GSSA Variable request | test_http_client.py:9:19:9:25 | ControlFlowNode for request |
-| test_http_client.py:1:26:1:32 | GSSA Variable request | test_http_client.py:9:19:9:25 | ControlFlowNode for request |
| test_http_client.py:1:26:1:32 | GSSA Variable request | test_http_client.py:10:19:10:25 | ControlFlowNode for request |
-| test_http_client.py:1:26:1:32 | GSSA Variable request | test_http_client.py:10:19:10:25 | ControlFlowNode for request |
-| test_http_client.py:1:26:1:32 | GSSA Variable request | test_http_client.py:11:18:11:24 | ControlFlowNode for request |
-| test_http_client.py:9:5:9:15 | SSA variable unsafe_host | test_http_client.py:13:27:13:37 | ControlFlowNode for unsafe_host |
| test_http_client.py:9:5:9:15 | SSA variable unsafe_host | test_http_client.py:13:27:13:37 | ControlFlowNode for unsafe_host |
| test_http_client.py:9:5:9:15 | SSA variable unsafe_host | test_http_client.py:18:27:18:37 | ControlFlowNode for unsafe_host |
-| test_http_client.py:9:5:9:15 | SSA variable unsafe_host | test_http_client.py:18:27:18:37 | ControlFlowNode for unsafe_host |
-| test_http_client.py:9:5:9:15 | SSA variable unsafe_host | test_http_client.py:25:27:25:37 | ControlFlowNode for unsafe_host |
| test_http_client.py:9:5:9:15 | SSA variable unsafe_host | test_http_client.py:25:27:25:37 | ControlFlowNode for unsafe_host |
| test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:9:5:9:15 | SSA variable unsafe_host |
-| test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:9:5:9:15 | SSA variable unsafe_host |
| test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:10:5:10:15 | SSA variable unsafe_path |
-| test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:10:5:10:15 | SSA variable unsafe_path |
-| test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:11:5:11:14 | SSA variable user_input |
-| test_http_client.py:10:5:10:15 | SSA variable unsafe_path | test_http_client.py:14:25:14:35 | ControlFlowNode for unsafe_path |
| test_http_client.py:10:5:10:15 | SSA variable unsafe_path | test_http_client.py:14:25:14:35 | ControlFlowNode for unsafe_path |
| test_http_client.py:10:5:10:15 | SSA variable unsafe_path | test_http_client.py:19:25:19:35 | ControlFlowNode for unsafe_path |
-| test_http_client.py:10:5:10:15 | SSA variable unsafe_path | test_http_client.py:19:25:19:35 | ControlFlowNode for unsafe_path |
-| test_http_client.py:10:5:10:15 | SSA variable unsafe_path | test_http_client.py:29:25:29:35 | ControlFlowNode for unsafe_path |
| test_http_client.py:10:5:10:15 | SSA variable unsafe_path | test_http_client.py:29:25:29:35 | ControlFlowNode for unsafe_path |
| test_http_client.py:10:19:10:25 | ControlFlowNode for request | test_http_client.py:10:5:10:15 | SSA variable unsafe_path |
-| test_http_client.py:10:19:10:25 | ControlFlowNode for request | test_http_client.py:10:5:10:15 | SSA variable unsafe_path |
-| test_http_client.py:10:19:10:25 | ControlFlowNode for request | test_http_client.py:11:5:11:14 | SSA variable user_input |
-| test_http_client.py:11:5:11:14 | SSA variable user_input | test_http_client.py:31:5:31:8 | SSA variable path |
-| test_http_client.py:11:5:11:14 | SSA variable user_input | test_http_client.py:35:5:35:8 | SSA variable path |
-| test_http_client.py:11:18:11:24 | ControlFlowNode for request | test_http_client.py:11:5:11:14 | SSA variable user_input |
-| test_http_client.py:31:5:31:8 | SSA variable path | test_http_client.py:33:25:33:28 | ControlFlowNode for path |
-| test_http_client.py:35:5:35:8 | SSA variable path | test_http_client.py:37:25:37:28 | ControlFlowNode for path |
-| test_requests.py:1:19:1:25 | ControlFlowNode for ImportMember | test_requests.py:1:19:1:25 | GSSA Variable request |
| test_requests.py:1:19:1:25 | ControlFlowNode for ImportMember | test_requests.py:1:19:1:25 | GSSA Variable request |
| test_requests.py:1:19:1:25 | GSSA Variable request | test_requests.py:6:18:6:24 | ControlFlowNode for request |
-| test_requests.py:1:19:1:25 | GSSA Variable request | test_requests.py:6:18:6:24 | ControlFlowNode for request |
| test_requests.py:6:5:6:14 | SSA variable user_input | test_requests.py:8:18:8:27 | ControlFlowNode for user_input |
-| test_requests.py:6:5:6:14 | SSA variable user_input | test_requests.py:8:18:8:27 | ControlFlowNode for user_input |
-| test_requests.py:6:18:6:24 | ControlFlowNode for request | test_requests.py:6:5:6:14 | SSA variable user_input |
| test_requests.py:6:18:6:24 | ControlFlowNode for request | test_requests.py:6:5:6:14 | SSA variable user_input |
nodes
| full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember |
-| full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember |
-| full_partial_test.py:1:19:1:25 | GSSA Variable request | semmle.label | GSSA Variable request |
| full_partial_test.py:1:19:1:25 | GSSA Variable request | semmle.label | GSSA Variable request |
| full_partial_test.py:7:5:7:14 | SSA variable user_input | semmle.label | SSA variable user_input |
-| full_partial_test.py:7:5:7:14 | SSA variable user_input | semmle.label | SSA variable user_input |
| full_partial_test.py:7:18:7:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
-| full_partial_test.py:7:18:7:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
-| full_partial_test.py:8:5:8:13 | SSA variable query_val | semmle.label | SSA variable query_val |
-| full_partial_test.py:8:17:8:23 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
-| full_partial_test.py:10:18:10:27 | ControlFlowNode for user_input | semmle.label | ControlFlowNode for user_input |
| full_partial_test.py:10:18:10:27 | ControlFlowNode for user_input | semmle.label | ControlFlowNode for user_input |
| full_partial_test.py:12:5:12:7 | SSA variable url | semmle.label | SSA variable url |
-| full_partial_test.py:12:5:12:7 | SSA variable url | semmle.label | SSA variable url |
-| full_partial_test.py:13:18:13:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:13:18:13:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:18:5:18:7 | SSA variable url | semmle.label | SSA variable url |
-| full_partial_test.py:18:5:18:7 | SSA variable url | semmle.label | SSA variable url |
-| full_partial_test.py:19:18:19:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:19:18:19:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:22:5:22:7 | SSA variable url | semmle.label | SSA variable url |
-| full_partial_test.py:22:5:22:7 | SSA variable url | semmle.label | SSA variable url |
-| full_partial_test.py:23:18:23:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:23:18:23:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:37:5:37:14 | SSA variable user_input | semmle.label | SSA variable user_input |
-| full_partial_test.py:37:5:37:14 | SSA variable user_input | semmle.label | SSA variable user_input |
| full_partial_test.py:37:18:37:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
-| full_partial_test.py:37:18:37:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
-| full_partial_test.py:38:5:38:13 | SSA variable query_val | semmle.label | SSA variable query_val |
-| full_partial_test.py:38:17:38:23 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
-| full_partial_test.py:41:5:41:7 | SSA variable url | semmle.label | SSA variable url |
| full_partial_test.py:41:5:41:7 | SSA variable url | semmle.label | SSA variable url |
| full_partial_test.py:42:18:42:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
-| full_partial_test.py:42:18:42:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
-| full_partial_test.py:44:5:44:7 | SSA variable url | semmle.label | SSA variable url |
| full_partial_test.py:44:5:44:7 | SSA variable url | semmle.label | SSA variable url |
| full_partial_test.py:45:18:45:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
-| full_partial_test.py:45:18:45:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
-| full_partial_test.py:47:5:47:7 | SSA variable url | semmle.label | SSA variable url |
| full_partial_test.py:47:5:47:7 | SSA variable url | semmle.label | SSA variable url |
| full_partial_test.py:48:18:48:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
-| full_partial_test.py:48:18:48:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
-| full_partial_test.py:50:5:50:7 | SSA variable url | semmle.label | SSA variable url |
| full_partial_test.py:50:5:50:7 | SSA variable url | semmle.label | SSA variable url |
| full_partial_test.py:51:18:51:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
-| full_partial_test.py:51:18:51:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
-| full_partial_test.py:53:5:53:7 | SSA variable url | semmle.label | SSA variable url |
| full_partial_test.py:53:5:53:7 | SSA variable url | semmle.label | SSA variable url |
| full_partial_test.py:54:18:54:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
-| full_partial_test.py:54:18:54:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
-| full_partial_test.py:57:5:57:14 | SSA variable user_input | semmle.label | SSA variable user_input |
| full_partial_test.py:57:5:57:14 | SSA variable user_input | semmle.label | SSA variable user_input |
| full_partial_test.py:57:18:57:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
-| full_partial_test.py:57:18:57:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
-| full_partial_test.py:58:5:58:13 | SSA variable query_val | semmle.label | SSA variable query_val |
-| full_partial_test.py:58:17:58:23 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
-| full_partial_test.py:61:5:61:7 | SSA variable url | semmle.label | SSA variable url |
| full_partial_test.py:61:5:61:7 | SSA variable url | semmle.label | SSA variable url |
| full_partial_test.py:62:18:62:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
-| full_partial_test.py:62:18:62:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
-| full_partial_test.py:64:5:64:7 | SSA variable url | semmle.label | SSA variable url |
| full_partial_test.py:64:5:64:7 | SSA variable url | semmle.label | SSA variable url |
| full_partial_test.py:65:18:65:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
-| full_partial_test.py:65:18:65:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
-| full_partial_test.py:67:5:67:7 | SSA variable url | semmle.label | SSA variable url |
-| full_partial_test.py:68:18:68:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
-| full_partial_test.py:71:5:71:14 | SSA variable user_input | semmle.label | SSA variable user_input |
| full_partial_test.py:71:5:71:14 | SSA variable user_input | semmle.label | SSA variable user_input |
| full_partial_test.py:71:18:71:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
-| full_partial_test.py:71:18:71:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
-| full_partial_test.py:72:5:72:13 | SSA variable query_val | semmle.label | SSA variable query_val |
-| full_partial_test.py:72:17:72:23 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
-| full_partial_test.py:75:5:75:7 | SSA variable url | semmle.label | SSA variable url |
| full_partial_test.py:75:5:75:7 | SSA variable url | semmle.label | SSA variable url |
| full_partial_test.py:76:18:76:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
-| full_partial_test.py:76:18:76:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
-| full_partial_test.py:78:5:78:7 | SSA variable url | semmle.label | SSA variable url |
| full_partial_test.py:78:5:78:7 | SSA variable url | semmle.label | SSA variable url |
| full_partial_test.py:79:18:79:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
-| full_partial_test.py:79:18:79:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
-| full_partial_test.py:81:5:81:7 | SSA variable url | semmle.label | SSA variable url |
| full_partial_test.py:81:5:81:7 | SSA variable url | semmle.label | SSA variable url |
| full_partial_test.py:82:18:82:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
-| full_partial_test.py:82:18:82:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
-| full_partial_test.py:86:5:86:14 | SSA variable user_input | semmle.label | SSA variable user_input |
-| full_partial_test.py:86:18:86:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
-| full_partial_test.py:88:5:88:7 | SSA variable url | semmle.label | SSA variable url |
-| full_partial_test.py:89:18:89:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
-| full_partial_test.py:92:5:92:14 | SSA variable user_input | semmle.label | SSA variable user_input |
-| full_partial_test.py:92:18:92:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
-| full_partial_test.py:94:5:94:7 | SSA variable url | semmle.label | SSA variable url |
-| full_partial_test.py:95:18:95:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
-| full_partial_test.py:98:5:98:14 | SSA variable user_input | semmle.label | SSA variable user_input |
-| full_partial_test.py:98:18:98:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
-| full_partial_test.py:100:5:100:7 | SSA variable url | semmle.label | SSA variable url |
-| full_partial_test.py:101:18:101:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
-| full_partial_test.py:104:5:104:14 | SSA variable user_input | semmle.label | SSA variable user_input |
-| full_partial_test.py:104:18:104:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
-| full_partial_test.py:106:5:106:7 | SSA variable url | semmle.label | SSA variable url |
-| full_partial_test.py:107:18:107:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
-| full_partial_test.py:110:5:110:14 | SSA variable user_input | semmle.label | SSA variable user_input |
-| full_partial_test.py:110:18:110:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
-| full_partial_test.py:115:5:115:7 | SSA variable url | semmle.label | SSA variable url |
-| full_partial_test.py:116:18:116:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
-| full_partial_test.py:119:5:119:14 | SSA variable user_input | semmle.label | SSA variable user_input |
-| full_partial_test.py:119:18:119:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
-| full_partial_test.py:121:5:121:7 | SSA variable url | semmle.label | SSA variable url |
-| full_partial_test.py:122:18:122:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
-| test_http_client.py:1:26:1:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember |
| test_http_client.py:1:26:1:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember |
| test_http_client.py:1:26:1:32 | GSSA Variable request | semmle.label | GSSA Variable request |
-| test_http_client.py:1:26:1:32 | GSSA Variable request | semmle.label | GSSA Variable request |
-| test_http_client.py:9:5:9:15 | SSA variable unsafe_host | semmle.label | SSA variable unsafe_host |
| test_http_client.py:9:5:9:15 | SSA variable unsafe_host | semmle.label | SSA variable unsafe_host |
| test_http_client.py:9:19:9:25 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
-| test_http_client.py:9:19:9:25 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
-| test_http_client.py:10:5:10:15 | SSA variable unsafe_path | semmle.label | SSA variable unsafe_path |
| test_http_client.py:10:5:10:15 | SSA variable unsafe_path | semmle.label | SSA variable unsafe_path |
| test_http_client.py:10:19:10:25 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
-| test_http_client.py:10:19:10:25 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
-| test_http_client.py:11:5:11:14 | SSA variable user_input | semmle.label | SSA variable user_input |
-| test_http_client.py:11:18:11:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
-| test_http_client.py:13:27:13:37 | ControlFlowNode for unsafe_host | semmle.label | ControlFlowNode for unsafe_host |
| test_http_client.py:13:27:13:37 | ControlFlowNode for unsafe_host | semmle.label | ControlFlowNode for unsafe_host |
| test_http_client.py:14:25:14:35 | ControlFlowNode for unsafe_path | semmle.label | ControlFlowNode for unsafe_path |
-| test_http_client.py:14:25:14:35 | ControlFlowNode for unsafe_path | semmle.label | ControlFlowNode for unsafe_path |
-| test_http_client.py:18:27:18:37 | ControlFlowNode for unsafe_host | semmle.label | ControlFlowNode for unsafe_host |
| test_http_client.py:18:27:18:37 | ControlFlowNode for unsafe_host | semmle.label | ControlFlowNode for unsafe_host |
| test_http_client.py:19:25:19:35 | ControlFlowNode for unsafe_path | semmle.label | ControlFlowNode for unsafe_path |
-| test_http_client.py:19:25:19:35 | ControlFlowNode for unsafe_path | semmle.label | ControlFlowNode for unsafe_path |
-| test_http_client.py:25:27:25:37 | ControlFlowNode for unsafe_host | semmle.label | ControlFlowNode for unsafe_host |
| test_http_client.py:25:27:25:37 | ControlFlowNode for unsafe_host | semmle.label | ControlFlowNode for unsafe_host |
| test_http_client.py:29:25:29:35 | ControlFlowNode for unsafe_path | semmle.label | ControlFlowNode for unsafe_path |
-| test_http_client.py:29:25:29:35 | ControlFlowNode for unsafe_path | semmle.label | ControlFlowNode for unsafe_path |
-| test_http_client.py:31:5:31:8 | SSA variable path | semmle.label | SSA variable path |
-| test_http_client.py:33:25:33:28 | ControlFlowNode for path | semmle.label | ControlFlowNode for path |
-| test_http_client.py:35:5:35:8 | SSA variable path | semmle.label | SSA variable path |
-| test_http_client.py:37:25:37:28 | ControlFlowNode for path | semmle.label | ControlFlowNode for path |
-| test_requests.py:1:19:1:25 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember |
| test_requests.py:1:19:1:25 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember |
| test_requests.py:1:19:1:25 | GSSA Variable request | semmle.label | GSSA Variable request |
-| test_requests.py:1:19:1:25 | GSSA Variable request | semmle.label | GSSA Variable request |
-| test_requests.py:6:5:6:14 | SSA variable user_input | semmle.label | SSA variable user_input |
| test_requests.py:6:5:6:14 | SSA variable user_input | semmle.label | SSA variable user_input |
| test_requests.py:6:18:6:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
-| test_requests.py:6:18:6:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
-| test_requests.py:8:18:8:27 | ControlFlowNode for user_input | semmle.label | ControlFlowNode for user_input |
| test_requests.py:8:18:8:27 | ControlFlowNode for user_input | semmle.label | ControlFlowNode for user_input |
subpaths
#select
diff --git a/python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/PartialServerSideRequestForgery.expected b/python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/PartialServerSideRequestForgery.expected
index faa8560d19f..aa983e62e01 100644
--- a/python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/PartialServerSideRequestForgery.expected
+++ b/python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/PartialServerSideRequestForgery.expected
@@ -1,17 +1,12 @@
edges
| full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:1:19:1:25 | GSSA Variable request |
-| full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:1:19:1:25 | GSSA Variable request |
-| full_partial_test.py:1:19:1:25 | GSSA Variable request | full_partial_test.py:7:18:7:24 | ControlFlowNode for request |
| full_partial_test.py:1:19:1:25 | GSSA Variable request | full_partial_test.py:7:18:7:24 | ControlFlowNode for request |
| full_partial_test.py:1:19:1:25 | GSSA Variable request | full_partial_test.py:8:17:8:23 | ControlFlowNode for request |
| full_partial_test.py:1:19:1:25 | GSSA Variable request | full_partial_test.py:37:18:37:24 | ControlFlowNode for request |
-| full_partial_test.py:1:19:1:25 | GSSA Variable request | full_partial_test.py:37:18:37:24 | ControlFlowNode for request |
| full_partial_test.py:1:19:1:25 | GSSA Variable request | full_partial_test.py:38:17:38:23 | ControlFlowNode for request |
| full_partial_test.py:1:19:1:25 | GSSA Variable request | full_partial_test.py:57:18:57:24 | ControlFlowNode for request |
-| full_partial_test.py:1:19:1:25 | GSSA Variable request | full_partial_test.py:57:18:57:24 | ControlFlowNode for request |
| full_partial_test.py:1:19:1:25 | GSSA Variable request | full_partial_test.py:58:17:58:23 | ControlFlowNode for request |
| full_partial_test.py:1:19:1:25 | GSSA Variable request | full_partial_test.py:71:18:71:24 | ControlFlowNode for request |
-| full_partial_test.py:1:19:1:25 | GSSA Variable request | full_partial_test.py:71:18:71:24 | ControlFlowNode for request |
| full_partial_test.py:1:19:1:25 | GSSA Variable request | full_partial_test.py:72:17:72:23 | ControlFlowNode for request |
| full_partial_test.py:1:19:1:25 | GSSA Variable request | full_partial_test.py:86:18:86:24 | ControlFlowNode for request |
| full_partial_test.py:1:19:1:25 | GSSA Variable request | full_partial_test.py:92:18:92:24 | ControlFlowNode for request |
@@ -20,80 +15,49 @@ edges
| full_partial_test.py:1:19:1:25 | GSSA Variable request | full_partial_test.py:110:18:110:24 | ControlFlowNode for request |
| full_partial_test.py:1:19:1:25 | GSSA Variable request | full_partial_test.py:119:18:119:24 | ControlFlowNode for request |
| full_partial_test.py:7:5:7:14 | SSA variable user_input | full_partial_test.py:10:18:10:27 | ControlFlowNode for user_input |
-| full_partial_test.py:7:5:7:14 | SSA variable user_input | full_partial_test.py:10:18:10:27 | ControlFlowNode for user_input |
-| full_partial_test.py:7:5:7:14 | SSA variable user_input | full_partial_test.py:12:5:12:7 | SSA variable url |
| full_partial_test.py:7:5:7:14 | SSA variable user_input | full_partial_test.py:12:5:12:7 | SSA variable url |
| full_partial_test.py:7:5:7:14 | SSA variable user_input | full_partial_test.py:18:5:18:7 | SSA variable url |
-| full_partial_test.py:7:5:7:14 | SSA variable user_input | full_partial_test.py:18:5:18:7 | SSA variable url |
| full_partial_test.py:7:5:7:14 | SSA variable user_input | full_partial_test.py:22:5:22:7 | SSA variable url |
-| full_partial_test.py:7:5:7:14 | SSA variable user_input | full_partial_test.py:22:5:22:7 | SSA variable url |
-| full_partial_test.py:7:18:7:24 | ControlFlowNode for request | full_partial_test.py:7:5:7:14 | SSA variable user_input |
| full_partial_test.py:7:18:7:24 | ControlFlowNode for request | full_partial_test.py:7:5:7:14 | SSA variable user_input |
| full_partial_test.py:7:18:7:24 | ControlFlowNode for request | full_partial_test.py:8:5:8:13 | SSA variable query_val |
| full_partial_test.py:8:5:8:13 | SSA variable query_val | full_partial_test.py:22:5:22:7 | SSA variable url |
| full_partial_test.py:8:17:8:23 | ControlFlowNode for request | full_partial_test.py:8:5:8:13 | SSA variable query_val |
| full_partial_test.py:12:5:12:7 | SSA variable url | full_partial_test.py:13:18:13:20 | ControlFlowNode for url |
-| full_partial_test.py:12:5:12:7 | SSA variable url | full_partial_test.py:13:18:13:20 | ControlFlowNode for url |
-| full_partial_test.py:18:5:18:7 | SSA variable url | full_partial_test.py:19:18:19:20 | ControlFlowNode for url |
| full_partial_test.py:18:5:18:7 | SSA variable url | full_partial_test.py:19:18:19:20 | ControlFlowNode for url |
| full_partial_test.py:22:5:22:7 | SSA variable url | full_partial_test.py:23:18:23:20 | ControlFlowNode for url |
-| full_partial_test.py:22:5:22:7 | SSA variable url | full_partial_test.py:23:18:23:20 | ControlFlowNode for url |
-| full_partial_test.py:37:5:37:14 | SSA variable user_input | full_partial_test.py:41:5:41:7 | SSA variable url |
| full_partial_test.py:37:5:37:14 | SSA variable user_input | full_partial_test.py:41:5:41:7 | SSA variable url |
| full_partial_test.py:37:5:37:14 | SSA variable user_input | full_partial_test.py:44:5:44:7 | SSA variable url |
-| full_partial_test.py:37:5:37:14 | SSA variable user_input | full_partial_test.py:44:5:44:7 | SSA variable url |
-| full_partial_test.py:37:5:37:14 | SSA variable user_input | full_partial_test.py:47:5:47:7 | SSA variable url |
| full_partial_test.py:37:5:37:14 | SSA variable user_input | full_partial_test.py:47:5:47:7 | SSA variable url |
| full_partial_test.py:37:5:37:14 | SSA variable user_input | full_partial_test.py:50:5:50:7 | SSA variable url |
-| full_partial_test.py:37:5:37:14 | SSA variable user_input | full_partial_test.py:50:5:50:7 | SSA variable url |
| full_partial_test.py:37:5:37:14 | SSA variable user_input | full_partial_test.py:53:5:53:7 | SSA variable url |
-| full_partial_test.py:37:5:37:14 | SSA variable user_input | full_partial_test.py:53:5:53:7 | SSA variable url |
-| full_partial_test.py:37:18:37:24 | ControlFlowNode for request | full_partial_test.py:37:5:37:14 | SSA variable user_input |
| full_partial_test.py:37:18:37:24 | ControlFlowNode for request | full_partial_test.py:37:5:37:14 | SSA variable user_input |
| full_partial_test.py:37:18:37:24 | ControlFlowNode for request | full_partial_test.py:38:5:38:13 | SSA variable query_val |
| full_partial_test.py:38:5:38:13 | SSA variable query_val | full_partial_test.py:47:5:47:7 | SSA variable url |
| full_partial_test.py:38:17:38:23 | ControlFlowNode for request | full_partial_test.py:38:5:38:13 | SSA variable query_val |
| full_partial_test.py:41:5:41:7 | SSA variable url | full_partial_test.py:42:18:42:20 | ControlFlowNode for url |
-| full_partial_test.py:41:5:41:7 | SSA variable url | full_partial_test.py:42:18:42:20 | ControlFlowNode for url |
-| full_partial_test.py:44:5:44:7 | SSA variable url | full_partial_test.py:45:18:45:20 | ControlFlowNode for url |
| full_partial_test.py:44:5:44:7 | SSA variable url | full_partial_test.py:45:18:45:20 | ControlFlowNode for url |
| full_partial_test.py:47:5:47:7 | SSA variable url | full_partial_test.py:48:18:48:20 | ControlFlowNode for url |
-| full_partial_test.py:47:5:47:7 | SSA variable url | full_partial_test.py:48:18:48:20 | ControlFlowNode for url |
-| full_partial_test.py:50:5:50:7 | SSA variable url | full_partial_test.py:51:18:51:20 | ControlFlowNode for url |
| full_partial_test.py:50:5:50:7 | SSA variable url | full_partial_test.py:51:18:51:20 | ControlFlowNode for url |
| full_partial_test.py:53:5:53:7 | SSA variable url | full_partial_test.py:54:18:54:20 | ControlFlowNode for url |
-| full_partial_test.py:53:5:53:7 | SSA variable url | full_partial_test.py:54:18:54:20 | ControlFlowNode for url |
| full_partial_test.py:57:5:57:14 | SSA variable user_input | full_partial_test.py:61:5:61:7 | SSA variable url |
-| full_partial_test.py:57:5:57:14 | SSA variable user_input | full_partial_test.py:61:5:61:7 | SSA variable url |
-| full_partial_test.py:57:5:57:14 | SSA variable user_input | full_partial_test.py:64:5:64:7 | SSA variable url |
| full_partial_test.py:57:5:57:14 | SSA variable user_input | full_partial_test.py:64:5:64:7 | SSA variable url |
| full_partial_test.py:57:5:57:14 | SSA variable user_input | full_partial_test.py:67:5:67:7 | SSA variable url |
| full_partial_test.py:57:18:57:24 | ControlFlowNode for request | full_partial_test.py:57:5:57:14 | SSA variable user_input |
-| full_partial_test.py:57:18:57:24 | ControlFlowNode for request | full_partial_test.py:57:5:57:14 | SSA variable user_input |
| full_partial_test.py:57:18:57:24 | ControlFlowNode for request | full_partial_test.py:58:5:58:13 | SSA variable query_val |
| full_partial_test.py:58:5:58:13 | SSA variable query_val | full_partial_test.py:67:5:67:7 | SSA variable url |
| full_partial_test.py:58:17:58:23 | ControlFlowNode for request | full_partial_test.py:58:5:58:13 | SSA variable query_val |
| full_partial_test.py:61:5:61:7 | SSA variable url | full_partial_test.py:62:18:62:20 | ControlFlowNode for url |
-| full_partial_test.py:61:5:61:7 | SSA variable url | full_partial_test.py:62:18:62:20 | ControlFlowNode for url |
-| full_partial_test.py:64:5:64:7 | SSA variable url | full_partial_test.py:65:18:65:20 | ControlFlowNode for url |
| full_partial_test.py:64:5:64:7 | SSA variable url | full_partial_test.py:65:18:65:20 | ControlFlowNode for url |
| full_partial_test.py:67:5:67:7 | SSA variable url | full_partial_test.py:68:18:68:20 | ControlFlowNode for url |
| full_partial_test.py:71:5:71:14 | SSA variable user_input | full_partial_test.py:75:5:75:7 | SSA variable url |
-| full_partial_test.py:71:5:71:14 | SSA variable user_input | full_partial_test.py:75:5:75:7 | SSA variable url |
-| full_partial_test.py:71:5:71:14 | SSA variable user_input | full_partial_test.py:78:5:78:7 | SSA variable url |
| full_partial_test.py:71:5:71:14 | SSA variable user_input | full_partial_test.py:78:5:78:7 | SSA variable url |
| full_partial_test.py:71:5:71:14 | SSA variable user_input | full_partial_test.py:81:5:81:7 | SSA variable url |
-| full_partial_test.py:71:5:71:14 | SSA variable user_input | full_partial_test.py:81:5:81:7 | SSA variable url |
-| full_partial_test.py:71:18:71:24 | ControlFlowNode for request | full_partial_test.py:71:5:71:14 | SSA variable user_input |
| full_partial_test.py:71:18:71:24 | ControlFlowNode for request | full_partial_test.py:71:5:71:14 | SSA variable user_input |
| full_partial_test.py:71:18:71:24 | ControlFlowNode for request | full_partial_test.py:72:5:72:13 | SSA variable query_val |
| full_partial_test.py:72:5:72:13 | SSA variable query_val | full_partial_test.py:81:5:81:7 | SSA variable url |
| full_partial_test.py:72:17:72:23 | ControlFlowNode for request | full_partial_test.py:72:5:72:13 | SSA variable query_val |
| full_partial_test.py:75:5:75:7 | SSA variable url | full_partial_test.py:76:18:76:20 | ControlFlowNode for url |
-| full_partial_test.py:75:5:75:7 | SSA variable url | full_partial_test.py:76:18:76:20 | ControlFlowNode for url |
| full_partial_test.py:78:5:78:7 | SSA variable url | full_partial_test.py:79:18:79:20 | ControlFlowNode for url |
-| full_partial_test.py:78:5:78:7 | SSA variable url | full_partial_test.py:79:18:79:20 | ControlFlowNode for url |
-| full_partial_test.py:81:5:81:7 | SSA variable url | full_partial_test.py:82:18:82:20 | ControlFlowNode for url |
| full_partial_test.py:81:5:81:7 | SSA variable url | full_partial_test.py:82:18:82:20 | ControlFlowNode for url |
| full_partial_test.py:86:5:86:14 | SSA variable user_input | full_partial_test.py:88:5:88:7 | SSA variable url |
| full_partial_test.py:86:18:86:24 | ControlFlowNode for request | full_partial_test.py:86:5:86:14 | SSA variable user_input |
@@ -114,30 +78,18 @@ edges
| full_partial_test.py:119:18:119:24 | ControlFlowNode for request | full_partial_test.py:119:5:119:14 | SSA variable user_input |
| full_partial_test.py:121:5:121:7 | SSA variable url | full_partial_test.py:122:18:122:20 | ControlFlowNode for url |
| test_http_client.py:1:26:1:32 | ControlFlowNode for ImportMember | test_http_client.py:1:26:1:32 | GSSA Variable request |
-| test_http_client.py:1:26:1:32 | ControlFlowNode for ImportMember | test_http_client.py:1:26:1:32 | GSSA Variable request |
| test_http_client.py:1:26:1:32 | GSSA Variable request | test_http_client.py:9:19:9:25 | ControlFlowNode for request |
-| test_http_client.py:1:26:1:32 | GSSA Variable request | test_http_client.py:9:19:9:25 | ControlFlowNode for request |
-| test_http_client.py:1:26:1:32 | GSSA Variable request | test_http_client.py:10:19:10:25 | ControlFlowNode for request |
| test_http_client.py:1:26:1:32 | GSSA Variable request | test_http_client.py:10:19:10:25 | ControlFlowNode for request |
| test_http_client.py:1:26:1:32 | GSSA Variable request | test_http_client.py:11:18:11:24 | ControlFlowNode for request |
| test_http_client.py:9:5:9:15 | SSA variable unsafe_host | test_http_client.py:13:27:13:37 | ControlFlowNode for unsafe_host |
-| test_http_client.py:9:5:9:15 | SSA variable unsafe_host | test_http_client.py:13:27:13:37 | ControlFlowNode for unsafe_host |
-| test_http_client.py:9:5:9:15 | SSA variable unsafe_host | test_http_client.py:18:27:18:37 | ControlFlowNode for unsafe_host |
| test_http_client.py:9:5:9:15 | SSA variable unsafe_host | test_http_client.py:18:27:18:37 | ControlFlowNode for unsafe_host |
| test_http_client.py:9:5:9:15 | SSA variable unsafe_host | test_http_client.py:25:27:25:37 | ControlFlowNode for unsafe_host |
-| test_http_client.py:9:5:9:15 | SSA variable unsafe_host | test_http_client.py:25:27:25:37 | ControlFlowNode for unsafe_host |
| test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:9:5:9:15 | SSA variable unsafe_host |
-| test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:9:5:9:15 | SSA variable unsafe_host |
-| test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:10:5:10:15 | SSA variable unsafe_path |
| test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:10:5:10:15 | SSA variable unsafe_path |
| test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:11:5:11:14 | SSA variable user_input |
| test_http_client.py:10:5:10:15 | SSA variable unsafe_path | test_http_client.py:14:25:14:35 | ControlFlowNode for unsafe_path |
-| test_http_client.py:10:5:10:15 | SSA variable unsafe_path | test_http_client.py:14:25:14:35 | ControlFlowNode for unsafe_path |
-| test_http_client.py:10:5:10:15 | SSA variable unsafe_path | test_http_client.py:19:25:19:35 | ControlFlowNode for unsafe_path |
| test_http_client.py:10:5:10:15 | SSA variable unsafe_path | test_http_client.py:19:25:19:35 | ControlFlowNode for unsafe_path |
| test_http_client.py:10:5:10:15 | SSA variable unsafe_path | test_http_client.py:29:25:29:35 | ControlFlowNode for unsafe_path |
-| test_http_client.py:10:5:10:15 | SSA variable unsafe_path | test_http_client.py:29:25:29:35 | ControlFlowNode for unsafe_path |
-| test_http_client.py:10:19:10:25 | ControlFlowNode for request | test_http_client.py:10:5:10:15 | SSA variable unsafe_path |
| test_http_client.py:10:19:10:25 | ControlFlowNode for request | test_http_client.py:10:5:10:15 | SSA variable unsafe_path |
| test_http_client.py:10:19:10:25 | ControlFlowNode for request | test_http_client.py:11:5:11:14 | SSA variable user_input |
| test_http_client.py:11:5:11:14 | SSA variable user_input | test_http_client.py:31:5:31:8 | SSA variable path |
@@ -146,97 +98,56 @@ edges
| test_http_client.py:31:5:31:8 | SSA variable path | test_http_client.py:33:25:33:28 | ControlFlowNode for path |
| test_http_client.py:35:5:35:8 | SSA variable path | test_http_client.py:37:25:37:28 | ControlFlowNode for path |
| test_requests.py:1:19:1:25 | ControlFlowNode for ImportMember | test_requests.py:1:19:1:25 | GSSA Variable request |
-| test_requests.py:1:19:1:25 | ControlFlowNode for ImportMember | test_requests.py:1:19:1:25 | GSSA Variable request |
-| test_requests.py:1:19:1:25 | GSSA Variable request | test_requests.py:6:18:6:24 | ControlFlowNode for request |
| test_requests.py:1:19:1:25 | GSSA Variable request | test_requests.py:6:18:6:24 | ControlFlowNode for request |
| test_requests.py:6:5:6:14 | SSA variable user_input | test_requests.py:8:18:8:27 | ControlFlowNode for user_input |
-| test_requests.py:6:5:6:14 | SSA variable user_input | test_requests.py:8:18:8:27 | ControlFlowNode for user_input |
-| test_requests.py:6:18:6:24 | ControlFlowNode for request | test_requests.py:6:5:6:14 | SSA variable user_input |
| test_requests.py:6:18:6:24 | ControlFlowNode for request | test_requests.py:6:5:6:14 | SSA variable user_input |
nodes
| full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember |
-| full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember |
-| full_partial_test.py:1:19:1:25 | GSSA Variable request | semmle.label | GSSA Variable request |
| full_partial_test.py:1:19:1:25 | GSSA Variable request | semmle.label | GSSA Variable request |
| full_partial_test.py:7:5:7:14 | SSA variable user_input | semmle.label | SSA variable user_input |
-| full_partial_test.py:7:5:7:14 | SSA variable user_input | semmle.label | SSA variable user_input |
-| full_partial_test.py:7:18:7:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| full_partial_test.py:7:18:7:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| full_partial_test.py:8:5:8:13 | SSA variable query_val | semmle.label | SSA variable query_val |
| full_partial_test.py:8:17:8:23 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| full_partial_test.py:10:18:10:27 | ControlFlowNode for user_input | semmle.label | ControlFlowNode for user_input |
-| full_partial_test.py:10:18:10:27 | ControlFlowNode for user_input | semmle.label | ControlFlowNode for user_input |
-| full_partial_test.py:12:5:12:7 | SSA variable url | semmle.label | SSA variable url |
| full_partial_test.py:12:5:12:7 | SSA variable url | semmle.label | SSA variable url |
| full_partial_test.py:13:18:13:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
-| full_partial_test.py:13:18:13:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
-| full_partial_test.py:18:5:18:7 | SSA variable url | semmle.label | SSA variable url |
| full_partial_test.py:18:5:18:7 | SSA variable url | semmle.label | SSA variable url |
| full_partial_test.py:19:18:19:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
-| full_partial_test.py:19:18:19:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
-| full_partial_test.py:22:5:22:7 | SSA variable url | semmle.label | SSA variable url |
| full_partial_test.py:22:5:22:7 | SSA variable url | semmle.label | SSA variable url |
| full_partial_test.py:23:18:23:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
-| full_partial_test.py:23:18:23:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:37:5:37:14 | SSA variable user_input | semmle.label | SSA variable user_input |
-| full_partial_test.py:37:5:37:14 | SSA variable user_input | semmle.label | SSA variable user_input |
-| full_partial_test.py:37:18:37:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| full_partial_test.py:37:18:37:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| full_partial_test.py:38:5:38:13 | SSA variable query_val | semmle.label | SSA variable query_val |
| full_partial_test.py:38:17:38:23 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| full_partial_test.py:41:5:41:7 | SSA variable url | semmle.label | SSA variable url |
-| full_partial_test.py:41:5:41:7 | SSA variable url | semmle.label | SSA variable url |
-| full_partial_test.py:42:18:42:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:42:18:42:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:44:5:44:7 | SSA variable url | semmle.label | SSA variable url |
-| full_partial_test.py:44:5:44:7 | SSA variable url | semmle.label | SSA variable url |
-| full_partial_test.py:45:18:45:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:45:18:45:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:47:5:47:7 | SSA variable url | semmle.label | SSA variable url |
-| full_partial_test.py:47:5:47:7 | SSA variable url | semmle.label | SSA variable url |
-| full_partial_test.py:48:18:48:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:48:18:48:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:50:5:50:7 | SSA variable url | semmle.label | SSA variable url |
-| full_partial_test.py:50:5:50:7 | SSA variable url | semmle.label | SSA variable url |
-| full_partial_test.py:51:18:51:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:51:18:51:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:53:5:53:7 | SSA variable url | semmle.label | SSA variable url |
-| full_partial_test.py:53:5:53:7 | SSA variable url | semmle.label | SSA variable url |
-| full_partial_test.py:54:18:54:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:54:18:54:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:57:5:57:14 | SSA variable user_input | semmle.label | SSA variable user_input |
-| full_partial_test.py:57:5:57:14 | SSA variable user_input | semmle.label | SSA variable user_input |
-| full_partial_test.py:57:18:57:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| full_partial_test.py:57:18:57:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| full_partial_test.py:58:5:58:13 | SSA variable query_val | semmle.label | SSA variable query_val |
| full_partial_test.py:58:17:58:23 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| full_partial_test.py:61:5:61:7 | SSA variable url | semmle.label | SSA variable url |
-| full_partial_test.py:61:5:61:7 | SSA variable url | semmle.label | SSA variable url |
-| full_partial_test.py:62:18:62:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:62:18:62:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:64:5:64:7 | SSA variable url | semmle.label | SSA variable url |
-| full_partial_test.py:64:5:64:7 | SSA variable url | semmle.label | SSA variable url |
-| full_partial_test.py:65:18:65:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:65:18:65:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:67:5:67:7 | SSA variable url | semmle.label | SSA variable url |
| full_partial_test.py:68:18:68:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:71:5:71:14 | SSA variable user_input | semmle.label | SSA variable user_input |
-| full_partial_test.py:71:5:71:14 | SSA variable user_input | semmle.label | SSA variable user_input |
-| full_partial_test.py:71:18:71:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| full_partial_test.py:71:18:71:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| full_partial_test.py:72:5:72:13 | SSA variable query_val | semmle.label | SSA variable query_val |
| full_partial_test.py:72:17:72:23 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| full_partial_test.py:75:5:75:7 | SSA variable url | semmle.label | SSA variable url |
-| full_partial_test.py:75:5:75:7 | SSA variable url | semmle.label | SSA variable url |
-| full_partial_test.py:76:18:76:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:76:18:76:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:78:5:78:7 | SSA variable url | semmle.label | SSA variable url |
-| full_partial_test.py:78:5:78:7 | SSA variable url | semmle.label | SSA variable url |
-| full_partial_test.py:79:18:79:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:79:18:79:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:81:5:81:7 | SSA variable url | semmle.label | SSA variable url |
-| full_partial_test.py:81:5:81:7 | SSA variable url | semmle.label | SSA variable url |
-| full_partial_test.py:82:18:82:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:82:18:82:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| full_partial_test.py:86:5:86:14 | SSA variable user_input | semmle.label | SSA variable user_input |
| full_partial_test.py:86:18:86:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
@@ -263,44 +174,27 @@ nodes
| full_partial_test.py:121:5:121:7 | SSA variable url | semmle.label | SSA variable url |
| full_partial_test.py:122:18:122:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url |
| test_http_client.py:1:26:1:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember |
-| test_http_client.py:1:26:1:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember |
-| test_http_client.py:1:26:1:32 | GSSA Variable request | semmle.label | GSSA Variable request |
| test_http_client.py:1:26:1:32 | GSSA Variable request | semmle.label | GSSA Variable request |
| test_http_client.py:9:5:9:15 | SSA variable unsafe_host | semmle.label | SSA variable unsafe_host |
-| test_http_client.py:9:5:9:15 | SSA variable unsafe_host | semmle.label | SSA variable unsafe_host |
-| test_http_client.py:9:19:9:25 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| test_http_client.py:9:19:9:25 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| test_http_client.py:10:5:10:15 | SSA variable unsafe_path | semmle.label | SSA variable unsafe_path |
-| test_http_client.py:10:5:10:15 | SSA variable unsafe_path | semmle.label | SSA variable unsafe_path |
-| test_http_client.py:10:19:10:25 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| test_http_client.py:10:19:10:25 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| test_http_client.py:11:5:11:14 | SSA variable user_input | semmle.label | SSA variable user_input |
| test_http_client.py:11:18:11:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| test_http_client.py:13:27:13:37 | ControlFlowNode for unsafe_host | semmle.label | ControlFlowNode for unsafe_host |
-| test_http_client.py:13:27:13:37 | ControlFlowNode for unsafe_host | semmle.label | ControlFlowNode for unsafe_host |
-| test_http_client.py:14:25:14:35 | ControlFlowNode for unsafe_path | semmle.label | ControlFlowNode for unsafe_path |
| test_http_client.py:14:25:14:35 | ControlFlowNode for unsafe_path | semmle.label | ControlFlowNode for unsafe_path |
| test_http_client.py:18:27:18:37 | ControlFlowNode for unsafe_host | semmle.label | ControlFlowNode for unsafe_host |
-| test_http_client.py:18:27:18:37 | ControlFlowNode for unsafe_host | semmle.label | ControlFlowNode for unsafe_host |
-| test_http_client.py:19:25:19:35 | ControlFlowNode for unsafe_path | semmle.label | ControlFlowNode for unsafe_path |
| test_http_client.py:19:25:19:35 | ControlFlowNode for unsafe_path | semmle.label | ControlFlowNode for unsafe_path |
| test_http_client.py:25:27:25:37 | ControlFlowNode for unsafe_host | semmle.label | ControlFlowNode for unsafe_host |
-| test_http_client.py:25:27:25:37 | ControlFlowNode for unsafe_host | semmle.label | ControlFlowNode for unsafe_host |
-| test_http_client.py:29:25:29:35 | ControlFlowNode for unsafe_path | semmle.label | ControlFlowNode for unsafe_path |
| test_http_client.py:29:25:29:35 | ControlFlowNode for unsafe_path | semmle.label | ControlFlowNode for unsafe_path |
| test_http_client.py:31:5:31:8 | SSA variable path | semmle.label | SSA variable path |
| test_http_client.py:33:25:33:28 | ControlFlowNode for path | semmle.label | ControlFlowNode for path |
| test_http_client.py:35:5:35:8 | SSA variable path | semmle.label | SSA variable path |
| test_http_client.py:37:25:37:28 | ControlFlowNode for path | semmle.label | ControlFlowNode for path |
| test_requests.py:1:19:1:25 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember |
-| test_requests.py:1:19:1:25 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember |
-| test_requests.py:1:19:1:25 | GSSA Variable request | semmle.label | GSSA Variable request |
| test_requests.py:1:19:1:25 | GSSA Variable request | semmle.label | GSSA Variable request |
| test_requests.py:6:5:6:14 | SSA variable user_input | semmle.label | SSA variable user_input |
-| test_requests.py:6:5:6:14 | SSA variable user_input | semmle.label | SSA variable user_input |
| test_requests.py:6:18:6:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
-| test_requests.py:6:18:6:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
-| test_requests.py:8:18:8:27 | ControlFlowNode for user_input | semmle.label | ControlFlowNode for user_input |
| test_requests.py:8:18:8:27 | ControlFlowNode for user_input | semmle.label | ControlFlowNode for user_input |
subpaths
#select
From acde1920e7930f9a41469ba2a2bc43e82df5f95b Mon Sep 17 00:00:00 2001
From: Rasmus Wriedt Larsen
Date: Fri, 25 Aug 2023 16:45:25 +0200
Subject: [PATCH 106/788] Python: Move `UntrustedDataToExternalAPI` to new
dataflow API
---
.../CWE-020-ExternalAPIs/ExternalAPIs.qll | 23 ++++++++++++++-----
.../UntrustedDataToExternalAPI.ql | 6 ++---
2 files changed, 20 insertions(+), 9 deletions(-)
diff --git a/python/ql/src/Security/CWE-020-ExternalAPIs/ExternalAPIs.qll b/python/ql/src/Security/CWE-020-ExternalAPIs/ExternalAPIs.qll
index 766cf6845af..82e3c3121d0 100644
--- a/python/ql/src/Security/CWE-020-ExternalAPIs/ExternalAPIs.qll
+++ b/python/ql/src/Security/CWE-020-ExternalAPIs/ExternalAPIs.qll
@@ -167,8 +167,12 @@ class ExternalApiDataNode extends DataFlow::Node {
}
}
-/** A configuration for tracking flow from `RemoteFlowSource`s to `ExternalApiDataNode`s. */
-class UntrustedDataToExternalApiConfig extends TaintTracking::Configuration {
+/**
+ * DEPRECATED: Use `XmlBombFlow` module instead.
+ *
+ * A configuration for tracking flow from `RemoteFlowSource`s to `ExternalApiDataNode`s.
+ */
+deprecated class UntrustedDataToExternalApiConfig extends TaintTracking::Configuration {
UntrustedDataToExternalApiConfig() { this = "UntrustedDataToExternalAPIConfig" }
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
@@ -176,14 +180,21 @@ class UntrustedDataToExternalApiConfig extends TaintTracking::Configuration {
override predicate isSink(DataFlow::Node sink) { sink instanceof ExternalApiDataNode }
}
+private module UntrustedDataToExternalApiConfig implements DataFlow::ConfigSig {
+ predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
+
+ predicate isSink(DataFlow::Node sink) { sink instanceof ExternalApiDataNode }
+}
+
+/** Global taint-tracking from `RemoteFlowSource`s to `ExternalApiDataNode`s. */
+module UntrustedDataToExternalApiFlow = TaintTracking::Global;
+
/** A node representing untrusted data being passed to an external API. */
class UntrustedExternalApiDataNode extends ExternalApiDataNode {
- UntrustedExternalApiDataNode() { any(UntrustedDataToExternalApiConfig c).hasFlow(_, this) }
+ UntrustedExternalApiDataNode() { UntrustedDataToExternalApiFlow::flow(_, this) }
/** Gets a source of untrusted data which is passed to this external API data node. */
- DataFlow::Node getAnUntrustedSource() {
- any(UntrustedDataToExternalApiConfig c).hasFlow(result, this)
- }
+ DataFlow::Node getAnUntrustedSource() { UntrustedDataToExternalApiFlow::flow(result, this) }
}
/** An external API which is used with untrusted data. */
diff --git a/python/ql/src/Security/CWE-020-ExternalAPIs/UntrustedDataToExternalAPI.ql b/python/ql/src/Security/CWE-020-ExternalAPIs/UntrustedDataToExternalAPI.ql
index 6426854222c..f5706ccc3a6 100644
--- a/python/ql/src/Security/CWE-020-ExternalAPIs/UntrustedDataToExternalAPI.ql
+++ b/python/ql/src/Security/CWE-020-ExternalAPIs/UntrustedDataToExternalAPI.ql
@@ -11,14 +11,14 @@
import python
import ExternalAPIs
-import DataFlow::PathGraph
+import UntrustedDataToExternalApiFlow::PathGraph
from
- UntrustedDataToExternalApiConfig config, DataFlow::PathNode source, DataFlow::PathNode sink,
+ UntrustedDataToExternalApiFlow::PathNode source, UntrustedDataToExternalApiFlow::PathNode sink,
ExternalApiUsedWithUntrustedData externalApi
where
sink.getNode() = externalApi.getUntrustedDataNode() and
- config.hasFlowPath(source, sink)
+ UntrustedDataToExternalApiFlow::flowPath(source, sink)
select sink.getNode(), source, sink,
"Call to " + externalApi.toString() + " with untrusted data from $@.", source.getNode(),
source.toString()
From 3edb9d1011fb6e8882740daf640650a66adc66b9 Mon Sep 17 00:00:00 2001
From: Rasmus Wriedt Larsen
Date: Fri, 25 Aug 2023 17:14:21 +0200
Subject: [PATCH 107/788] Python: Move experimental `TokenBuiltFromUUID` to new
dataflow API
---
.../Security/CWE-340/TokenBuiltFromUUID.ql | 20 ++++++++++---------
1 file changed, 11 insertions(+), 9 deletions(-)
diff --git a/python/ql/src/experimental/Security/CWE-340/TokenBuiltFromUUID.ql b/python/ql/src/experimental/Security/CWE-340/TokenBuiltFromUUID.ql
index 711abdb2f33..e4310a68e8f 100644
--- a/python/ql/src/experimental/Security/CWE-340/TokenBuiltFromUUID.ql
+++ b/python/ql/src/experimental/Security/CWE-340/TokenBuiltFromUUID.ql
@@ -16,7 +16,6 @@ import python
import semmle.python.dataflow.new.DataFlow
import semmle.python.ApiGraphs
import semmle.python.dataflow.new.TaintTracking
-import DataFlow::PathGraph
class PredictableResultSource extends DataFlow::Node {
PredictableResultSource() {
@@ -40,14 +39,12 @@ class TokenAssignmentValueSink extends DataFlow::Node {
}
}
-class TokenBuiltFromUuidConfig extends TaintTracking::Configuration {
- TokenBuiltFromUuidConfig() { this = "TokenBuiltFromUuidConfig" }
+private module TokenBuiltFromUUIDConfig implements DataFlow::ConfigSig {
+ predicate isSource(DataFlow::Node source) { source instanceof PredictableResultSource }
- override predicate isSource(DataFlow::Node source) { source instanceof PredictableResultSource }
+ predicate isSink(DataFlow::Node sink) { sink instanceof TokenAssignmentValueSink }
- override predicate isSink(DataFlow::Node sink) { sink instanceof TokenAssignmentValueSink }
-
- override predicate isAdditionalTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
+ predicate isAdditionalFlowStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
exists(DataFlow::CallCfgNode call |
call = API::builtin("str").getACall() and
nodeFrom = call.getArg(0) and
@@ -56,6 +53,11 @@ class TokenBuiltFromUuidConfig extends TaintTracking::Configuration {
}
}
-from DataFlow::PathNode source, DataFlow::PathNode sink, TokenBuiltFromUuidConfig config
-where config.hasFlowPath(source, sink)
+/** Global taint-tracking for detecting "TokenBuiltFromUUID" vulnerabilities. */
+module TokenBuiltFromUUIDFlow = TaintTracking::Global;
+
+import TokenBuiltFromUUIDFlow::PathGraph
+
+from TokenBuiltFromUUIDFlow::PathNode source, TokenBuiltFromUUIDFlow::PathNode sink
+where TokenBuiltFromUUIDFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "Token built from $@.", source.getNode(), "predictable value"
From 3cdd875e9fc773d50d445a56de610657a9f0731a Mon Sep 17 00:00:00 2001
From: Rasmus Wriedt Larsen
Date: Fri, 25 Aug 2023 17:23:50 +0200
Subject: [PATCH 108/788] Python: Move experimental `UnsafeUnpack` to new
dataflow API
---
.../Security/CWE-022bis/UnsafeUnpack.ql | 6 +-
.../Security/UnsafeUnpackQuery.qll | 13 +-
.../UnsafeUnpack.expected | 126 +++++++++++++++---
3 files changed, 117 insertions(+), 28 deletions(-)
diff --git a/python/ql/src/experimental/Security/CWE-022bis/UnsafeUnpack.ql b/python/ql/src/experimental/Security/CWE-022bis/UnsafeUnpack.ql
index a6a0e06559c..1afe3f738ad 100644
--- a/python/ql/src/experimental/Security/CWE-022bis/UnsafeUnpack.ql
+++ b/python/ql/src/experimental/Security/CWE-022bis/UnsafeUnpack.ql
@@ -16,9 +16,9 @@
import python
import experimental.Security.UnsafeUnpackQuery
-import DataFlow::PathGraph
+import UnsafeUnpackFlow::PathGraph
-from UnsafeUnpackingConfig config, DataFlow::PathNode source, DataFlow::PathNode sink
-where config.hasFlowPath(source, sink)
+from UnsafeUnpackFlow::PathNode source, UnsafeUnpackFlow::PathNode sink
+where UnsafeUnpackFlow::flowPath(source, sink)
select sink.getNode(), source, sink,
"Unsafe extraction from a malicious tarball retrieved from a remote location."
diff --git a/python/ql/src/experimental/Security/UnsafeUnpackQuery.qll b/python/ql/src/experimental/Security/UnsafeUnpackQuery.qll
index ba359ee32f3..7c297d975a4 100644
--- a/python/ql/src/experimental/Security/UnsafeUnpackQuery.qll
+++ b/python/ql/src/experimental/Security/UnsafeUnpackQuery.qll
@@ -39,10 +39,8 @@ class AllTarfileOpens extends API::CallNode {
}
}
-class UnsafeUnpackingConfig extends TaintTracking::Configuration {
- UnsafeUnpackingConfig() { this = "UnsafeUnpackingConfig" }
-
- override predicate isSource(DataFlow::Node source) {
+private module UnsafeUnpackConfig implements DataFlow::ConfigSig {
+ predicate isSource(DataFlow::Node source) {
// A source coming from a remote location
source instanceof RemoteFlowSource
or
@@ -92,7 +90,7 @@ class UnsafeUnpackingConfig extends TaintTracking::Configuration {
source.(AttrRead).getAttributeName() = "FILES"
}
- override predicate isSink(DataFlow::Node sink) {
+ predicate isSink(DataFlow::Node sink) {
(
// A sink capturing method calls to `unpack_archive`.
sink = API::moduleImport("shutil").getMember("unpack_archive").getACall().getArg(0)
@@ -136,7 +134,7 @@ class UnsafeUnpackingConfig extends TaintTracking::Configuration {
not sink.getScope().getLocation().getFile().inStdlib()
}
- override predicate isAdditionalTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
+ predicate isAdditionalFlowStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
// Reading the response
nodeTo.(MethodCallNode).calls(nodeFrom, "read")
or
@@ -211,3 +209,6 @@ class UnsafeUnpackingConfig extends TaintTracking::Configuration {
)
}
}
+
+/** Global taint-tracking for detecting "UnsafeUnpacking" vulnerabilities. */
+module UnsafeUnpackFlow = TaintTracking::Global;
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-022-UnsafeUnpacking/UnsafeUnpack.expected b/python/ql/test/experimental/query-tests/Security/CWE-022-UnsafeUnpacking/UnsafeUnpack.expected
index b05f536c26d..f8921911e4f 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-022-UnsafeUnpacking/UnsafeUnpack.expected
+++ b/python/ql/test/experimental/query-tests/Security/CWE-022-UnsafeUnpacking/UnsafeUnpack.expected
@@ -1,43 +1,86 @@
edges
| UnsafeUnpack.py:5:26:5:32 | ControlFlowNode for ImportMember | UnsafeUnpack.py:5:26:5:32 | GSSA Variable request |
| UnsafeUnpack.py:5:26:5:32 | GSSA Variable request | UnsafeUnpack.py:11:18:11:24 | ControlFlowNode for request |
-| UnsafeUnpack.py:11:7:11:14 | SSA variable filename | UnsafeUnpack.py:13:13:13:20 | SSA variable response |
-| UnsafeUnpack.py:11:18:11:24 | ControlFlowNode for request | UnsafeUnpack.py:11:7:11:14 | SSA variable filename |
+| UnsafeUnpack.py:11:7:11:14 | SSA variable filename | UnsafeUnpack.py:13:24:13:58 | ControlFlowNode for Attribute() |
| UnsafeUnpack.py:11:18:11:24 | ControlFlowNode for request | UnsafeUnpack.py:11:18:11:29 | ControlFlowNode for Attribute |
| UnsafeUnpack.py:11:18:11:29 | ControlFlowNode for Attribute | UnsafeUnpack.py:11:18:11:49 | ControlFlowNode for Attribute() |
| UnsafeUnpack.py:11:18:11:49 | ControlFlowNode for Attribute() | UnsafeUnpack.py:11:7:11:14 | SSA variable filename |
-| UnsafeUnpack.py:13:13:13:20 | SSA variable response | UnsafeUnpack.py:19:35:19:41 | ControlFlowNode for tarpath |
+| UnsafeUnpack.py:13:13:13:20 | SSA variable response | UnsafeUnpack.py:17:27:17:34 | ControlFlowNode for response |
+| UnsafeUnpack.py:13:24:13:58 | ControlFlowNode for Attribute() | UnsafeUnpack.py:13:13:13:20 | SSA variable response |
+| UnsafeUnpack.py:16:23:16:29 | ControlFlowNode for tarpath | UnsafeUnpack.py:19:35:19:41 | ControlFlowNode for tarpath |
+| UnsafeUnpack.py:17:19:17:19 | ControlFlowNode for f | UnsafeUnpack.py:16:23:16:29 | ControlFlowNode for tarpath |
+| UnsafeUnpack.py:17:27:17:34 | ControlFlowNode for response | UnsafeUnpack.py:17:27:17:38 | ControlFlowNode for Attribute |
+| UnsafeUnpack.py:17:27:17:38 | ControlFlowNode for Attribute | UnsafeUnpack.py:17:27:17:45 | ControlFlowNode for Attribute() |
+| UnsafeUnpack.py:17:27:17:45 | ControlFlowNode for Attribute() | UnsafeUnpack.py:17:19:17:19 | ControlFlowNode for f |
| UnsafeUnpack.py:33:50:33:65 | ControlFlowNode for local_ziped_path | UnsafeUnpack.py:34:23:34:38 | ControlFlowNode for local_ziped_path |
| UnsafeUnpack.py:47:20:47:34 | ControlFlowNode for compressed_file | UnsafeUnpack.py:48:23:48:37 | ControlFlowNode for compressed_file |
| UnsafeUnpack.py:51:1:51:15 | GSSA Variable compressed_file | UnsafeUnpack.py:52:23:52:37 | ControlFlowNode for compressed_file |
| UnsafeUnpack.py:51:19:51:36 | ControlFlowNode for Attribute() | UnsafeUnpack.py:51:1:51:15 | GSSA Variable compressed_file |
| UnsafeUnpack.py:65:1:65:15 | GSSA Variable compressed_file | UnsafeUnpack.py:66:23:66:37 | ControlFlowNode for compressed_file |
| UnsafeUnpack.py:65:19:65:31 | ControlFlowNode for Attribute | UnsafeUnpack.py:65:1:65:15 | GSSA Variable compressed_file |
-| UnsafeUnpack.py:79:1:79:12 | GSSA Variable url_filename | UnsafeUnpack.py:81:1:81:8 | GSSA Variable response |
-| UnsafeUnpack.py:79:1:79:12 | GSSA Variable url_filename | UnsafeUnpack.py:171:1:171:8 | GSSA Variable response |
+| UnsafeUnpack.py:79:1:79:12 | GSSA Variable url_filename | UnsafeUnpack.py:81:12:81:50 | ControlFlowNode for Attribute() |
+| UnsafeUnpack.py:79:1:79:12 | GSSA Variable url_filename | UnsafeUnpack.py:171:12:171:50 | ControlFlowNode for Attribute() |
| UnsafeUnpack.py:79:16:79:28 | ControlFlowNode for Attribute | UnsafeUnpack.py:79:1:79:12 | GSSA Variable url_filename |
-| UnsafeUnpack.py:81:1:81:8 | GSSA Variable response | UnsafeUnpack.py:87:23:87:29 | ControlFlowNode for tarpath |
-| UnsafeUnpack.py:103:23:103:27 | SSA variable chunk | UnsafeUnpack.py:105:35:105:42 | ControlFlowNode for savepath |
-| UnsafeUnpack.py:103:32:103:44 | ControlFlowNode for Attribute | UnsafeUnpack.py:103:23:103:27 | SSA variable chunk |
-| UnsafeUnpack.py:108:13:108:18 | SSA variable myfile | UnsafeUnpack.py:112:35:112:43 | ControlFlowNode for file_path |
-| UnsafeUnpack.py:108:22:108:34 | ControlFlowNode for Attribute | UnsafeUnpack.py:108:13:108:18 | SSA variable myfile |
+| UnsafeUnpack.py:81:1:81:8 | GSSA Variable response | UnsafeUnpack.py:85:15:85:22 | ControlFlowNode for response |
+| UnsafeUnpack.py:81:12:81:50 | ControlFlowNode for Attribute() | UnsafeUnpack.py:81:1:81:8 | GSSA Variable response |
+| UnsafeUnpack.py:84:11:84:17 | ControlFlowNode for tarpath | UnsafeUnpack.py:87:23:87:29 | ControlFlowNode for tarpath |
+| UnsafeUnpack.py:85:7:85:7 | ControlFlowNode for f | UnsafeUnpack.py:84:11:84:17 | ControlFlowNode for tarpath |
+| UnsafeUnpack.py:85:15:85:22 | ControlFlowNode for response | UnsafeUnpack.py:85:15:85:26 | ControlFlowNode for Attribute |
+| UnsafeUnpack.py:85:15:85:26 | ControlFlowNode for Attribute | UnsafeUnpack.py:85:15:85:33 | ControlFlowNode for Attribute() |
+| UnsafeUnpack.py:85:15:85:33 | ControlFlowNode for Attribute() | UnsafeUnpack.py:85:7:85:7 | ControlFlowNode for f |
+| UnsafeUnpack.py:102:23:102:30 | ControlFlowNode for savepath | UnsafeUnpack.py:105:35:105:42 | ControlFlowNode for savepath |
+| UnsafeUnpack.py:103:23:103:27 | SSA variable chunk | UnsafeUnpack.py:104:37:104:41 | ControlFlowNode for chunk |
+| UnsafeUnpack.py:103:32:103:44 | ControlFlowNode for Attribute | UnsafeUnpack.py:103:32:103:54 | ControlFlowNode for Subscript |
+| UnsafeUnpack.py:103:32:103:54 | ControlFlowNode for Subscript | UnsafeUnpack.py:103:32:103:63 | ControlFlowNode for Attribute() |
+| UnsafeUnpack.py:103:32:103:63 | ControlFlowNode for Attribute() | UnsafeUnpack.py:103:23:103:27 | SSA variable chunk |
+| UnsafeUnpack.py:104:25:104:29 | ControlFlowNode for wfile | UnsafeUnpack.py:102:23:102:30 | ControlFlowNode for savepath |
+| UnsafeUnpack.py:104:37:104:41 | ControlFlowNode for chunk | UnsafeUnpack.py:104:25:104:29 | ControlFlowNode for wfile |
+| UnsafeUnpack.py:108:13:108:18 | SSA variable myfile | UnsafeUnpack.py:111:27:111:32 | ControlFlowNode for myfile |
| UnsafeUnpack.py:108:22:108:34 | ControlFlowNode for Attribute | UnsafeUnpack.py:108:22:108:48 | ControlFlowNode for Attribute() |
| UnsafeUnpack.py:108:22:108:48 | ControlFlowNode for Attribute() | UnsafeUnpack.py:108:13:108:18 | SSA variable myfile |
-| UnsafeUnpack.py:116:17:116:21 | SSA variable ufile | UnsafeUnpack.py:118:19:118:26 | SSA variable filename |
-| UnsafeUnpack.py:116:27:116:39 | ControlFlowNode for Attribute | UnsafeUnpack.py:116:17:116:21 | SSA variable ufile |
-| UnsafeUnpack.py:118:19:118:26 | SSA variable filename | UnsafeUnpack.py:119:19:119:36 | SSA variable uploaded_file_path |
+| UnsafeUnpack.py:110:18:110:26 | ControlFlowNode for file_path | UnsafeUnpack.py:112:35:112:43 | ControlFlowNode for file_path |
+| UnsafeUnpack.py:111:19:111:19 | ControlFlowNode for f | UnsafeUnpack.py:110:18:110:26 | ControlFlowNode for file_path |
+| UnsafeUnpack.py:111:27:111:32 | ControlFlowNode for myfile | UnsafeUnpack.py:111:27:111:39 | ControlFlowNode for Attribute() |
+| UnsafeUnpack.py:111:27:111:39 | ControlFlowNode for Attribute() | UnsafeUnpack.py:111:19:111:19 | ControlFlowNode for f |
+| UnsafeUnpack.py:116:17:116:21 | SSA variable ufile | UnsafeUnpack.py:118:38:118:42 | ControlFlowNode for ufile |
+| UnsafeUnpack.py:116:27:116:39 | ControlFlowNode for Attribute | UnsafeUnpack.py:116:27:116:49 | ControlFlowNode for Attribute() |
+| UnsafeUnpack.py:116:27:116:49 | ControlFlowNode for Attribute() | UnsafeUnpack.py:116:17:116:21 | SSA variable ufile |
+| UnsafeUnpack.py:118:19:118:26 | SSA variable filename | UnsafeUnpack.py:119:48:119:55 | ControlFlowNode for filename |
+| UnsafeUnpack.py:118:30:118:55 | ControlFlowNode for Attribute() | UnsafeUnpack.py:118:19:118:26 | SSA variable filename |
+| UnsafeUnpack.py:118:38:118:42 | ControlFlowNode for ufile | UnsafeUnpack.py:118:38:118:47 | ControlFlowNode for Attribute |
+| UnsafeUnpack.py:118:38:118:47 | ControlFlowNode for Attribute | UnsafeUnpack.py:118:30:118:55 | ControlFlowNode for Attribute() |
| UnsafeUnpack.py:119:19:119:36 | SSA variable uploaded_file_path | UnsafeUnpack.py:120:41:120:58 | ControlFlowNode for uploaded_file_path |
-| UnsafeUnpack.py:140:1:140:19 | GSSA Variable unsafe_filename_tar | UnsafeUnpack.py:141:56:141:58 | GSSA Variable tar |
+| UnsafeUnpack.py:119:40:119:56 | ControlFlowNode for Attribute() | UnsafeUnpack.py:119:19:119:36 | SSA variable uploaded_file_path |
+| UnsafeUnpack.py:119:48:119:55 | ControlFlowNode for filename | UnsafeUnpack.py:119:40:119:56 | ControlFlowNode for Attribute() |
+| UnsafeUnpack.py:140:1:140:19 | GSSA Variable unsafe_filename_tar | UnsafeUnpack.py:141:22:141:40 | ControlFlowNode for unsafe_filename_tar |
| UnsafeUnpack.py:140:23:140:35 | ControlFlowNode for Attribute | UnsafeUnpack.py:140:1:140:19 | GSSA Variable unsafe_filename_tar |
+| UnsafeUnpack.py:141:6:141:51 | ControlFlowNode for Attribute() | UnsafeUnpack.py:141:56:141:58 | GSSA Variable tar |
+| UnsafeUnpack.py:141:22:141:40 | ControlFlowNode for unsafe_filename_tar | UnsafeUnpack.py:141:6:141:51 | ControlFlowNode for Attribute() |
| UnsafeUnpack.py:141:56:141:58 | GSSA Variable tar | UnsafeUnpack.py:142:49:142:51 | ControlFlowNode for tar |
-| UnsafeUnpack.py:158:23:158:27 | SSA variable chunk | UnsafeUnpack.py:161:19:161:21 | SSA variable tar |
-| UnsafeUnpack.py:158:32:158:44 | ControlFlowNode for Attribute | UnsafeUnpack.py:158:23:158:27 | SSA variable chunk |
-| UnsafeUnpack.py:161:19:161:21 | SSA variable tar | UnsafeUnpack.py:163:23:163:28 | SSA variable member |
+| UnsafeUnpack.py:157:23:157:30 | ControlFlowNode for savepath | UnsafeUnpack.py:161:38:161:45 | ControlFlowNode for savepath |
+| UnsafeUnpack.py:158:23:158:27 | SSA variable chunk | UnsafeUnpack.py:159:37:159:41 | ControlFlowNode for chunk |
+| UnsafeUnpack.py:158:32:158:44 | ControlFlowNode for Attribute | UnsafeUnpack.py:158:32:158:54 | ControlFlowNode for Subscript |
+| UnsafeUnpack.py:158:32:158:54 | ControlFlowNode for Subscript | UnsafeUnpack.py:158:32:158:63 | ControlFlowNode for Attribute() |
+| UnsafeUnpack.py:158:32:158:63 | ControlFlowNode for Attribute() | UnsafeUnpack.py:158:23:158:27 | SSA variable chunk |
+| UnsafeUnpack.py:159:25:159:29 | ControlFlowNode for wfile | UnsafeUnpack.py:157:23:157:30 | ControlFlowNode for savepath |
+| UnsafeUnpack.py:159:37:159:41 | ControlFlowNode for chunk | UnsafeUnpack.py:159:25:159:29 | ControlFlowNode for wfile |
+| UnsafeUnpack.py:161:19:161:21 | SSA variable tar | UnsafeUnpack.py:163:33:163:35 | ControlFlowNode for tar |
+| UnsafeUnpack.py:161:25:161:46 | ControlFlowNode for Attribute() | UnsafeUnpack.py:161:19:161:21 | SSA variable tar |
+| UnsafeUnpack.py:161:38:161:45 | ControlFlowNode for savepath | UnsafeUnpack.py:161:25:161:46 | ControlFlowNode for Attribute() |
| UnsafeUnpack.py:163:23:163:28 | SSA variable member | UnsafeUnpack.py:166:37:166:42 | ControlFlowNode for member |
+| UnsafeUnpack.py:163:33:163:35 | ControlFlowNode for tar | UnsafeUnpack.py:163:23:163:28 | SSA variable member |
| UnsafeUnpack.py:166:23:166:28 | [post] ControlFlowNode for result | UnsafeUnpack.py:167:67:167:72 | ControlFlowNode for result |
| UnsafeUnpack.py:166:37:166:42 | ControlFlowNode for member | UnsafeUnpack.py:166:23:166:28 | [post] ControlFlowNode for result |
-| UnsafeUnpack.py:171:1:171:8 | GSSA Variable response | UnsafeUnpack.py:176:1:176:34 | ControlFlowNode for Attribute() |
-| UnsafeUnpack.py:194:53:194:55 | ControlFlowNode for tmp | UnsafeUnpack.py:201:29:201:36 | ControlFlowNode for Attribute |
+| UnsafeUnpack.py:171:1:171:8 | GSSA Variable response | UnsafeUnpack.py:174:15:174:22 | ControlFlowNode for response |
+| UnsafeUnpack.py:171:12:171:50 | ControlFlowNode for Attribute() | UnsafeUnpack.py:171:1:171:8 | GSSA Variable response |
+| UnsafeUnpack.py:173:11:173:17 | ControlFlowNode for tarpath | UnsafeUnpack.py:176:17:176:23 | ControlFlowNode for tarpath |
+| UnsafeUnpack.py:174:7:174:7 | ControlFlowNode for f | UnsafeUnpack.py:173:11:173:17 | ControlFlowNode for tarpath |
+| UnsafeUnpack.py:174:15:174:22 | ControlFlowNode for response | UnsafeUnpack.py:174:15:174:26 | ControlFlowNode for Attribute |
+| UnsafeUnpack.py:174:15:174:26 | ControlFlowNode for Attribute | UnsafeUnpack.py:174:15:174:33 | ControlFlowNode for Attribute() |
+| UnsafeUnpack.py:174:15:174:33 | ControlFlowNode for Attribute() | UnsafeUnpack.py:174:7:174:7 | ControlFlowNode for f |
+| UnsafeUnpack.py:176:17:176:23 | ControlFlowNode for tarpath | UnsafeUnpack.py:176:1:176:34 | ControlFlowNode for Attribute() |
+| UnsafeUnpack.py:194:53:194:55 | ControlFlowNode for tmp | UnsafeUnpack.py:201:29:201:31 | ControlFlowNode for tmp |
+| UnsafeUnpack.py:201:29:201:31 | ControlFlowNode for tmp | UnsafeUnpack.py:201:29:201:36 | ControlFlowNode for Attribute |
nodes
| UnsafeUnpack.py:5:26:5:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember |
| UnsafeUnpack.py:5:26:5:32 | GSSA Variable request | semmle.label | GSSA Variable request |
@@ -46,6 +89,12 @@ nodes
| UnsafeUnpack.py:11:18:11:29 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| UnsafeUnpack.py:11:18:11:49 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| UnsafeUnpack.py:13:13:13:20 | SSA variable response | semmle.label | SSA variable response |
+| UnsafeUnpack.py:13:24:13:58 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
+| UnsafeUnpack.py:16:23:16:29 | ControlFlowNode for tarpath | semmle.label | ControlFlowNode for tarpath |
+| UnsafeUnpack.py:17:19:17:19 | ControlFlowNode for f | semmle.label | ControlFlowNode for f |
+| UnsafeUnpack.py:17:27:17:34 | ControlFlowNode for response | semmle.label | ControlFlowNode for response |
+| UnsafeUnpack.py:17:27:17:38 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
+| UnsafeUnpack.py:17:27:17:45 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| UnsafeUnpack.py:19:35:19:41 | ControlFlowNode for tarpath | semmle.label | ControlFlowNode for tarpath |
| UnsafeUnpack.py:33:50:33:65 | ControlFlowNode for local_ziped_path | semmle.label | ControlFlowNode for local_ziped_path |
| UnsafeUnpack.py:34:23:34:38 | ControlFlowNode for local_ziped_path | semmle.label | ControlFlowNode for local_ziped_path |
@@ -60,33 +109,72 @@ nodes
| UnsafeUnpack.py:79:1:79:12 | GSSA Variable url_filename | semmle.label | GSSA Variable url_filename |
| UnsafeUnpack.py:79:16:79:28 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| UnsafeUnpack.py:81:1:81:8 | GSSA Variable response | semmle.label | GSSA Variable response |
+| UnsafeUnpack.py:81:12:81:50 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
+| UnsafeUnpack.py:84:11:84:17 | ControlFlowNode for tarpath | semmle.label | ControlFlowNode for tarpath |
+| UnsafeUnpack.py:85:7:85:7 | ControlFlowNode for f | semmle.label | ControlFlowNode for f |
+| UnsafeUnpack.py:85:15:85:22 | ControlFlowNode for response | semmle.label | ControlFlowNode for response |
+| UnsafeUnpack.py:85:15:85:26 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
+| UnsafeUnpack.py:85:15:85:33 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| UnsafeUnpack.py:87:23:87:29 | ControlFlowNode for tarpath | semmle.label | ControlFlowNode for tarpath |
+| UnsafeUnpack.py:102:23:102:30 | ControlFlowNode for savepath | semmle.label | ControlFlowNode for savepath |
| UnsafeUnpack.py:103:23:103:27 | SSA variable chunk | semmle.label | SSA variable chunk |
| UnsafeUnpack.py:103:32:103:44 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
+| UnsafeUnpack.py:103:32:103:54 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
+| UnsafeUnpack.py:103:32:103:63 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
+| UnsafeUnpack.py:104:25:104:29 | ControlFlowNode for wfile | semmle.label | ControlFlowNode for wfile |
+| UnsafeUnpack.py:104:37:104:41 | ControlFlowNode for chunk | semmle.label | ControlFlowNode for chunk |
| UnsafeUnpack.py:105:35:105:42 | ControlFlowNode for savepath | semmle.label | ControlFlowNode for savepath |
| UnsafeUnpack.py:108:13:108:18 | SSA variable myfile | semmle.label | SSA variable myfile |
| UnsafeUnpack.py:108:22:108:34 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| UnsafeUnpack.py:108:22:108:48 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
+| UnsafeUnpack.py:110:18:110:26 | ControlFlowNode for file_path | semmle.label | ControlFlowNode for file_path |
+| UnsafeUnpack.py:111:19:111:19 | ControlFlowNode for f | semmle.label | ControlFlowNode for f |
+| UnsafeUnpack.py:111:27:111:32 | ControlFlowNode for myfile | semmle.label | ControlFlowNode for myfile |
+| UnsafeUnpack.py:111:27:111:39 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| UnsafeUnpack.py:112:35:112:43 | ControlFlowNode for file_path | semmle.label | ControlFlowNode for file_path |
| UnsafeUnpack.py:116:17:116:21 | SSA variable ufile | semmle.label | SSA variable ufile |
| UnsafeUnpack.py:116:27:116:39 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
+| UnsafeUnpack.py:116:27:116:49 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| UnsafeUnpack.py:118:19:118:26 | SSA variable filename | semmle.label | SSA variable filename |
+| UnsafeUnpack.py:118:30:118:55 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
+| UnsafeUnpack.py:118:38:118:42 | ControlFlowNode for ufile | semmle.label | ControlFlowNode for ufile |
+| UnsafeUnpack.py:118:38:118:47 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| UnsafeUnpack.py:119:19:119:36 | SSA variable uploaded_file_path | semmle.label | SSA variable uploaded_file_path |
+| UnsafeUnpack.py:119:40:119:56 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
+| UnsafeUnpack.py:119:48:119:55 | ControlFlowNode for filename | semmle.label | ControlFlowNode for filename |
| UnsafeUnpack.py:120:41:120:58 | ControlFlowNode for uploaded_file_path | semmle.label | ControlFlowNode for uploaded_file_path |
| UnsafeUnpack.py:140:1:140:19 | GSSA Variable unsafe_filename_tar | semmle.label | GSSA Variable unsafe_filename_tar |
| UnsafeUnpack.py:140:23:140:35 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
+| UnsafeUnpack.py:141:6:141:51 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
+| UnsafeUnpack.py:141:22:141:40 | ControlFlowNode for unsafe_filename_tar | semmle.label | ControlFlowNode for unsafe_filename_tar |
| UnsafeUnpack.py:141:56:141:58 | GSSA Variable tar | semmle.label | GSSA Variable tar |
| UnsafeUnpack.py:142:49:142:51 | ControlFlowNode for tar | semmle.label | ControlFlowNode for tar |
+| UnsafeUnpack.py:157:23:157:30 | ControlFlowNode for savepath | semmle.label | ControlFlowNode for savepath |
| UnsafeUnpack.py:158:23:158:27 | SSA variable chunk | semmle.label | SSA variable chunk |
| UnsafeUnpack.py:158:32:158:44 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
+| UnsafeUnpack.py:158:32:158:54 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
+| UnsafeUnpack.py:158:32:158:63 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
+| UnsafeUnpack.py:159:25:159:29 | ControlFlowNode for wfile | semmle.label | ControlFlowNode for wfile |
+| UnsafeUnpack.py:159:37:159:41 | ControlFlowNode for chunk | semmle.label | ControlFlowNode for chunk |
| UnsafeUnpack.py:161:19:161:21 | SSA variable tar | semmle.label | SSA variable tar |
+| UnsafeUnpack.py:161:25:161:46 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
+| UnsafeUnpack.py:161:38:161:45 | ControlFlowNode for savepath | semmle.label | ControlFlowNode for savepath |
| UnsafeUnpack.py:163:23:163:28 | SSA variable member | semmle.label | SSA variable member |
+| UnsafeUnpack.py:163:33:163:35 | ControlFlowNode for tar | semmle.label | ControlFlowNode for tar |
| UnsafeUnpack.py:166:23:166:28 | [post] ControlFlowNode for result | semmle.label | [post] ControlFlowNode for result |
| UnsafeUnpack.py:166:37:166:42 | ControlFlowNode for member | semmle.label | ControlFlowNode for member |
| UnsafeUnpack.py:167:67:167:72 | ControlFlowNode for result | semmle.label | ControlFlowNode for result |
| UnsafeUnpack.py:171:1:171:8 | GSSA Variable response | semmle.label | GSSA Variable response |
+| UnsafeUnpack.py:171:12:171:50 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
+| UnsafeUnpack.py:173:11:173:17 | ControlFlowNode for tarpath | semmle.label | ControlFlowNode for tarpath |
+| UnsafeUnpack.py:174:7:174:7 | ControlFlowNode for f | semmle.label | ControlFlowNode for f |
+| UnsafeUnpack.py:174:15:174:22 | ControlFlowNode for response | semmle.label | ControlFlowNode for response |
+| UnsafeUnpack.py:174:15:174:26 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
+| UnsafeUnpack.py:174:15:174:33 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| UnsafeUnpack.py:176:1:176:34 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
+| UnsafeUnpack.py:176:17:176:23 | ControlFlowNode for tarpath | semmle.label | ControlFlowNode for tarpath |
| UnsafeUnpack.py:194:53:194:55 | ControlFlowNode for tmp | semmle.label | ControlFlowNode for tmp |
+| UnsafeUnpack.py:201:29:201:31 | ControlFlowNode for tmp | semmle.label | ControlFlowNode for tmp |
| UnsafeUnpack.py:201:29:201:36 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
subpaths
#select
From a0d26741d05c8bfbe7ed668d50518e8850982a9f Mon Sep 17 00:00:00 2001
From: Rasmus Wriedt Larsen
Date: Fri, 25 Aug 2023 17:23:50 +0200
Subject: [PATCH 109/788] Python: Move experimental `TarSlipImprov` to new
dataflow API
---
.../Security/CWE-022bis/TarSlipImprov.ql | 19 ++++++++++---------
.../Security/CWE-022-TarSlip/TarSlip.expected | 4 +++-
2 files changed, 13 insertions(+), 10 deletions(-)
diff --git a/python/ql/src/experimental/Security/CWE-022bis/TarSlipImprov.ql b/python/ql/src/experimental/Security/CWE-022bis/TarSlipImprov.ql
index 65ff272bbbd..431fe293cec 100755
--- a/python/ql/src/experimental/Security/CWE-022bis/TarSlipImprov.ql
+++ b/python/ql/src/experimental/Security/CWE-022bis/TarSlipImprov.ql
@@ -16,7 +16,7 @@
import python
import semmle.python.dataflow.new.DataFlow
import semmle.python.dataflow.new.TaintTracking
-import DataFlow::PathGraph
+import TarSlipImprovFlow::PathGraph
import semmle.python.ApiGraphs
import semmle.python.dataflow.new.internal.Attributes
import semmle.python.dataflow.new.BarrierGuards
@@ -54,12 +54,10 @@ class AllTarfileOpens extends API::CallNode {
/**
* A taint-tracking configuration for detecting more "TarSlip" vulnerabilities.
*/
-class Configuration extends TaintTracking::Configuration {
- Configuration() { this = "TarSlip" }
+private module TarSlipImprovConfig implements DataFlow::ConfigSig {
+ predicate isSource(DataFlow::Node source) { source = tarfileOpen().getACall() }
- override predicate isSource(DataFlow::Node source) { source = tarfileOpen().getACall() }
-
- override predicate isSink(DataFlow::Node sink) {
+ predicate isSink(DataFlow::Node sink) {
(
// A sink capturing method calls to `extractall` without `members` argument.
// For a call to `file.extractall` without `members` argument, `file` is considered a sink.
@@ -100,7 +98,7 @@ class Configuration extends TaintTracking::Configuration {
not sink.getScope().getLocation().getFile().inStdlib()
}
- override predicate isAdditionalTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
+ predicate isAdditionalFlowStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
nodeTo.(MethodCallNode).calls(nodeFrom, "getmembers") and
nodeFrom instanceof AllTarfileOpens
or
@@ -113,7 +111,10 @@ class Configuration extends TaintTracking::Configuration {
}
}
-from Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink
-where config.hasFlowPath(source, sink)
+/** Global taint-tracking for detecting more "TarSlip" vulnerabilities. */
+module TarSlipImprovFlow = TaintTracking::Global;
+
+from TarSlipImprovFlow::PathNode source, TarSlipImprovFlow::PathNode sink
+where TarSlipImprovFlow::flowPath(source, sink)
select sink, source, sink, "Extraction of tarfile from $@ to a potentially untrusted source $@.",
source.getNode(), source.getNode().toString(), sink.getNode(), sink.getNode().toString()
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-022-TarSlip/TarSlip.expected b/python/ql/test/experimental/query-tests/Security/CWE-022-TarSlip/TarSlip.expected
index 52fd49e57b1..a699a1bac5f 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-022-TarSlip/TarSlip.expected
+++ b/python/ql/test/experimental/query-tests/Security/CWE-022-TarSlip/TarSlip.expected
@@ -33,7 +33,8 @@ edges
| TarSlipImprov.py:141:34:141:36 | GSSA Variable tar | TarSlipImprov.py:142:9:142:13 | GSSA Variable entry |
| TarSlipImprov.py:142:9:142:13 | GSSA Variable entry | TarSlipImprov.py:143:36:143:40 | ControlFlowNode for entry |
| TarSlipImprov.py:159:9:159:14 | SSA variable tar_cm | TarSlipImprov.py:162:20:162:23 | SSA variable tarc |
-| TarSlipImprov.py:159:26:159:51 | ControlFlowNode for Attribute() | TarSlipImprov.py:159:9:159:14 | SSA variable tar_cm |
+| TarSlipImprov.py:159:18:159:52 | ControlFlowNode for closing() | TarSlipImprov.py:159:9:159:14 | SSA variable tar_cm |
+| TarSlipImprov.py:159:26:159:51 | ControlFlowNode for Attribute() | TarSlipImprov.py:159:18:159:52 | ControlFlowNode for closing() |
| TarSlipImprov.py:162:20:162:23 | SSA variable tarc | TarSlipImprov.py:169:9:169:12 | ControlFlowNode for tarc |
| TarSlipImprov.py:176:6:176:31 | ControlFlowNode for Attribute() | TarSlipImprov.py:176:36:176:38 | GSSA Variable tar |
| TarSlipImprov.py:176:36:176:38 | GSSA Variable tar | TarSlipImprov.py:177:9:177:13 | GSSA Variable entry |
@@ -122,6 +123,7 @@ nodes
| TarSlipImprov.py:142:9:142:13 | GSSA Variable entry | semmle.label | GSSA Variable entry |
| TarSlipImprov.py:143:36:143:40 | ControlFlowNode for entry | semmle.label | ControlFlowNode for entry |
| TarSlipImprov.py:159:9:159:14 | SSA variable tar_cm | semmle.label | SSA variable tar_cm |
+| TarSlipImprov.py:159:18:159:52 | ControlFlowNode for closing() | semmle.label | ControlFlowNode for closing() |
| TarSlipImprov.py:159:26:159:51 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| TarSlipImprov.py:162:20:162:23 | SSA variable tarc | semmle.label | SSA variable tarc |
| TarSlipImprov.py:169:9:169:12 | ControlFlowNode for tarc | semmle.label | ControlFlowNode for tarc |
From 67cc3a3935a05e0381ee8374c6cb5b1bc8621b31 Mon Sep 17 00:00:00 2001
From: Rasmus Wriedt Larsen
Date: Fri, 25 Aug 2023 17:23:50 +0200
Subject: [PATCH 110/788] Python: Move experimental `ReflectedXSS` to new
dataflow API
---
.../experimental/Security/CWE-079/ReflectedXSS.ql | 6 +++---
.../python/security/dataflow/ReflectedXSS.qll | 15 ++++++++-------
.../Security/CWE-079/ReflectedXSS.expected | 4 +++-
3 files changed, 14 insertions(+), 11 deletions(-)
diff --git a/python/ql/src/experimental/Security/CWE-079/ReflectedXSS.ql b/python/ql/src/experimental/Security/CWE-079/ReflectedXSS.ql
index 468cef01f7d..1f5cc601c09 100644
--- a/python/ql/src/experimental/Security/CWE-079/ReflectedXSS.ql
+++ b/python/ql/src/experimental/Security/CWE-079/ReflectedXSS.ql
@@ -16,9 +16,9 @@
// determine precision above
import python
import experimental.semmle.python.security.dataflow.ReflectedXSS
-import DataFlow::PathGraph
+import ReflectedXSSFlow::PathGraph
-from ReflectedXssConfiguration config, DataFlow::PathNode source, DataFlow::PathNode sink
-where config.hasFlowPath(source, sink)
+from ReflectedXSSFlow::PathNode source, ReflectedXSSFlow::PathNode sink
+where ReflectedXSSFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "Cross-site scripting vulnerability due to $@.",
source.getNode(), "a user-provided value"
diff --git a/python/ql/src/experimental/semmle/python/security/dataflow/ReflectedXSS.qll b/python/ql/src/experimental/semmle/python/security/dataflow/ReflectedXSS.qll
index b35cb405dc0..b12f54dedf8 100644
--- a/python/ql/src/experimental/semmle/python/security/dataflow/ReflectedXSS.qll
+++ b/python/ql/src/experimental/semmle/python/security/dataflow/ReflectedXSS.qll
@@ -16,20 +16,18 @@ import semmle.python.ApiGraphs
* A taint-tracking configuration for detecting reflected server-side cross-site
* scripting vulnerabilities.
*/
-class ReflectedXssConfiguration extends TaintTracking::Configuration {
- ReflectedXssConfiguration() { this = "ReflectedXssConfiguration" }
+private module ReflectedXSSConfig implements DataFlow::ConfigSig {
+ predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
- override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
+ predicate isSink(DataFlow::Node sink) { sink = any(EmailSender email).getHtmlBody() }
- override predicate isSink(DataFlow::Node sink) { sink = any(EmailSender email).getHtmlBody() }
-
- override predicate isSanitizer(DataFlow::Node sanitizer) {
+ predicate isBarrier(DataFlow::Node sanitizer) {
sanitizer = any(HtmlEscaping esc).getOutput()
or
sanitizer instanceof StringConstCompareBarrier
}
- override predicate isAdditionalTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
+ predicate isAdditionalFlowStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
exists(DataFlow::CallCfgNode htmlContentCall |
htmlContentCall =
API::moduleImport("sendgrid")
@@ -42,3 +40,6 @@ class ReflectedXssConfiguration extends TaintTracking::Configuration {
)
}
}
+
+/** Global taint-tracking for detecting "TODO" vulnerabilities. */
+module ReflectedXSSFlow = TaintTracking::Global;
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-079/ReflectedXSS.expected b/python/ql/test/experimental/query-tests/Security/CWE-079/ReflectedXSS.expected
index 7f16b6dcdac..02fed5424cc 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-079/ReflectedXSS.expected
+++ b/python/ql/test/experimental/query-tests/Security/CWE-079/ReflectedXSS.expected
@@ -12,7 +12,8 @@ edges
| sendgrid_mail.py:1:19:1:25 | GSSA Variable request | sendgrid_mail.py:26:34:26:40 | ControlFlowNode for request |
| sendgrid_mail.py:1:19:1:25 | GSSA Variable request | sendgrid_mail.py:37:41:37:47 | ControlFlowNode for request |
| sendgrid_mail.py:14:22:14:28 | ControlFlowNode for request | sendgrid_mail.py:14:22:14:49 | ControlFlowNode for Subscript |
-| sendgrid_mail.py:26:34:26:40 | ControlFlowNode for request | sendgrid_mail.py:26:22:26:62 | ControlFlowNode for HtmlContent() |
+| sendgrid_mail.py:26:34:26:40 | ControlFlowNode for request | sendgrid_mail.py:26:34:26:61 | ControlFlowNode for Subscript |
+| sendgrid_mail.py:26:34:26:61 | ControlFlowNode for Subscript | sendgrid_mail.py:26:22:26:62 | ControlFlowNode for HtmlContent() |
| sendgrid_mail.py:37:41:37:47 | ControlFlowNode for request | sendgrid_mail.py:37:41:37:68 | ControlFlowNode for Subscript |
| sendgrid_via_mail_send_post_request_body_bad.py:3:19:3:25 | ControlFlowNode for ImportMember | sendgrid_via_mail_send_post_request_body_bad.py:3:19:3:25 | GSSA Variable request |
| sendgrid_via_mail_send_post_request_body_bad.py:3:19:3:25 | GSSA Variable request | sendgrid_via_mail_send_post_request_body_bad.py:16:51:16:57 | ControlFlowNode for request |
@@ -52,6 +53,7 @@ nodes
| sendgrid_mail.py:14:22:14:49 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| sendgrid_mail.py:26:22:26:62 | ControlFlowNode for HtmlContent() | semmle.label | ControlFlowNode for HtmlContent() |
| sendgrid_mail.py:26:34:26:40 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
+| sendgrid_mail.py:26:34:26:61 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| sendgrid_mail.py:37:41:37:47 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| sendgrid_mail.py:37:41:37:68 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| sendgrid_via_mail_send_post_request_body_bad.py:3:19:3:25 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember |
From 5d8329d9c8a62281989a88e4d47ae6b0fcd6d2b2 Mon Sep 17 00:00:00 2001
From: Rasmus Wriedt Larsen
Date: Fri, 25 Aug 2023 17:23:50 +0200
Subject: [PATCH 111/788] Python: Move experimental `ZipSlip` to new dataflow
API
---
.../ql/src/experimental/Security/CWE-022/ZipSlip.ql | 6 +++---
.../experimental/semmle/python/security/ZipSlip.qll | 11 ++++++-----
2 files changed, 9 insertions(+), 8 deletions(-)
diff --git a/python/ql/src/experimental/Security/CWE-022/ZipSlip.ql b/python/ql/src/experimental/Security/CWE-022/ZipSlip.ql
index eba8da087b3..4bdca63e1d6 100644
--- a/python/ql/src/experimental/Security/CWE-022/ZipSlip.ql
+++ b/python/ql/src/experimental/Security/CWE-022/ZipSlip.ql
@@ -15,10 +15,10 @@
import python
import experimental.semmle.python.security.ZipSlip
-import DataFlow::PathGraph
+import ZipSlipFlow::PathGraph
-from ZipSlipConfig config, DataFlow::PathNode source, DataFlow::PathNode sink
-where config.hasFlowPath(source, sink)
+from ZipSlipFlow::PathNode source, ZipSlipFlow::PathNode sink
+where ZipSlipFlow::flowPath(source, sink)
select source.getNode(), source, sink,
"This unsanitized archive entry, which may contain '..', is used in a $@.", sink.getNode(),
"file system operation"
diff --git a/python/ql/src/experimental/semmle/python/security/ZipSlip.qll b/python/ql/src/experimental/semmle/python/security/ZipSlip.qll
index 59f558c67d6..5f8b4d940ef 100644
--- a/python/ql/src/experimental/semmle/python/security/ZipSlip.qll
+++ b/python/ql/src/experimental/semmle/python/security/ZipSlip.qll
@@ -4,10 +4,8 @@ import semmle.python.dataflow.new.DataFlow
import semmle.python.ApiGraphs
import semmle.python.dataflow.new.TaintTracking
-class ZipSlipConfig extends TaintTracking::Configuration {
- ZipSlipConfig() { this = "ZipSlipConfig" }
-
- override predicate isSource(DataFlow::Node source) {
+private module ZipSlipConfig implements DataFlow::ConfigSig {
+ predicate isSource(DataFlow::Node source) {
(
source =
API::moduleImport("zipfile").getMember("ZipFile").getReturn().getMember("open").getACall() or
@@ -29,7 +27,7 @@ class ZipSlipConfig extends TaintTracking::Configuration {
not source.getScope().getLocation().getFile().inStdlib()
}
- override predicate isSink(DataFlow::Node sink) {
+ predicate isSink(DataFlow::Node sink) {
(
sink = any(CopyFile copyfile).getAPathArgument() or
sink = any(CopyFile copyfile).getfsrcArgument()
@@ -37,3 +35,6 @@ class ZipSlipConfig extends TaintTracking::Configuration {
not sink.getScope().getLocation().getFile().inStdlib()
}
}
+
+/** Global taint-tracking for detecting "zip slip" vulnerabilities. */
+module ZipSlipFlow = TaintTracking::Global;
From 5fd3594f5fda5773e889bf6309e6a75f4ad101d3 Mon Sep 17 00:00:00 2001
From: Rasmus Wriedt Larsen
Date: Fri, 25 Aug 2023 22:15:43 +0200
Subject: [PATCH 112/788] Python: Move TimingAttack.qll to new dataflow API
---
.../semmle/python/security/TimingAttack.qll | 43 ++++++++-----------
1 file changed, 19 insertions(+), 24 deletions(-)
diff --git a/python/ql/src/experimental/semmle/python/security/TimingAttack.qll b/python/ql/src/experimental/semmle/python/security/TimingAttack.qll
index 4df7752e64d..37d3a35158d 100644
--- a/python/ql/src/experimental/semmle/python/security/TimingAttack.qll
+++ b/python/ql/src/experimental/semmle/python/security/TimingAttack.qll
@@ -164,9 +164,7 @@ class NonConstantTimeComparisonSink extends DataFlow::Node {
/** Holds if remote user input was used in the comparison. */
predicate includesUserInput() {
- exists(UserInputInComparisonConfig config |
- config.hasFlowTo(DataFlow2::exprNode(anotherParameter))
- )
+ UserInputInComparisonFlow::flowTo(DataFlow2::exprNode(anotherParameter))
}
}
@@ -177,9 +175,7 @@ class SecretSource extends DataFlow::Node {
SecretSource() { secret = this.asExpr() }
/** Holds if the secret was deliverd by remote user. */
- predicate includesUserInput() {
- exists(UserInputSecretConfig config | config.hasFlowTo(DataFlow2::exprNode(secret)))
- }
+ predicate includesUserInput() { UserInputSecretFlow::flowTo(DataFlow2::exprNode(secret)) }
}
/** A string for `match` that identifies strings that look like they represent secret data. */
@@ -267,23 +263,21 @@ private string sensitiveheaders() {
/**
* A config that tracks data flow from remote user input to Variable that hold sensitive info
*/
-class UserInputSecretConfig extends TaintTracking::Configuration {
- UserInputSecretConfig() { this = "UserInputSecretConfig" }
+module UserInputSecretConfig implements DataFlow::ConfigSig {
+ predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
- override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
-
- override predicate isSink(DataFlow::Node sink) { sink.asExpr() instanceof CredentialExpr }
+ predicate isSink(DataFlow::Node sink) { sink.asExpr() instanceof CredentialExpr }
}
+module UserInputSecretFlow = TaintTracking::Global;
+
/**
* A config that tracks data flow from remote user input to Equality test
*/
-class UserInputInComparisonConfig extends TaintTracking2::Configuration {
- UserInputInComparisonConfig() { this = "UserInputInComparisonConfig" }
+module UserInputInComparisonConfig implements DataFlow::ConfigSig {
+ predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
- override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
-
- override predicate isSink(DataFlow::Node sink) {
+ predicate isSink(DataFlow::Node sink) {
exists(Compare cmp, Expr left, Expr right, Cmpop cmpop |
cmpop.getSymbol() = ["==", "in", "is not", "!="] and
cmp.compares(left, cmpop, right) and
@@ -292,15 +286,15 @@ class UserInputInComparisonConfig extends TaintTracking2::Configuration {
}
}
+module UserInputInComparisonFlow = TaintTracking::Global;
+
/**
* A configuration tracing flow from a client Secret obtained by an HTTP header to a len() function.
*/
-private class ExcludeLenFunc extends TaintTracking2::Configuration {
- ExcludeLenFunc() { this = "ExcludeLenFunc" }
+private module ExcludeLenFuncConfig implements DataFlow::ConfigSig {
+ predicate isSource(DataFlow::Node source) { source instanceof ClientSuppliedSecret }
- override predicate isSource(DataFlow::Node source) { source instanceof ClientSuppliedSecret }
-
- override predicate isSink(DataFlow::Node sink) {
+ predicate isSink(DataFlow::Node sink) {
exists(Call call |
call.getFunc().(Name).getId() = "len" and
sink.asExpr() = call.getArg(0)
@@ -308,6 +302,8 @@ private class ExcludeLenFunc extends TaintTracking2::Configuration {
}
}
+module ExcludeLenFuncFlow = TaintTracking::Global;
+
/**
* Holds if there is a fast-fail check.
*/
@@ -343,8 +339,7 @@ class CompareSink extends DataFlow::Node {
* Holds if there is a flow to len().
*/
predicate flowtolen() {
- exists(ExcludeLenFunc config, DataFlow2::PathNode source, DataFlow2::PathNode sink |
- config.hasFlowPath(source, sink)
- )
+ // TODO: Fly by comment: I don't understand this code at all, seems very strange.
+ ExcludeLenFuncFlow::flowPath(_, _)
}
}
From 1a4e8d9464888bb1fdbdd72540ddce5117032472 Mon Sep 17 00:00:00 2001
From: Rasmus Wriedt Larsen
Date: Fri, 25 Aug 2023 17:23:50 +0200
Subject: [PATCH 113/788] Python: Move experimental
`PossibleTimingAttackAgainstSensitiveInfo` to new dataflow API
---
...ossibleTimingAttackAgainstSensitiveInfo.ql | 18 +++++++++-------
...eTimingAttackAgainstSensitiveInfo.expected | 21 -------------------
2 files changed, 10 insertions(+), 29 deletions(-)
diff --git a/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstSensitiveInfo/PossibleTimingAttackAgainstSensitiveInfo.ql b/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstSensitiveInfo/PossibleTimingAttackAgainstSensitiveInfo.ql
index d43c3aa8995..2cd51f49770 100644
--- a/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstSensitiveInfo/PossibleTimingAttackAgainstSensitiveInfo.ql
+++ b/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstSensitiveInfo/PossibleTimingAttackAgainstSensitiveInfo.ql
@@ -15,20 +15,22 @@ import python
import semmle.python.dataflow.new.DataFlow
import semmle.python.dataflow.new.TaintTracking
import experimental.semmle.python.security.TimingAttack
-import DataFlow::PathGraph
/**
* A configuration tracing flow from obtaining a client Secret to a unsafe Comparison.
*/
-class ClientSuppliedSecretConfig extends TaintTracking::Configuration {
- ClientSuppliedSecretConfig() { this = "ClientSuppliedSecretConfig" }
+private module PossibleTimingAttackAgainstSensitiveInfoConfig implements DataFlow::ConfigSig {
+ predicate isSource(DataFlow::Node source) { source instanceof SecretSource }
- override predicate isSource(DataFlow::Node source) { source instanceof SecretSource }
-
- override predicate isSink(DataFlow::Node sink) { sink instanceof NonConstantTimeComparisonSink }
+ predicate isSink(DataFlow::Node sink) { sink instanceof NonConstantTimeComparisonSink }
}
-from ClientSuppliedSecretConfig config, DataFlow::PathNode source, DataFlow::PathNode sink
-where config.hasFlowPath(source, sink)
+module PossibleTimingAttackAgainstSensitiveInfoFlow =
+TaintTracking::Global;
+
+import PossibleTimingAttackAgainstSensitiveInfoFlow::PathGraph
+
+from PossibleTimingAttackAgainstSensitiveInfoFlow::PathNode source, PossibleTimingAttackAgainstSensitiveInfoFlow::PathNode sink
+where PossibleTimingAttackAgainstSensitiveInfoFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "Timing attack against $@ validation.", source.getNode(),
"client-supplied token"
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-208/TimingAttackAgainstSensitiveInfo/PossibleTimingAttackAgainstSensitiveInfo.expected b/python/ql/test/experimental/query-tests/Security/CWE-208/TimingAttackAgainstSensitiveInfo/PossibleTimingAttackAgainstSensitiveInfo.expected
index 564398c25c3..63d5e8ad821 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-208/TimingAttackAgainstSensitiveInfo/PossibleTimingAttackAgainstSensitiveInfo.expected
+++ b/python/ql/test/experimental/query-tests/Security/CWE-208/TimingAttackAgainstSensitiveInfo/PossibleTimingAttackAgainstSensitiveInfo.expected
@@ -1,27 +1,6 @@
edges
-| TimingAttackAgainstSensitiveInfo.py:7:19:7:25 | ControlFlowNode for ImportMember | TimingAttackAgainstSensitiveInfo.py:7:19:7:25 | GSSA Variable request |
-| TimingAttackAgainstSensitiveInfo.py:7:19:7:25 | GSSA Variable request | TimingAttackAgainstSensitiveInfo.py:14:8:14:14 | ControlFlowNode for request |
-| TimingAttackAgainstSensitiveInfo.py:7:19:7:25 | GSSA Variable request | TimingAttackAgainstSensitiveInfo.py:15:20:15:26 | ControlFlowNode for request |
-| TimingAttackAgainstSensitiveInfo.py:7:19:7:25 | GSSA Variable request | TimingAttackAgainstSensitiveInfo.py:20:8:20:14 | ControlFlowNode for request |
-| TimingAttackAgainstSensitiveInfo.py:7:19:7:25 | GSSA Variable request | TimingAttackAgainstSensitiveInfo.py:21:20:21:26 | ControlFlowNode for request |
-| TimingAttackAgainstSensitiveInfo.py:14:8:14:14 | ControlFlowNode for request | TimingAttackAgainstSensitiveInfo.py:15:9:15:16 | SSA variable password |
-| TimingAttackAgainstSensitiveInfo.py:15:9:15:16 | SSA variable password | TimingAttackAgainstSensitiveInfo.py:16:16:16:23 | ControlFlowNode for password |
-| TimingAttackAgainstSensitiveInfo.py:15:20:15:26 | ControlFlowNode for request | TimingAttackAgainstSensitiveInfo.py:15:9:15:16 | SSA variable password |
-| TimingAttackAgainstSensitiveInfo.py:20:8:20:14 | ControlFlowNode for request | TimingAttackAgainstSensitiveInfo.py:21:9:21:16 | SSA variable password |
-| TimingAttackAgainstSensitiveInfo.py:21:9:21:16 | SSA variable password | TimingAttackAgainstSensitiveInfo.py:22:38:22:45 | ControlFlowNode for password |
-| TimingAttackAgainstSensitiveInfo.py:21:20:21:26 | ControlFlowNode for request | TimingAttackAgainstSensitiveInfo.py:21:9:21:16 | SSA variable password |
nodes
-| TimingAttackAgainstSensitiveInfo.py:7:19:7:25 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember |
-| TimingAttackAgainstSensitiveInfo.py:7:19:7:25 | GSSA Variable request | semmle.label | GSSA Variable request |
-| TimingAttackAgainstSensitiveInfo.py:14:8:14:14 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
-| TimingAttackAgainstSensitiveInfo.py:15:9:15:16 | SSA variable password | semmle.label | SSA variable password |
-| TimingAttackAgainstSensitiveInfo.py:15:20:15:26 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| TimingAttackAgainstSensitiveInfo.py:16:16:16:23 | ControlFlowNode for password | semmle.label | ControlFlowNode for password |
-| TimingAttackAgainstSensitiveInfo.py:16:16:16:23 | ControlFlowNode for password | semmle.label | ControlFlowNode for password |
-| TimingAttackAgainstSensitiveInfo.py:20:8:20:14 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
-| TimingAttackAgainstSensitiveInfo.py:21:9:21:16 | SSA variable password | semmle.label | SSA variable password |
-| TimingAttackAgainstSensitiveInfo.py:21:20:21:26 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
-| TimingAttackAgainstSensitiveInfo.py:22:38:22:45 | ControlFlowNode for password | semmle.label | ControlFlowNode for password |
subpaths
#select
| TimingAttackAgainstSensitiveInfo.py:16:16:16:23 | ControlFlowNode for password | TimingAttackAgainstSensitiveInfo.py:16:16:16:23 | ControlFlowNode for password | TimingAttackAgainstSensitiveInfo.py:16:16:16:23 | ControlFlowNode for password | Timing attack against $@ validation. | TimingAttackAgainstSensitiveInfo.py:16:16:16:23 | ControlFlowNode for password | client-supplied token |
From 8abd3430a27160ecda1f035b5e83508e6ac4d6a2 Mon Sep 17 00:00:00 2001
From: Rasmus Wriedt Larsen
Date: Fri, 25 Aug 2023 17:23:50 +0200
Subject: [PATCH 114/788] Python: Move experimental
`TimingAttackAgainstSensitiveInfo` to new dataflow API
---
.../TimingAttackAgainstSensitiveInfo.ql | 19 +++++++++++--------
1 file changed, 11 insertions(+), 8 deletions(-)
diff --git a/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstSensitiveInfo/TimingAttackAgainstSensitiveInfo.ql b/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstSensitiveInfo/TimingAttackAgainstSensitiveInfo.ql
index 63587d4afcc..8ec4fac97e3 100644
--- a/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstSensitiveInfo/TimingAttackAgainstSensitiveInfo.ql
+++ b/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstSensitiveInfo/TimingAttackAgainstSensitiveInfo.ql
@@ -15,22 +15,25 @@ import python
import semmle.python.dataflow.new.DataFlow
import semmle.python.dataflow.new.TaintTracking
import experimental.semmle.python.security.TimingAttack
-import DataFlow::PathGraph
+import TimingAttackAgainstSensitiveInfoFlow::PathGraph
/**
* A configuration tracing flow from obtaining a client Secret to a unsafe Comparison.
*/
-class ClientSuppliedSecretConfig extends TaintTracking::Configuration {
- ClientSuppliedSecretConfig() { this = "ClientSuppliedSecretConfig" }
+private module TimingAttackAgainstSensitiveInfoConfig implements DataFlow::ConfigSig {
+ predicate isSource(DataFlow::Node source) { source instanceof SecretSource }
- override predicate isSource(DataFlow::Node source) { source instanceof SecretSource }
-
- override predicate isSink(DataFlow::Node sink) { sink instanceof NonConstantTimeComparisonSink }
+ predicate isSink(DataFlow::Node sink) { sink instanceof NonConstantTimeComparisonSink }
}
-from ClientSuppliedSecretConfig config, DataFlow::PathNode source, DataFlow::PathNode sink
+module TimingAttackAgainstSensitiveInfoFlow =
+ TaintTracking::Global;
+
+from
+ TimingAttackAgainstSensitiveInfoFlow::PathNode source,
+ TimingAttackAgainstSensitiveInfoFlow::PathNode sink
where
- config.hasFlowPath(source, sink) and
+ TimingAttackAgainstSensitiveInfoFlow::flowPath(source, sink) and
(
source.getNode().(SecretSource).includesUserInput() or
sink.getNode().(NonConstantTimeComparisonSink).includesUserInput()
From a779547515c6c9b6c04a6dfdcca5bc8707e70d08 Mon Sep 17 00:00:00 2001
From: Rasmus Wriedt Larsen
Date: Fri, 25 Aug 2023 17:23:50 +0200
Subject: [PATCH 115/788] Python: Move experimental
`PossibleTimingAttackAgainstHash` to new dataflow API
---
.../PossibleTimingAttackAgainstHash.ql | 17 +++++++++--------
1 file changed, 9 insertions(+), 8 deletions(-)
diff --git a/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstHash/PossibleTimingAttackAgainstHash.ql b/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstHash/PossibleTimingAttackAgainstHash.ql
index f46b93fb266..7a6a3f946bc 100644
--- a/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstHash/PossibleTimingAttackAgainstHash.ql
+++ b/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstHash/PossibleTimingAttackAgainstHash.ql
@@ -17,21 +17,22 @@ import python
import semmle.python.dataflow.new.DataFlow
import semmle.python.dataflow.new.TaintTracking
import experimental.semmle.python.security.TimingAttack
-import DataFlow::PathGraph
/**
* A configuration that tracks data flow from cryptographic operations
* to equality test
*/
-class PossibleTimingAttackAgainstHash extends TaintTracking::Configuration {
- PossibleTimingAttackAgainstHash() { this = "PossibleTimingAttackAgainstHash" }
+private module PossibleTimingAttackAgainstHash implements DataFlow::ConfigSig {
+ predicate isSource(DataFlow::Node source) { source instanceof ProduceCryptoCall }
- override predicate isSource(DataFlow::Node source) { source instanceof ProduceCryptoCall }
-
- override predicate isSink(DataFlow::Node sink) { sink instanceof NonConstantTimeComparisonSink }
+ predicate isSink(DataFlow::Node sink) { sink instanceof NonConstantTimeComparisonSink }
}
-from PossibleTimingAttackAgainstHash config, DataFlow::PathNode source, DataFlow::PathNode sink
-where config.hasFlowPath(source, sink)
+module PossibleTimingAttackAgainstHashFlow = TaintTracking::Global;
+
+import PossibleTimingAttackAgainstHashFlow::PathGraph
+
+from PossibleTimingAttackAgainstHashFlow::PathNode source, PossibleTimingAttackAgainstHashFlow::PathNode sink
+where PossibleTimingAttackAgainstHashFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "Possible Timing attack against $@ validation.",
source.getNode().(ProduceCryptoCall).getResultType(), "message"
From c88a0ccb7c4510365ad9ee41a894ed42cfd018c1 Mon Sep 17 00:00:00 2001
From: Rasmus Wriedt Larsen
Date: Fri, 25 Aug 2023 17:23:50 +0200
Subject: [PATCH 116/788] Python: Move experimental `TimingAttackAgainstHash`
to new dataflow API
---
.../TimingAttackAgainstHash.ql | 17 +++++++++--------
1 file changed, 9 insertions(+), 8 deletions(-)
diff --git a/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstHash/TimingAttackAgainstHash.ql b/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstHash/TimingAttackAgainstHash.ql
index 392356b7c42..e08f1dbb517 100644
--- a/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstHash/TimingAttackAgainstHash.ql
+++ b/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstHash/TimingAttackAgainstHash.ql
@@ -16,23 +16,24 @@ import python
import semmle.python.dataflow.new.DataFlow
import semmle.python.dataflow.new.TaintTracking
import experimental.semmle.python.security.TimingAttack
-import DataFlow::PathGraph
/**
* A configuration that tracks data flow from cryptographic operations
* to Equality test.
*/
-class TimingAttackAgainsthash extends TaintTracking::Configuration {
- TimingAttackAgainsthash() { this = "TimingAttackAgainsthash" }
+private module TimingAttackAgainstHashConfig implements DataFlow::ConfigSig {
+ predicate isSource(DataFlow::Node source) { source instanceof ProduceCryptoCall }
- override predicate isSource(DataFlow::Node source) { source instanceof ProduceCryptoCall }
-
- override predicate isSink(DataFlow::Node sink) { sink instanceof NonConstantTimeComparisonSink }
+ predicate isSink(DataFlow::Node sink) { sink instanceof NonConstantTimeComparisonSink }
}
-from TimingAttackAgainsthash config, DataFlow::PathNode source, DataFlow::PathNode sink
+module TimingAttackAgainstHashFlow = TaintTracking::Global;
+
+import TimingAttackAgainstHashFlow::PathGraph
+
+from TimingAttackAgainstHashFlow::PathNode source, TimingAttackAgainstHashFlow::PathNode sink
where
- config.hasFlowPath(source, sink) and
+ TimingAttackAgainstHashFlow::flowPath(source, sink) and
sink.getNode().(NonConstantTimeComparisonSink).includesUserInput()
select sink.getNode(), source, sink, "Timing attack against $@ validation.",
source.getNode().(ProduceCryptoCall).getResultType(), "message"
From 3bf2705668a5b09b4aa91a9620207abb3e9b03b6 Mon Sep 17 00:00:00 2001
From: Rasmus Wriedt Larsen
Date: Fri, 25 Aug 2023 17:23:51 +0200
Subject: [PATCH 117/788] Python: Move experimental
`TimingAttackAgainstHeaderValue` to new dataflow API
---
.../TimingAttackAgainstHeaderValue.ql | 22 ++++++++++++-------
1 file changed, 14 insertions(+), 8 deletions(-)
diff --git a/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstHeaderValue/TimingAttackAgainstHeaderValue.ql b/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstHeaderValue/TimingAttackAgainstHeaderValue.ql
index 1f2ff8f50fb..a1da41530a8 100644
--- a/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstHeaderValue/TimingAttackAgainstHeaderValue.ql
+++ b/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstHeaderValue/TimingAttackAgainstHeaderValue.ql
@@ -15,20 +15,26 @@ import python
import semmle.python.dataflow.new.DataFlow
import semmle.python.dataflow.new.TaintTracking
import experimental.semmle.python.security.TimingAttack
-import DataFlow::PathGraph
/**
* A configuration tracing flow from a client Secret obtained by an HTTP header to a unsafe Comparison.
*/
-class ClientSuppliedSecretConfig extends TaintTracking::Configuration {
- ClientSuppliedSecretConfig() { this = "ClientSuppliedSecretConfig" }
+private module TimingAttackAgainstHeaderValueConfig implements DataFlow::ConfigSig {
+ predicate isSource(DataFlow::Node source) { source instanceof ClientSuppliedSecret }
- override predicate isSource(DataFlow::Node source) { source instanceof ClientSuppliedSecret }
-
- override predicate isSink(DataFlow::Node sink) { sink instanceof CompareSink }
+ predicate isSink(DataFlow::Node sink) { sink instanceof CompareSink }
}
-from ClientSuppliedSecretConfig config, DataFlow::PathNode source, DataFlow::PathNode sink
-where config.hasFlowPath(source, sink) and not sink.getNode().(CompareSink).flowtolen()
+module TimingAttackAgainstHeaderValueFlow =
+ TaintTracking::Global;
+
+import TimingAttackAgainstHeaderValueFlow::PathGraph
+
+from
+ TimingAttackAgainstHeaderValueFlow::PathNode source,
+ TimingAttackAgainstHeaderValueFlow::PathNode sink
+where
+ TimingAttackAgainstHeaderValueFlow::flowPath(source, sink) and
+ not sink.getNode().(CompareSink).flowtolen()
select sink.getNode(), source, sink, "Timing attack against $@ validation.", source.getNode(),
"client-supplied token"
From 53e57dad5c62eb7607ddc93584a65769c433b2a6 Mon Sep 17 00:00:00 2001
From: Rasmus Wriedt Larsen
Date: Fri, 25 Aug 2023 17:23:51 +0200
Subject: [PATCH 118/788] Python: Move experimental `InsecureRandomness` to new
dataflow API
---
.../Security/CWE-338/InsecureRandomness.ql | 9 +++++----
.../python/security/InsecureRandomness.qll | 17 +++++++----------
2 files changed, 12 insertions(+), 14 deletions(-)
diff --git a/python/ql/src/experimental/Security/CWE-338/InsecureRandomness.ql b/python/ql/src/experimental/Security/CWE-338/InsecureRandomness.ql
index 476906283aa..3e48068f015 100644
--- a/python/ql/src/experimental/Security/CWE-338/InsecureRandomness.ql
+++ b/python/ql/src/experimental/Security/CWE-338/InsecureRandomness.ql
@@ -14,11 +14,12 @@
*/
import python
-import experimental.semmle.python.security.InsecureRandomness::InsecureRandomness
+import experimental.semmle.python.security.InsecureRandomness
import semmle.python.dataflow.new.DataFlow
-import DataFlow::PathGraph
-from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
-where cfg.hasFlowPath(source, sink)
+import InsecureRandomness::Flow::PathGraph
+
+from InsecureRandomness::Flow::PathNode source, InsecureRandomness::Flow::PathNode sink
+where InsecureRandomness::Flow::flowPath(source, sink)
select sink.getNode(), source, sink, "Cryptographically insecure $@ in a security context.",
source.getNode(), "random value"
diff --git a/python/ql/src/experimental/semmle/python/security/InsecureRandomness.qll b/python/ql/src/experimental/semmle/python/security/InsecureRandomness.qll
index 5ad5e2553a5..c71b461d20a 100644
--- a/python/ql/src/experimental/semmle/python/security/InsecureRandomness.qll
+++ b/python/ql/src/experimental/semmle/python/security/InsecureRandomness.qll
@@ -21,17 +21,14 @@ module InsecureRandomness {
* A taint-tracking configuration for reasoning about random values that are
* not cryptographically secure.
*/
- class Configuration extends TaintTracking::Configuration {
- Configuration() { this = "InsecureRandomness" }
+ private module Configuration implements DataFlow::ConfigSig {
+ predicate isSource(DataFlow::Node source) { source instanceof Source }
- override predicate isSource(DataFlow::Node source) { source instanceof Source }
+ predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
- override predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
-
- override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer }
-
- deprecated override predicate isSanitizerGuard(DataFlow::BarrierGuard guard) {
- guard instanceof SanitizerGuard
- }
+ predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer }
}
+
+ /** Global taint-tracking for detecting "random values that are not cryptographically secure" vulnerabilities. */
+ module Flow = TaintTracking::Global;
}
From d948e103fa43057323d347c4efba6599cc40c223 Mon Sep 17 00:00:00 2001
From: Rasmus Wriedt Larsen
Date: Fri, 25 Aug 2023 17:23:51 +0200
Subject: [PATCH 119/788] Python: Move experimental `HeaderInjection` to new
dataflow API
---
.../experimental/Security/CWE-113/HeaderInjection.ql | 6 +++---
.../semmle/python/security/injection/HTTPHeaders.qll | 11 ++++++-----
2 files changed, 9 insertions(+), 8 deletions(-)
diff --git a/python/ql/src/experimental/Security/CWE-113/HeaderInjection.ql b/python/ql/src/experimental/Security/CWE-113/HeaderInjection.ql
index 65305d2f3b5..6527df03339 100644
--- a/python/ql/src/experimental/Security/CWE-113/HeaderInjection.ql
+++ b/python/ql/src/experimental/Security/CWE-113/HeaderInjection.ql
@@ -14,9 +14,9 @@
// determine precision above
import python
import experimental.semmle.python.security.injection.HTTPHeaders
-import DataFlow::PathGraph
+import HeaderInjectionFlow::PathGraph
-from HeaderInjectionFlowConfig config, DataFlow::PathNode source, DataFlow::PathNode sink
-where config.hasFlowPath(source, sink)
+from HeaderInjectionFlow::PathNode source, HeaderInjectionFlow::PathNode sink
+where HeaderInjectionFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "This HTTP header is constructed from a $@.", source.getNode(),
"user-provided value"
diff --git a/python/ql/src/experimental/semmle/python/security/injection/HTTPHeaders.qll b/python/ql/src/experimental/semmle/python/security/injection/HTTPHeaders.qll
index 4ba70cd37a2..0768d7a84b2 100644
--- a/python/ql/src/experimental/semmle/python/security/injection/HTTPHeaders.qll
+++ b/python/ql/src/experimental/semmle/python/security/injection/HTTPHeaders.qll
@@ -7,14 +7,15 @@ import semmle.python.dataflow.new.RemoteFlowSources
/**
* A taint-tracking configuration for detecting HTTP Header injections.
*/
-class HeaderInjectionFlowConfig extends TaintTracking::Configuration {
- HeaderInjectionFlowConfig() { this = "HeaderInjectionFlowConfig" }
+private module HeaderInjectionConfig implements DataFlow::ConfigSig {
+ predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
- override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
-
- override predicate isSink(DataFlow::Node sink) {
+ predicate isSink(DataFlow::Node sink) {
exists(HeaderDeclaration headerDeclaration |
sink in [headerDeclaration.getNameArg(), headerDeclaration.getValueArg()]
)
}
}
+
+/** Global taint-tracking for detecting "HTTP Header injection" vulnerabilities. */
+module HeaderInjectionFlow = TaintTracking::Global;
From ace1e23c211eaba17833499eeddc0aad9bc6cf48 Mon Sep 17 00:00:00 2001
From: Rasmus Wriedt Larsen
Date: Fri, 25 Aug 2023 17:23:51 +0200
Subject: [PATCH 120/788] Python: Move experimental
`ClientSuppliedIpUsedInSecurityCheck` to new dataflow API
---
.../ClientSuppliedIpUsedInSecurityCheck.ql | 24 ++++++++++---------
1 file changed, 13 insertions(+), 11 deletions(-)
diff --git a/python/ql/src/experimental/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheck.ql b/python/ql/src/experimental/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheck.ql
index aec637269ac..b1d598f4749 100644
--- a/python/ql/src/experimental/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheck.ql
+++ b/python/ql/src/experimental/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheck.ql
@@ -16,21 +16,19 @@ import semmle.python.dataflow.new.DataFlow
import semmle.python.dataflow.new.TaintTracking
import semmle.python.ApiGraphs
import ClientSuppliedIpUsedInSecurityCheckLib
-import DataFlow::PathGraph
+import ClientSuppliedIpUsedInSecurityCheckFlow::PathGraph
/**
* A taint-tracking configuration tracing flow from obtaining a client ip from an HTTP header to a sensitive use.
*/
-class ClientSuppliedIpUsedInSecurityCheckConfig extends TaintTracking::Configuration {
- ClientSuppliedIpUsedInSecurityCheckConfig() { this = "ClientSuppliedIpUsedInSecurityCheckConfig" }
-
- override predicate isSource(DataFlow::Node source) {
+private module ClientSuppliedIpUsedInSecurityCheckConfig implements DataFlow::ConfigSig {
+ predicate isSource(DataFlow::Node source) {
source instanceof ClientSuppliedIpUsedInSecurityCheck
}
- override predicate isSink(DataFlow::Node sink) { sink instanceof PossibleSecurityCheck }
+ predicate isSink(DataFlow::Node sink) { sink instanceof PossibleSecurityCheck }
- override predicate isAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ) {
+ predicate isAdditionalFlowStep(DataFlow::Node pred, DataFlow::Node succ) {
exists(DataFlow::CallCfgNode ccn |
ccn = API::moduleImport("netaddr").getMember("IPAddress").getACall() and
ccn.getArg(0) = pred and
@@ -38,7 +36,7 @@ class ClientSuppliedIpUsedInSecurityCheckConfig extends TaintTracking::Configura
)
}
- override predicate isSanitizer(DataFlow::Node node) {
+ predicate isBarrier(DataFlow::Node node) {
// `client_supplied_ip.split(",")[n]` for `n` > 0
exists(Subscript ss |
not ss.getIndex().(IntegerLiteral).getText() = "0" and
@@ -49,9 +47,13 @@ class ClientSuppliedIpUsedInSecurityCheckConfig extends TaintTracking::Configura
}
}
+
+/** Global taint-tracking for detecting "client ip used in security check" vulnerabilities. */
+module ClientSuppliedIpUsedInSecurityCheckFlow = TaintTracking::Global;
+
from
- ClientSuppliedIpUsedInSecurityCheckConfig config, DataFlow::PathNode source,
- DataFlow::PathNode sink
-where config.hasFlowPath(source, sink)
+ ClientSuppliedIpUsedInSecurityCheckFlow::PathNode source,
+ ClientSuppliedIpUsedInSecurityCheckFlow::PathNode sink
+where ClientSuppliedIpUsedInSecurityCheckFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "IP address spoofing might include code from $@.",
source.getNode(), "this user input"
From 2c412707ab3ede26a9551cf3806fccab51384e9e Mon Sep 17 00:00:00 2001
From: Rasmus Wriedt Larsen
Date: Fri, 25 Aug 2023 17:23:51 +0200
Subject: [PATCH 121/788] Python: Move experimental `CsvInjection` to new
dataflow API
---
.../experimental/Security/CWE-1236/CsvInjection.ql | 6 +++---
.../python/security/injection/CsvInjection.qll | 13 +++++++------
2 files changed, 10 insertions(+), 9 deletions(-)
diff --git a/python/ql/src/experimental/Security/CWE-1236/CsvInjection.ql b/python/ql/src/experimental/Security/CWE-1236/CsvInjection.ql
index 28a68dd78df..df9b7cf9f65 100644
--- a/python/ql/src/experimental/Security/CWE-1236/CsvInjection.ql
+++ b/python/ql/src/experimental/Security/CWE-1236/CsvInjection.ql
@@ -11,11 +11,11 @@
*/
import python
-import DataFlow::PathGraph
+import CsvInjectionFlow::PathGraph
import semmle.python.dataflow.new.DataFlow
import experimental.semmle.python.security.injection.CsvInjection
-from CsvInjectionFlowConfig config, DataFlow::PathNode source, DataFlow::PathNode sink
-where config.hasFlowPath(source, sink)
+from CsvInjectionFlow::PathNode source, CsvInjectionFlow::PathNode sink
+where CsvInjectionFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "Csv injection might include code from $@.", source.getNode(),
"this user input"
diff --git a/python/ql/src/experimental/semmle/python/security/injection/CsvInjection.qll b/python/ql/src/experimental/semmle/python/security/injection/CsvInjection.qll
index c6197222d91..316dd4d2603 100644
--- a/python/ql/src/experimental/semmle/python/security/injection/CsvInjection.qll
+++ b/python/ql/src/experimental/semmle/python/security/injection/CsvInjection.qll
@@ -8,14 +8,12 @@ import semmle.python.dataflow.new.RemoteFlowSources
/**
* A taint-tracking configuration for tracking untrusted user input used in file read.
*/
-class CsvInjectionFlowConfig extends TaintTracking::Configuration {
- CsvInjectionFlowConfig() { this = "CsvInjectionFlowConfig" }
+private module CsvInjectionConfig implements DataFlow::ConfigSig {
+ predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
- override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
+ predicate isSink(DataFlow::Node sink) { sink = any(CsvWriter cw).getAnInput() }
- override predicate isSink(DataFlow::Node sink) { sink = any(CsvWriter cw).getAnInput() }
-
- override predicate isSanitizer(DataFlow::Node node) {
+ predicate isBarrier(DataFlow::Node node) {
node = DataFlow::BarrierGuard::getABarrierNode() or
node instanceof StringConstCompareBarrier
}
@@ -29,3 +27,6 @@ private predicate startsWithCheck(DataFlow::GuardNode g, ControlFlowNode node, b
branch = true
)
}
+
+/** Global taint-tracking for detecting "CSV injection" vulnerabilities. */
+module CsvInjectionFlow = TaintTracking::Global;
From 2c06394bf359ee7e571ecb34fb7b8b0971da731d Mon Sep 17 00:00:00 2001
From: Rasmus Wriedt Larsen
Date: Fri, 25 Aug 2023 17:23:51 +0200
Subject: [PATCH 122/788] Python: Move experimental `CookieInjection` to new
dataflow API
---
.../experimental/Security/CWE-614/CookieInjection.ql | 6 +++---
.../python/security/injection/CookieInjection.qll | 11 ++++++-----
2 files changed, 9 insertions(+), 8 deletions(-)
diff --git a/python/ql/src/experimental/Security/CWE-614/CookieInjection.ql b/python/ql/src/experimental/Security/CWE-614/CookieInjection.ql
index 894a69753d9..60e0fc4a0e4 100644
--- a/python/ql/src/experimental/Security/CWE-614/CookieInjection.ql
+++ b/python/ql/src/experimental/Security/CWE-614/CookieInjection.ql
@@ -15,13 +15,13 @@ import semmle.python.dataflow.new.DataFlow
import experimental.semmle.python.Concepts
import experimental.semmle.python.CookieHeader
import experimental.semmle.python.security.injection.CookieInjection
-import DataFlow::PathGraph
+import CookieInjectionFlow::PathGraph
from
- CookieInjectionFlowConfig config, DataFlow::PathNode source, DataFlow::PathNode sink,
+ CookieInjectionFlow::PathNode source, CookieInjectionFlow::PathNode sink,
string insecure
where
- config.hasFlowPath(source, sink) and
+ 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 = "."
diff --git a/python/ql/src/experimental/semmle/python/security/injection/CookieInjection.qll b/python/ql/src/experimental/semmle/python/security/injection/CookieInjection.qll
index 87f3b1fd76b..5d31b9f8b51 100644
--- a/python/ql/src/experimental/semmle/python/security/injection/CookieInjection.qll
+++ b/python/ql/src/experimental/semmle/python/security/injection/CookieInjection.qll
@@ -29,12 +29,13 @@ class CookieSink extends DataFlow::Node {
/**
* A taint-tracking configuration for detecting Cookie injections.
*/
-class CookieInjectionFlowConfig extends TaintTracking::Configuration {
- CookieInjectionFlowConfig() { this = "CookieInjectionFlowConfig" }
+private module CookieInjectionConfig implements DataFlow::ConfigSig {
+ predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
- override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
-
- override predicate isSink(DataFlow::Node sink) {
+ predicate isSink(DataFlow::Node sink) {
exists(Cookie c | sink in [c.getNameArg(), c.getValueArg()])
}
}
+
+/** Global taint-tracking for detecting "Cookie injections" vulnerabilities. */
+module CookieInjectionFlow = TaintTracking::Global;
From c6911c2ae064422dfadac1d2a5850b9b7f8c1117 Mon Sep 17 00:00:00 2001
From: Rasmus Wriedt Larsen
Date: Fri, 25 Aug 2023 17:23:51 +0200
Subject: [PATCH 123/788] Python: Move experimental `UnicodeBypassValidation`
to new dataflow API
---
.../CWE-176/UnicodeBypassValidation.ql | 6 +++---
.../CWE-176/UnicodeBypassValidationQuery.qll | 18 +++++++++++-------
2 files changed, 14 insertions(+), 10 deletions(-)
diff --git a/python/ql/src/experimental/Security/CWE-176/UnicodeBypassValidation.ql b/python/ql/src/experimental/Security/CWE-176/UnicodeBypassValidation.ql
index 67c61653763..f830c0ea25d 100644
--- a/python/ql/src/experimental/Security/CWE-176/UnicodeBypassValidation.ql
+++ b/python/ql/src/experimental/Security/CWE-176/UnicodeBypassValidation.ql
@@ -14,10 +14,10 @@
import python
import UnicodeBypassValidationQuery
-import DataFlow::PathGraph
+import UnicodeBypassValidationFlow::PathGraph
-from Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink
-where config.hasFlowPath(source, sink)
+from UnicodeBypassValidationFlow::PathNode source, UnicodeBypassValidationFlow::PathNode sink
+where UnicodeBypassValidationFlow::flowPath(source, sink)
select sink.getNode(), source, sink,
"This $@ processes unsafely $@ and any logical validation in-between could be bypassed using special Unicode characters.",
sink.getNode(), "Unicode transformation (Unicode normalization)", source.getNode(),
diff --git a/python/ql/src/experimental/Security/CWE-176/UnicodeBypassValidationQuery.qll b/python/ql/src/experimental/Security/CWE-176/UnicodeBypassValidationQuery.qll
index 702a69a7095..169c71a0c09 100644
--- a/python/ql/src/experimental/Security/CWE-176/UnicodeBypassValidationQuery.qll
+++ b/python/ql/src/experimental/Security/CWE-176/UnicodeBypassValidationQuery.qll
@@ -3,6 +3,7 @@
*/
private import python
+import semmle.python.dataflow.new.DataFlow
import semmle.python.ApiGraphs
import semmle.python.Concepts
import semmle.python.dataflow.new.internal.DataFlowPublic
@@ -27,16 +28,16 @@ class PostValidation extends DataFlow::FlowState {
* This configuration uses two flow states, `PreValidation` and `PostValidation`,
* to track the requirement that a logical validation has been performed before the Unicode Transformation.
*/
-class Configuration extends TaintTracking::Configuration {
- Configuration() { this = "UnicodeBypassValidation" }
+private module UnicodeBypassValidationConfig implements DataFlow::StateConfigSig {
+ class FlowState = DataFlow::FlowState;
- override predicate isSource(DataFlow::Node source, DataFlow::FlowState state) {
+ predicate isSource(DataFlow::Node source, FlowState state) {
source instanceof RemoteFlowSource and state instanceof PreValidation
}
- override predicate isAdditionalTaintStep(
- DataFlow::Node nodeFrom, DataFlow::FlowState stateFrom, DataFlow::Node nodeTo,
- DataFlow::FlowState stateTo
+ predicate isAdditionalFlowStep(
+ DataFlow::Node nodeFrom, FlowState stateFrom, DataFlow::Node nodeTo,
+ FlowState stateTo
) {
(
exists(Escaping escaping | nodeFrom = escaping.getAnInput() and nodeTo = escaping.getOutput())
@@ -51,7 +52,7 @@ class Configuration extends TaintTracking::Configuration {
}
/* A Unicode Tranformation (Unicode tranformation) is considered a sink when the algorithm used is either NFC or NFKC. */
- override predicate isSink(DataFlow::Node sink, DataFlow::FlowState state) {
+ predicate isSink(DataFlow::Node sink, FlowState state) {
exists(API::CallNode cn |
cn = API::moduleImport("unicodedata").getMember("normalize").getACall() and
sink = cn.getArg(1)
@@ -71,3 +72,6 @@ class Configuration extends TaintTracking::Configuration {
state instanceof PostValidation
}
}
+
+/** Global taint-tracking for detecting "Unicode transformation mishandling" vulnerabilities. */
+module UnicodeBypassValidationFlow = TaintTracking::GlobalWithState;
From acd0f2a8fb241fe488d35f28bb435f0c4be0bdc8 Mon Sep 17 00:00:00 2001
From: Rasmus Wriedt Larsen
Date: Fri, 25 Aug 2023 17:23:51 +0200
Subject: [PATCH 124/788] Python: Move experimental `LDAPInsecureAuth` to new
dataflow API
---
.../experimental/Security/CWE-522/LDAPInsecureAuth.ql | 6 +++---
.../semmle/python/security/LDAPInsecureAuth.qll | 11 ++++++-----
2 files changed, 9 insertions(+), 8 deletions(-)
diff --git a/python/ql/src/experimental/Security/CWE-522/LDAPInsecureAuth.ql b/python/ql/src/experimental/Security/CWE-522/LDAPInsecureAuth.ql
index 960ef9a671a..e870a92e9ab 100644
--- a/python/ql/src/experimental/Security/CWE-522/LDAPInsecureAuth.ql
+++ b/python/ql/src/experimental/Security/CWE-522/LDAPInsecureAuth.ql
@@ -12,9 +12,9 @@
// determine precision above
import python
-import DataFlow::PathGraph
+import LDAPInsecureAuthFlow::PathGraph
import experimental.semmle.python.security.LDAPInsecureAuth
-from LdapInsecureAuthConfig config, DataFlow::PathNode source, DataFlow::PathNode sink
-where config.hasFlowPath(source, sink)
+from LDAPInsecureAuthFlow::PathNode source, LDAPInsecureAuthFlow::PathNode sink
+where LDAPInsecureAuthFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "This LDAP host is authenticated insecurely."
diff --git a/python/ql/src/experimental/semmle/python/security/LDAPInsecureAuth.qll b/python/ql/src/experimental/semmle/python/security/LDAPInsecureAuth.qll
index 56fffe3a2a0..133bb1810cc 100644
--- a/python/ql/src/experimental/semmle/python/security/LDAPInsecureAuth.qll
+++ b/python/ql/src/experimental/semmle/python/security/LDAPInsecureAuth.qll
@@ -88,10 +88,8 @@ class LdapStringVar extends BinaryExpr {
/**
* A taint-tracking configuration for detecting LDAP insecure authentications.
*/
-class LdapInsecureAuthConfig extends TaintTracking::Configuration {
- LdapInsecureAuthConfig() { this = "LDAPInsecureAuthConfig" }
-
- override predicate isSource(DataFlow::Node source) {
+private module LDAPInsecureAuthConfig implements DataFlow::ConfigSig {
+ predicate isSource(DataFlow::Node source) {
source instanceof RemoteFlowSource or
source.asExpr() instanceof LdapFullHost or
source.asExpr() instanceof LdapBothStrings or
@@ -100,7 +98,10 @@ class LdapInsecureAuthConfig extends TaintTracking::Configuration {
source.asExpr() instanceof LdapStringVar
}
- override predicate isSink(DataFlow::Node sink) {
+ predicate isSink(DataFlow::Node sink) {
exists(LdapBind ldapBind | not ldapBind.useSsl() and sink = ldapBind.getHost())
}
}
+
+/** Global taint-tracking for detecting "LDAP insecure authentications" vulnerabilities. */
+module LDAPInsecureAuthFlow = TaintTracking::Global;
From bfcc194b85500dc3b0fa7060cd1fac5368ec9f89 Mon Sep 17 00:00:00 2001
From: Rasmus Wriedt Larsen
Date: Fri, 25 Aug 2023 17:23:51 +0200
Subject: [PATCH 125/788] Python: Move experimental `paramiko` to new dataflow
API
---
.../Security/CWE-074/paramiko/paramiko.ql | 20 ++++++++++---------
.../CWE-074-paramiko/paramiko.expected | 4 +++-
2 files changed, 14 insertions(+), 10 deletions(-)
diff --git a/python/ql/src/experimental/Security/CWE-074/paramiko/paramiko.ql b/python/ql/src/experimental/Security/CWE-074/paramiko/paramiko.ql
index 5a38a673080..a902ff045c4 100644
--- a/python/ql/src/experimental/Security/CWE-074/paramiko/paramiko.ql
+++ b/python/ql/src/experimental/Security/CWE-074/paramiko/paramiko.ql
@@ -16,16 +16,13 @@ import semmle.python.dataflow.new.DataFlow
import semmle.python.dataflow.new.TaintTracking
import semmle.python.dataflow.new.RemoteFlowSources
import semmle.python.ApiGraphs
-import DataFlow::PathGraph
private API::Node paramikoClient() {
result = API::moduleImport("paramiko").getMember("SSHClient").getReturn()
}
-class ParamikoCmdInjectionConfiguration extends TaintTracking::Configuration {
- ParamikoCmdInjectionConfiguration() { this = "ParamikoCMDInjectionConfiguration" }
-
- override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
+private module ParamikoConfig implements DataFlow::ConfigSig {
+ predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
/**
* exec_command of `paramiko.SSHClient` class execute command on ssh target server
@@ -33,7 +30,7 @@ class ParamikoCmdInjectionConfiguration extends TaintTracking::Configuration {
* and it run CMD on current system that running the ssh command
* the Sink related to proxy command is the `connect` method of `paramiko.SSHClient` class
*/
- override predicate isSink(DataFlow::Node sink) {
+ predicate isSink(DataFlow::Node sink) {
sink = paramikoClient().getMember("exec_command").getACall().getParameter(0, "command").asSink()
or
sink = paramikoClient().getMember("connect").getACall().getParameter(11, "sock").asSink()
@@ -42,7 +39,7 @@ class ParamikoCmdInjectionConfiguration extends TaintTracking::Configuration {
/**
* this additional taint step help taint tracking to find the vulnerable `connect` method of `paramiko.SSHClient` class
*/
- override predicate isAdditionalTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
+ predicate isAdditionalFlowStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
exists(API::CallNode call |
call = API::moduleImport("paramiko").getMember("ProxyCommand").getACall() and
nodeFrom = call.getParameter(0, "command_line").asSink() and
@@ -51,7 +48,12 @@ class ParamikoCmdInjectionConfiguration extends TaintTracking::Configuration {
}
}
-from ParamikoCmdInjectionConfiguration config, DataFlow::PathNode source, DataFlow::PathNode sink
-where config.hasFlowPath(source, sink)
+/** Global taint-tracking for detecting "paramiko command injection" vulnerabilities. */
+module ParamikoFlow = TaintTracking::Global;
+
+import ParamikoFlow::PathGraph
+
+from ParamikoFlow::PathNode source, ParamikoFlow::PathNode sink
+where ParamikoFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "This code execution depends on a $@.", source.getNode(),
"a user-provided value"
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-074-paramiko/paramiko.expected b/python/ql/test/experimental/query-tests/Security/CWE-074-paramiko/paramiko.expected
index 85e1e7b326d..b31006425a6 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-074-paramiko/paramiko.expected
+++ b/python/ql/test/experimental/query-tests/Security/CWE-074-paramiko/paramiko.expected
@@ -1,7 +1,8 @@
edges
| paramiko.py:15:21:15:23 | ControlFlowNode for cmd | paramiko.py:16:62:16:64 | ControlFlowNode for cmd |
| paramiko.py:20:21:20:23 | ControlFlowNode for cmd | paramiko.py:21:70:21:72 | ControlFlowNode for cmd |
-| paramiko.py:25:21:25:23 | ControlFlowNode for cmd | paramiko.py:26:114:26:139 | ControlFlowNode for Attribute() |
+| paramiko.py:25:21:25:23 | ControlFlowNode for cmd | paramiko.py:26:136:26:138 | ControlFlowNode for cmd |
+| paramiko.py:26:136:26:138 | ControlFlowNode for cmd | paramiko.py:26:114:26:139 | ControlFlowNode for Attribute() |
nodes
| paramiko.py:15:21:15:23 | ControlFlowNode for cmd | semmle.label | ControlFlowNode for cmd |
| paramiko.py:16:62:16:64 | ControlFlowNode for cmd | semmle.label | ControlFlowNode for cmd |
@@ -9,6 +10,7 @@ nodes
| paramiko.py:21:70:21:72 | ControlFlowNode for cmd | semmle.label | ControlFlowNode for cmd |
| paramiko.py:25:21:25:23 | ControlFlowNode for cmd | semmle.label | ControlFlowNode for cmd |
| paramiko.py:26:114:26:139 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
+| paramiko.py:26:136:26:138 | ControlFlowNode for cmd | semmle.label | ControlFlowNode for cmd |
subpaths
#select
| paramiko.py:16:62:16:64 | ControlFlowNode for cmd | paramiko.py:15:21:15:23 | ControlFlowNode for cmd | paramiko.py:16:62:16:64 | ControlFlowNode for cmd | This code execution depends on a $@. | paramiko.py:15:21:15:23 | ControlFlowNode for cmd | a user-provided value |
From d5e2a30e5b7905410e69255682ecdc2c3c3fac4e Mon Sep 17 00:00:00 2001
From: Rasmus Wriedt Larsen
Date: Fri, 25 Aug 2023 21:58:51 +0200
Subject: [PATCH 126/788] Python: Modernize
`py/azure-storage/unsafe-client-side-encryption-in-use` a bit
To use consistent naming
---
.../Azure/UnsafeUsageOfClientSideEncryptionVersion.ql | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/python/ql/src/experimental/Security/CWE-327/Azure/UnsafeUsageOfClientSideEncryptionVersion.ql b/python/ql/src/experimental/Security/CWE-327/Azure/UnsafeUsageOfClientSideEncryptionVersion.ql
index 9b73cdcec87..b23ca4b0bc6 100644
--- a/python/ql/src/experimental/Security/CWE-327/Azure/UnsafeUsageOfClientSideEncryptionVersion.ql
+++ b/python/ql/src/experimental/Security/CWE-327/Azure/UnsafeUsageOfClientSideEncryptionVersion.ql
@@ -96,7 +96,7 @@ newtype TAzureFlowState =
MkUsesV1Encryption() or
MkUsesNoEncryption()
-module AzureBlobClientConfig implements DataFlow::StateConfigSig {
+private module AzureBlobClientConfig implements DataFlow::StateConfigSig {
class FlowState = TAzureFlowState;
predicate isSource(DataFlow::Node node, FlowState state) {
@@ -147,10 +147,10 @@ module AzureBlobClientConfig implements DataFlow::StateConfigSig {
}
}
-module AzureBlobClient = DataFlow::GlobalWithState;
+module AzureBlobClientFlow = DataFlow::GlobalWithState;
-import AzureBlobClient::PathGraph
+import AzureBlobClientFlow::PathGraph
-from AzureBlobClient::PathNode source, AzureBlobClient::PathNode sink
-where AzureBlobClient::flowPath(source, sink)
+from AzureBlobClientFlow::PathNode source, AzureBlobClientFlow::PathNode sink
+where AzureBlobClientFlow::flowPath(source, sink)
select sink, source, sink, "Unsafe usage of v1 version of Azure Storage client-side encryption"
From 852b01c65da327ee5a5f7b4bba5d8a15afddc198 Mon Sep 17 00:00:00 2001
From: Rasmus Wriedt Larsen
Date: Fri, 25 Aug 2023 22:07:11 +0200
Subject: [PATCH 127/788] Python: Move `SmtpMessageConfig` to new dataflow API
---
.../semmle/python/libraries/SmtpLib.qll | 15 +++++++--------
1 file changed, 7 insertions(+), 8 deletions(-)
diff --git a/python/ql/src/experimental/semmle/python/libraries/SmtpLib.qll b/python/ql/src/experimental/semmle/python/libraries/SmtpLib.qll
index 83ea49cbb66..7ecbbc1beba 100644
--- a/python/ql/src/experimental/semmle/python/libraries/SmtpLib.qll
+++ b/python/ql/src/experimental/semmle/python/libraries/SmtpLib.qll
@@ -2,7 +2,7 @@ private import python
private import semmle.python.dataflow.new.DataFlow
private import experimental.semmle.python.Concepts
private import semmle.python.ApiGraphs
-private import semmle.python.dataflow.new.TaintTracking2
+private import semmle.python.dataflow.new.TaintTracking
module SmtpLib {
/** Gets a reference to `smtplib.SMTP_SSL` */
@@ -31,16 +31,16 @@ module SmtpLib {
* argument. Used because of the impossibility to get local source nodes from `_subparts`'
* `(List|Tuple)` elements.
*/
- private class SmtpMessageConfig extends TaintTracking2::Configuration {
- SmtpMessageConfig() { this = "SMTPMessageConfig" }
+ private module SmtpMessageConfig implements DataFlow::ConfigSig {
+ predicate isSource(DataFlow::Node source) { source = mimeText(_) }
- override predicate isSource(DataFlow::Node source) { source = mimeText(_) }
-
- override predicate isSink(DataFlow::Node sink) {
+ predicate isSink(DataFlow::Node sink) {
sink = smtpMimeMultipartInstance().getACall().getArgByName("_subparts")
}
}
+ module SmtpMessageFlow = TaintTracking::Global;
+
/**
* Using the `MimeText` call retrieves the content argument whose type argument equals `mimetype`.
* This call flows into `MIMEMultipart`'s `_subparts` argument or the `.attach()` method call
@@ -87,8 +87,7 @@ module SmtpLib {
sink =
[sendCall.getArg(2), sendCall.getArg(2).(DataFlow::MethodCallNode).getObject()]
.getALocalSource() and
- any(SmtpMessageConfig a)
- .hasFlow(source, sink.(DataFlow::CallCfgNode).getArgByName("_subparts"))
+ SmtpMessageFlow::flow(source, sink.(DataFlow::CallCfgNode).getArgByName("_subparts"))
or
// via .attach()
sink = smtpMimeMultipartInstance().getReturn().getMember("attach").getACall() and
From 6d4491e0a92f74634bf12443b4882b1b69e41561 Mon Sep 17 00:00:00 2001
From: Rasmus Wriedt Larsen
Date: Fri, 25 Aug 2023 22:08:19 +0200
Subject: [PATCH 128/788] Python: Modernize `WebAppConstantSecretKey`
---
.../WebAppConstantSecretKey.ql | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/python/ql/src/experimental/Security/CWE-287-ConstantSecretKey/WebAppConstantSecretKey.ql b/python/ql/src/experimental/Security/CWE-287-ConstantSecretKey/WebAppConstantSecretKey.ql
index 38548628237..7bb35012b38 100644
--- a/python/ql/src/experimental/Security/CWE-287-ConstantSecretKey/WebAppConstantSecretKey.ql
+++ b/python/ql/src/experimental/Security/CWE-287-ConstantSecretKey/WebAppConstantSecretKey.ql
@@ -25,7 +25,7 @@ newtype TFrameWork =
Flask() or
Django()
-module WebAppConstantSecretKeyConfig implements DataFlow::StateConfigSig {
+private module WebAppConstantSecretKeyConfig implements DataFlow::StateConfigSig {
class FlowState = TFrameWork;
predicate isSource(DataFlow::Node source, FlowState state) {
@@ -54,11 +54,11 @@ module WebAppConstantSecretKeyConfig implements DataFlow::StateConfigSig {
}
}
-module WebAppConstantSecretKey = TaintTracking::GlobalWithState;
+module WebAppConstantSecretKeyFlow = TaintTracking::GlobalWithState;
-import WebAppConstantSecretKey::PathGraph
+import WebAppConstantSecretKeyFlow::PathGraph
-from WebAppConstantSecretKey::PathNode source, WebAppConstantSecretKey::PathNode sink
-where WebAppConstantSecretKey::flowPath(source, sink)
+from WebAppConstantSecretKeyFlow::PathNode source, WebAppConstantSecretKeyFlow::PathNode sink
+where WebAppConstantSecretKeyFlow::flowPath(source, sink)
select sink, source, sink, "The SECRET_KEY config variable is assigned by $@.", source,
" this constant String"
From ed0e441567bcec715250380b891150a1014c49b6 Mon Sep 17 00:00:00 2001
From: Rasmus Wriedt Larsen
Date: Fri, 25 Aug 2023 22:28:36 +0200
Subject: [PATCH 129/788] Python: Accept missing `DataflowQueryTest`
implementation for now
---
.../DataflowQueryTest.expected | 15 ++++++++++++++-
1 file changed, 14 insertions(+), 1 deletion(-)
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-022-UnsafeUnpacking/DataflowQueryTest.expected b/python/ql/test/experimental/query-tests/Security/CWE-022-UnsafeUnpacking/DataflowQueryTest.expected
index 04431311999..483a93aaf99 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-022-UnsafeUnpacking/DataflowQueryTest.expected
+++ b/python/ql/test/experimental/query-tests/Security/CWE-022-UnsafeUnpacking/DataflowQueryTest.expected
@@ -1,3 +1,16 @@
missingAnnotationOnSink
-failures
testFailures
+| UnsafeUnpack.py:19:59:19:71 | Comment # $result=BAD | Missing result:result=BAD |
+| UnsafeUnpack.py:34:52:34:64 | Comment # $result=BAD | Missing result:result=BAD |
+| UnsafeUnpack.py:48:50:48:62 | Comment # $result=BAD | Missing result:result=BAD |
+| UnsafeUnpack.py:52:50:52:62 | Comment # $result=BAD | Missing result:result=BAD |
+| UnsafeUnpack.py:66:50:66:62 | Comment # $result=BAD | Missing result:result=BAD |
+| UnsafeUnpack.py:87:42:87:54 | Comment # $result=BAD | Missing result:result=BAD |
+| UnsafeUnpack.py:105:55:105:67 | Comment # $result=BAD | Missing result:result=BAD |
+| UnsafeUnpack.py:112:56:112:68 | Comment # $result=BAD | Missing result:result=BAD |
+| UnsafeUnpack.py:120:71:120:83 | Comment # $result=BAD | Missing result:result=BAD |
+| UnsafeUnpack.py:142:54:142:66 | Comment # $result=BAD | Missing result:result=BAD |
+| UnsafeUnpack.py:167:75:167:90 | Comment # $result=BAD | Missing result:result=BAD |
+| UnsafeUnpack.py:176:64:176:76 | Comment # $result=BAD | Missing result:result=BAD |
+| UnsafeUnpack.py:201:47:201:59 | Comment # $result=BAD | Missing result:result=BAD |
+failures
From 6961ca5234b5357775c1a8f32aa4ef8c4d6aa644 Mon Sep 17 00:00:00 2001
From: Rasmus Wriedt Larsen
Date: Mon, 28 Aug 2023 11:10:10 +0200
Subject: [PATCH 130/788] Python: Rename to `EmailXss`
---
.../CWE-079/{ReflectedXSS.ql => EmailXss.ql} | 8 ++++----
.../dataflow/{ReflectedXSS.qll => EmailXss.qll} | 13 ++++---------
.../{ReflectedXSS.expected => EmailXss.expected} | 0
.../query-tests/Security/CWE-079/EmailXss.qlref | 1 +
.../query-tests/Security/CWE-079/ReflectedXSS.qlref | 1 -
5 files changed, 9 insertions(+), 14 deletions(-)
rename python/ql/src/experimental/Security/CWE-079/{ReflectedXSS.ql => EmailXss.ql} (72%)
rename python/ql/src/experimental/semmle/python/security/dataflow/{ReflectedXSS.qll => EmailXss.qll} (70%)
rename python/ql/test/experimental/query-tests/Security/CWE-079/{ReflectedXSS.expected => EmailXss.expected} (100%)
create mode 100644 python/ql/test/experimental/query-tests/Security/CWE-079/EmailXss.qlref
delete mode 100644 python/ql/test/experimental/query-tests/Security/CWE-079/ReflectedXSS.qlref
diff --git a/python/ql/src/experimental/Security/CWE-079/ReflectedXSS.ql b/python/ql/src/experimental/Security/CWE-079/EmailXss.ql
similarity index 72%
rename from python/ql/src/experimental/Security/CWE-079/ReflectedXSS.ql
rename to python/ql/src/experimental/Security/CWE-079/EmailXss.ql
index 1f5cc601c09..046efdeba89 100644
--- a/python/ql/src/experimental/Security/CWE-079/ReflectedXSS.ql
+++ b/python/ql/src/experimental/Security/CWE-079/EmailXss.ql
@@ -15,10 +15,10 @@
// determine precision above
import python
-import experimental.semmle.python.security.dataflow.ReflectedXSS
-import ReflectedXSSFlow::PathGraph
+import experimental.semmle.python.security.dataflow.EmailXss
+import EmailXssFlow::PathGraph
-from ReflectedXSSFlow::PathNode source, ReflectedXSSFlow::PathNode sink
-where ReflectedXSSFlow::flowPath(source, sink)
+from EmailXssFlow::PathNode source, EmailXssFlow::PathNode sink
+where EmailXssFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "Cross-site scripting vulnerability due to $@.",
source.getNode(), "a user-provided value"
diff --git a/python/ql/src/experimental/semmle/python/security/dataflow/ReflectedXSS.qll b/python/ql/src/experimental/semmle/python/security/dataflow/EmailXss.qll
similarity index 70%
rename from python/ql/src/experimental/semmle/python/security/dataflow/ReflectedXSS.qll
rename to python/ql/src/experimental/semmle/python/security/dataflow/EmailXss.qll
index b12f54dedf8..88e9af89ba6 100644
--- a/python/ql/src/experimental/semmle/python/security/dataflow/ReflectedXSS.qll
+++ b/python/ql/src/experimental/semmle/python/security/dataflow/EmailXss.qll
@@ -1,6 +1,5 @@
/**
- * Provides a taint-tracking configuration for detecting reflected server-side
- * cross-site scripting vulnerabilities.
+ * Provides a taint-tracking configuration for detecting "Email XSS" vulnerabilities.
*/
import python
@@ -12,11 +11,7 @@ import experimental.semmle.python.Concepts
import semmle.python.Concepts
import semmle.python.ApiGraphs
-/**
- * A taint-tracking configuration for detecting reflected server-side cross-site
- * scripting vulnerabilities.
- */
-private module ReflectedXSSConfig implements DataFlow::ConfigSig {
+private module EmailXssConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
predicate isSink(DataFlow::Node sink) { sink = any(EmailSender email).getHtmlBody() }
@@ -41,5 +36,5 @@ private module ReflectedXSSConfig implements DataFlow::ConfigSig {
}
}
-/** Global taint-tracking for detecting "TODO" vulnerabilities. */
-module ReflectedXSSFlow = TaintTracking::Global;
+/** Global taint-tracking for detecting "Email XSS" vulnerabilities. */
+module EmailXssFlow = TaintTracking::Global;
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-079/ReflectedXSS.expected b/python/ql/test/experimental/query-tests/Security/CWE-079/EmailXss.expected
similarity index 100%
rename from python/ql/test/experimental/query-tests/Security/CWE-079/ReflectedXSS.expected
rename to python/ql/test/experimental/query-tests/Security/CWE-079/EmailXss.expected
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-079/EmailXss.qlref b/python/ql/test/experimental/query-tests/Security/CWE-079/EmailXss.qlref
new file mode 100644
index 00000000000..fcc132dd66c
--- /dev/null
+++ b/python/ql/test/experimental/query-tests/Security/CWE-079/EmailXss.qlref
@@ -0,0 +1 @@
+experimental/Security/CWE-079/EmailXss.ql
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-079/ReflectedXSS.qlref b/python/ql/test/experimental/query-tests/Security/CWE-079/ReflectedXSS.qlref
deleted file mode 100644
index dec87309b29..00000000000
--- a/python/ql/test/experimental/query-tests/Security/CWE-079/ReflectedXSS.qlref
+++ /dev/null
@@ -1 +0,0 @@
-experimental/Security/CWE-079/ReflectedXSS.ql
From 5ba8e102eba5750cdb58680d2388e5c16ae35759 Mon Sep 17 00:00:00 2001
From: Rasmus Wriedt Larsen
Date: Mon, 28 Aug 2023 11:30:58 +0200
Subject: [PATCH 131/788] Python: Adopt tests to new `DataflowQueryTest`
Since we want to know the _sinks_ and not just the flow, we need to
expose the config as well :|
---
.../security/dataflow/CommandInjectionQuery.qll | 2 +-
.../python/security/dataflow/PathInjectionQuery.qll | 2 +-
.../UnsafeShellCommandConstructionQuery.qll | 2 +-
.../src/experimental/Security/UnsafeUnpackQuery.qll | 2 +-
.../DataflowQueryTest.expected | 13 -------------
.../CWE-022-UnsafeUnpacking/DataflowQueryTest.ql | 2 +-
.../CWE-022-PathInjection/DataflowQueryTest.ql | 2 +-
.../CWE-078-CommandInjection/DataflowQueryTest.ql | 2 +-
.../DataflowQueryTest.ql | 2 +-
9 files changed, 8 insertions(+), 21 deletions(-)
diff --git a/python/ql/lib/semmle/python/security/dataflow/CommandInjectionQuery.qll b/python/ql/lib/semmle/python/security/dataflow/CommandInjectionQuery.qll
index b9c1fb09043..ce4b88b419d 100644
--- a/python/ql/lib/semmle/python/security/dataflow/CommandInjectionQuery.qll
+++ b/python/ql/lib/semmle/python/security/dataflow/CommandInjectionQuery.qll
@@ -30,7 +30,7 @@ deprecated class Configuration extends TaintTracking::Configuration {
}
}
-private module CommandInjectionConfig implements DataFlow::ConfigSig {
+module CommandInjectionConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof Source }
predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
diff --git a/python/ql/lib/semmle/python/security/dataflow/PathInjectionQuery.qll b/python/ql/lib/semmle/python/security/dataflow/PathInjectionQuery.qll
index 307c16da05d..b185098dcb8 100644
--- a/python/ql/lib/semmle/python/security/dataflow/PathInjectionQuery.qll
+++ b/python/ql/lib/semmle/python/security/dataflow/PathInjectionQuery.qll
@@ -88,7 +88,7 @@ class NormalizedUnchecked extends DataFlow::FlowState {
*
* Such checks are ineffective in the `NotNormalized` state.
*/
-private module PathInjectionConfig implements DataFlow::StateConfigSig {
+module PathInjectionConfig implements DataFlow::StateConfigSig {
class FlowState = DataFlow::FlowState;
predicate isSource(DataFlow::Node source, FlowState state) {
diff --git a/python/ql/lib/semmle/python/security/dataflow/UnsafeShellCommandConstructionQuery.qll b/python/ql/lib/semmle/python/security/dataflow/UnsafeShellCommandConstructionQuery.qll
index 14a702a405e..2a68110859f 100644
--- a/python/ql/lib/semmle/python/security/dataflow/UnsafeShellCommandConstructionQuery.qll
+++ b/python/ql/lib/semmle/python/security/dataflow/UnsafeShellCommandConstructionQuery.qll
@@ -35,7 +35,7 @@ deprecated class Configuration extends TaintTracking::Configuration {
}
}
-private module UnsafeShellCommandConstructionConfig implements DataFlow::ConfigSig {
+module UnsafeShellCommandConstructionConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof Source }
predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
diff --git a/python/ql/src/experimental/Security/UnsafeUnpackQuery.qll b/python/ql/src/experimental/Security/UnsafeUnpackQuery.qll
index 7c297d975a4..338a5555c57 100644
--- a/python/ql/src/experimental/Security/UnsafeUnpackQuery.qll
+++ b/python/ql/src/experimental/Security/UnsafeUnpackQuery.qll
@@ -39,7 +39,7 @@ class AllTarfileOpens extends API::CallNode {
}
}
-private module UnsafeUnpackConfig implements DataFlow::ConfigSig {
+module UnsafeUnpackConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
// A source coming from a remote location
source instanceof RemoteFlowSource
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-022-UnsafeUnpacking/DataflowQueryTest.expected b/python/ql/test/experimental/query-tests/Security/CWE-022-UnsafeUnpacking/DataflowQueryTest.expected
index 483a93aaf99..9ce23b4c553 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-022-UnsafeUnpacking/DataflowQueryTest.expected
+++ b/python/ql/test/experimental/query-tests/Security/CWE-022-UnsafeUnpacking/DataflowQueryTest.expected
@@ -1,16 +1,3 @@
missingAnnotationOnSink
testFailures
-| UnsafeUnpack.py:19:59:19:71 | Comment # $result=BAD | Missing result:result=BAD |
-| UnsafeUnpack.py:34:52:34:64 | Comment # $result=BAD | Missing result:result=BAD |
-| UnsafeUnpack.py:48:50:48:62 | Comment # $result=BAD | Missing result:result=BAD |
-| UnsafeUnpack.py:52:50:52:62 | Comment # $result=BAD | Missing result:result=BAD |
-| UnsafeUnpack.py:66:50:66:62 | Comment # $result=BAD | Missing result:result=BAD |
-| UnsafeUnpack.py:87:42:87:54 | Comment # $result=BAD | Missing result:result=BAD |
-| UnsafeUnpack.py:105:55:105:67 | Comment # $result=BAD | Missing result:result=BAD |
-| UnsafeUnpack.py:112:56:112:68 | Comment # $result=BAD | Missing result:result=BAD |
-| UnsafeUnpack.py:120:71:120:83 | Comment # $result=BAD | Missing result:result=BAD |
-| UnsafeUnpack.py:142:54:142:66 | Comment # $result=BAD | Missing result:result=BAD |
-| UnsafeUnpack.py:167:75:167:90 | Comment # $result=BAD | Missing result:result=BAD |
-| UnsafeUnpack.py:176:64:176:76 | Comment # $result=BAD | Missing result:result=BAD |
-| UnsafeUnpack.py:201:47:201:59 | Comment # $result=BAD | Missing result:result=BAD |
failures
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-022-UnsafeUnpacking/DataflowQueryTest.ql b/python/ql/test/experimental/query-tests/Security/CWE-022-UnsafeUnpacking/DataflowQueryTest.ql
index 91a6cdaa14a..ed7d650f536 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-022-UnsafeUnpacking/DataflowQueryTest.ql
+++ b/python/ql/test/experimental/query-tests/Security/CWE-022-UnsafeUnpacking/DataflowQueryTest.ql
@@ -1,4 +1,4 @@
import python
import experimental.dataflow.TestUtil.DataflowQueryTest
import experimental.Security.UnsafeUnpackQuery
-import FromLegacyConfiguration
+import FromTaintTrackingConfig
diff --git a/python/ql/test/query-tests/Security/CWE-022-PathInjection/DataflowQueryTest.ql b/python/ql/test/query-tests/Security/CWE-022-PathInjection/DataflowQueryTest.ql
index 91ba1765724..90761391ce7 100644
--- a/python/ql/test/query-tests/Security/CWE-022-PathInjection/DataflowQueryTest.ql
+++ b/python/ql/test/query-tests/Security/CWE-022-PathInjection/DataflowQueryTest.ql
@@ -1,4 +1,4 @@
import python
import experimental.dataflow.TestUtil.DataflowQueryTest
import semmle.python.security.dataflow.PathInjectionQuery
-import FromLegacyConfiguration
+import FromTaintTrackingStateConfig
diff --git a/python/ql/test/query-tests/Security/CWE-078-CommandInjection/DataflowQueryTest.ql b/python/ql/test/query-tests/Security/CWE-078-CommandInjection/DataflowQueryTest.ql
index ecb787218b1..df745b4ee8c 100644
--- a/python/ql/test/query-tests/Security/CWE-078-CommandInjection/DataflowQueryTest.ql
+++ b/python/ql/test/query-tests/Security/CWE-078-CommandInjection/DataflowQueryTest.ql
@@ -1,4 +1,4 @@
import python
import experimental.dataflow.TestUtil.DataflowQueryTest
import semmle.python.security.dataflow.CommandInjectionQuery
-import FromLegacyConfiguration
+import FromTaintTrackingConfig
diff --git a/python/ql/test/query-tests/Security/CWE-078-UnsafeShellCommandConstruction/DataflowQueryTest.ql b/python/ql/test/query-tests/Security/CWE-078-UnsafeShellCommandConstruction/DataflowQueryTest.ql
index b00d364b853..b2602b2b25c 100644
--- a/python/ql/test/query-tests/Security/CWE-078-UnsafeShellCommandConstruction/DataflowQueryTest.ql
+++ b/python/ql/test/query-tests/Security/CWE-078-UnsafeShellCommandConstruction/DataflowQueryTest.ql
@@ -1,4 +1,4 @@
import python
import experimental.dataflow.TestUtil.DataflowQueryTest
import semmle.python.security.dataflow.UnsafeShellCommandConstructionQuery
-import FromLegacyConfiguration
+import FromTaintTrackingConfig
From 98538d237e27b3b0eca8de81c369acf60525ade6 Mon Sep 17 00:00:00 2001
From: Rasmus Wriedt Larsen
Date: Mon, 28 Aug 2023 11:56:41 +0200
Subject: [PATCH 132/788] Python: Autoformat
---
.../Security/CWE-176/UnicodeBypassValidationQuery.qll | 3 +--
.../PossibleTimingAttackAgainstHash.ql | 4 +++-
.../PossibleTimingAttackAgainstSensitiveInfo.ql | 6 ++++--
.../src/experimental/Security/CWE-338/InsecureRandomness.ql | 1 -
.../Security/CWE-348/ClientSuppliedIpUsedInSecurityCheck.ql | 4 ++--
.../ql/src/experimental/Security/CWE-614/CookieInjection.ql | 4 +---
.../experimental/semmle/python/security/TimingAttack.qll | 2 +-
7 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/python/ql/src/experimental/Security/CWE-176/UnicodeBypassValidationQuery.qll b/python/ql/src/experimental/Security/CWE-176/UnicodeBypassValidationQuery.qll
index 169c71a0c09..a5d9d53b084 100644
--- a/python/ql/src/experimental/Security/CWE-176/UnicodeBypassValidationQuery.qll
+++ b/python/ql/src/experimental/Security/CWE-176/UnicodeBypassValidationQuery.qll
@@ -36,8 +36,7 @@ private module UnicodeBypassValidationConfig implements DataFlow::StateConfigSig
}
predicate isAdditionalFlowStep(
- DataFlow::Node nodeFrom, FlowState stateFrom, DataFlow::Node nodeTo,
- FlowState stateTo
+ DataFlow::Node nodeFrom, FlowState stateFrom, DataFlow::Node nodeTo, FlowState stateTo
) {
(
exists(Escaping escaping | nodeFrom = escaping.getAnInput() and nodeTo = escaping.getOutput())
diff --git a/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstHash/PossibleTimingAttackAgainstHash.ql b/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstHash/PossibleTimingAttackAgainstHash.ql
index 7a6a3f946bc..c28b51f02d7 100644
--- a/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstHash/PossibleTimingAttackAgainstHash.ql
+++ b/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstHash/PossibleTimingAttackAgainstHash.ql
@@ -32,7 +32,9 @@ module PossibleTimingAttackAgainstHashFlow = TaintTracking::Global;
+ TaintTracking::Global;
import PossibleTimingAttackAgainstSensitiveInfoFlow::PathGraph
-from PossibleTimingAttackAgainstSensitiveInfoFlow::PathNode source, PossibleTimingAttackAgainstSensitiveInfoFlow::PathNode sink
+from
+ PossibleTimingAttackAgainstSensitiveInfoFlow::PathNode source,
+ PossibleTimingAttackAgainstSensitiveInfoFlow::PathNode sink
where PossibleTimingAttackAgainstSensitiveInfoFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "Timing attack against $@ validation.", source.getNode(),
"client-supplied token"
diff --git a/python/ql/src/experimental/Security/CWE-338/InsecureRandomness.ql b/python/ql/src/experimental/Security/CWE-338/InsecureRandomness.ql
index 3e48068f015..1991300726b 100644
--- a/python/ql/src/experimental/Security/CWE-338/InsecureRandomness.ql
+++ b/python/ql/src/experimental/Security/CWE-338/InsecureRandomness.ql
@@ -16,7 +16,6 @@
import python
import experimental.semmle.python.security.InsecureRandomness
import semmle.python.dataflow.new.DataFlow
-
import InsecureRandomness::Flow::PathGraph
from InsecureRandomness::Flow::PathNode source, InsecureRandomness::Flow::PathNode sink
diff --git a/python/ql/src/experimental/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheck.ql b/python/ql/src/experimental/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheck.ql
index b1d598f4749..51d6c9b6652 100644
--- a/python/ql/src/experimental/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheck.ql
+++ b/python/ql/src/experimental/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheck.ql
@@ -47,9 +47,9 @@ private module ClientSuppliedIpUsedInSecurityCheckConfig implements DataFlow::Co
}
}
-
/** Global taint-tracking for detecting "client ip used in security check" vulnerabilities. */
-module ClientSuppliedIpUsedInSecurityCheckFlow = TaintTracking::Global;
+module ClientSuppliedIpUsedInSecurityCheckFlow =
+ TaintTracking::Global;
from
ClientSuppliedIpUsedInSecurityCheckFlow::PathNode source,
diff --git a/python/ql/src/experimental/Security/CWE-614/CookieInjection.ql b/python/ql/src/experimental/Security/CWE-614/CookieInjection.ql
index 60e0fc4a0e4..4193e37dee2 100644
--- a/python/ql/src/experimental/Security/CWE-614/CookieInjection.ql
+++ b/python/ql/src/experimental/Security/CWE-614/CookieInjection.ql
@@ -17,9 +17,7 @@ import experimental.semmle.python.CookieHeader
import experimental.semmle.python.security.injection.CookieInjection
import CookieInjectionFlow::PathGraph
-from
- CookieInjectionFlow::PathNode source, CookieInjectionFlow::PathNode sink,
- string insecure
+from CookieInjectionFlow::PathNode source, CookieInjectionFlow::PathNode sink, string insecure
where
CookieInjectionFlow::flowPath(source, sink) and
if exists(sink.getNode().(CookieSink))
diff --git a/python/ql/src/experimental/semmle/python/security/TimingAttack.qll b/python/ql/src/experimental/semmle/python/security/TimingAttack.qll
index 37d3a35158d..23bd4dc268d 100644
--- a/python/ql/src/experimental/semmle/python/security/TimingAttack.qll
+++ b/python/ql/src/experimental/semmle/python/security/TimingAttack.qll
@@ -263,7 +263,7 @@ private string sensitiveheaders() {
/**
* A config that tracks data flow from remote user input to Variable that hold sensitive info
*/
-module UserInputSecretConfig implements DataFlow::ConfigSig {
+module UserInputSecretConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
predicate isSink(DataFlow::Node sink) { sink.asExpr() instanceof CredentialExpr }
From efec4e7ebf4d4deec3f8838fd20fc0bc0beb1147 Mon Sep 17 00:00:00 2001
From: Rasmus Wriedt Larsen
Date: Mon, 28 Aug 2023 11:58:13 +0200
Subject: [PATCH 133/788] Python: Add missing qldocs
---
.../semmle/python/security/dataflow/CommandInjectionQuery.qll | 3 +++
.../security/dataflow/UnsafeShellCommandConstructionQuery.qll | 3 +++
2 files changed, 6 insertions(+)
diff --git a/python/ql/lib/semmle/python/security/dataflow/CommandInjectionQuery.qll b/python/ql/lib/semmle/python/security/dataflow/CommandInjectionQuery.qll
index ce4b88b419d..80ca46dafa9 100644
--- a/python/ql/lib/semmle/python/security/dataflow/CommandInjectionQuery.qll
+++ b/python/ql/lib/semmle/python/security/dataflow/CommandInjectionQuery.qll
@@ -30,6 +30,9 @@ deprecated class Configuration extends TaintTracking::Configuration {
}
}
+/**
+ * A taint-tracking configuration for detecting "command injection" vulnerabilities.
+ */
module CommandInjectionConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof Source }
diff --git a/python/ql/lib/semmle/python/security/dataflow/UnsafeShellCommandConstructionQuery.qll b/python/ql/lib/semmle/python/security/dataflow/UnsafeShellCommandConstructionQuery.qll
index 2a68110859f..d829f08608f 100644
--- a/python/ql/lib/semmle/python/security/dataflow/UnsafeShellCommandConstructionQuery.qll
+++ b/python/ql/lib/semmle/python/security/dataflow/UnsafeShellCommandConstructionQuery.qll
@@ -35,6 +35,9 @@ deprecated class Configuration extends TaintTracking::Configuration {
}
}
+/**
+ * A taint-tracking configuration for detecting "shell command constructed from library input" vulnerabilities.
+ */
module UnsafeShellCommandConstructionConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof Source }
From 996364d6ee4dbd24ae3b070ae30929a74fb122ed Mon Sep 17 00:00:00 2001
From: Rasmus Wriedt Larsen
Date: Mon, 28 Aug 2023 12:01:49 +0200
Subject: [PATCH 134/788] Python: Fix naming style guide violations
---
.../PossibleTimingAttackAgainstHash.ql | 5 +++--
.../Security/CWE-340/TokenBuiltFromUUID.ql | 10 +++++-----
.../experimental/Security/CWE-522/LDAPInsecureAuth.ql | 6 +++---
.../semmle/python/security/InsecureRandomness.qll | 4 ++--
.../semmle/python/security/LDAPInsecureAuth.qll | 4 ++--
5 files changed, 15 insertions(+), 14 deletions(-)
diff --git a/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstHash/PossibleTimingAttackAgainstHash.ql b/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstHash/PossibleTimingAttackAgainstHash.ql
index c28b51f02d7..82ba11c1d4b 100644
--- a/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstHash/PossibleTimingAttackAgainstHash.ql
+++ b/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstHash/PossibleTimingAttackAgainstHash.ql
@@ -22,13 +22,14 @@ import experimental.semmle.python.security.TimingAttack
* A configuration that tracks data flow from cryptographic operations
* to equality test
*/
-private module PossibleTimingAttackAgainstHash implements DataFlow::ConfigSig {
+private module PossibleTimingAttackAgainstHashConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof ProduceCryptoCall }
predicate isSink(DataFlow::Node sink) { sink instanceof NonConstantTimeComparisonSink }
}
-module PossibleTimingAttackAgainstHashFlow = TaintTracking::Global;
+module PossibleTimingAttackAgainstHashFlow =
+ TaintTracking::Global;
import PossibleTimingAttackAgainstHashFlow::PathGraph
diff --git a/python/ql/src/experimental/Security/CWE-340/TokenBuiltFromUUID.ql b/python/ql/src/experimental/Security/CWE-340/TokenBuiltFromUUID.ql
index e4310a68e8f..b91f2dd6237 100644
--- a/python/ql/src/experimental/Security/CWE-340/TokenBuiltFromUUID.ql
+++ b/python/ql/src/experimental/Security/CWE-340/TokenBuiltFromUUID.ql
@@ -39,7 +39,7 @@ class TokenAssignmentValueSink extends DataFlow::Node {
}
}
-private module TokenBuiltFromUUIDConfig implements DataFlow::ConfigSig {
+private module TokenBuiltFromUuidConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof PredictableResultSource }
predicate isSink(DataFlow::Node sink) { sink instanceof TokenAssignmentValueSink }
@@ -54,10 +54,10 @@ private module TokenBuiltFromUUIDConfig implements DataFlow::ConfigSig {
}
/** Global taint-tracking for detecting "TokenBuiltFromUUID" vulnerabilities. */
-module TokenBuiltFromUUIDFlow = TaintTracking::Global;
+module TokenBuiltFromUuidFlow = TaintTracking::Global;
-import TokenBuiltFromUUIDFlow::PathGraph
+import TokenBuiltFromUuidFlow::PathGraph
-from TokenBuiltFromUUIDFlow::PathNode source, TokenBuiltFromUUIDFlow::PathNode sink
-where TokenBuiltFromUUIDFlow::flowPath(source, sink)
+from TokenBuiltFromUuidFlow::PathNode source, TokenBuiltFromUuidFlow::PathNode sink
+where TokenBuiltFromUuidFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "Token built from $@.", source.getNode(), "predictable value"
diff --git a/python/ql/src/experimental/Security/CWE-522/LDAPInsecureAuth.ql b/python/ql/src/experimental/Security/CWE-522/LDAPInsecureAuth.ql
index e870a92e9ab..284f20b2c39 100644
--- a/python/ql/src/experimental/Security/CWE-522/LDAPInsecureAuth.ql
+++ b/python/ql/src/experimental/Security/CWE-522/LDAPInsecureAuth.ql
@@ -12,9 +12,9 @@
// determine precision above
import python
-import LDAPInsecureAuthFlow::PathGraph
import experimental.semmle.python.security.LDAPInsecureAuth
+import LdapInsecureAuthFlow::PathGraph
-from LDAPInsecureAuthFlow::PathNode source, LDAPInsecureAuthFlow::PathNode sink
-where LDAPInsecureAuthFlow::flowPath(source, sink)
+from LdapInsecureAuthFlow::PathNode source, LdapInsecureAuthFlow::PathNode sink
+where LdapInsecureAuthFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "This LDAP host is authenticated insecurely."
diff --git a/python/ql/src/experimental/semmle/python/security/InsecureRandomness.qll b/python/ql/src/experimental/semmle/python/security/InsecureRandomness.qll
index c71b461d20a..5a32a887bd5 100644
--- a/python/ql/src/experimental/semmle/python/security/InsecureRandomness.qll
+++ b/python/ql/src/experimental/semmle/python/security/InsecureRandomness.qll
@@ -21,7 +21,7 @@ module InsecureRandomness {
* A taint-tracking configuration for reasoning about random values that are
* not cryptographically secure.
*/
- private module Configuration implements DataFlow::ConfigSig {
+ private module Config implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof Source }
predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
@@ -30,5 +30,5 @@ module InsecureRandomness {
}
/** Global taint-tracking for detecting "random values that are not cryptographically secure" vulnerabilities. */
- module Flow = TaintTracking::Global;
+ module Flow = TaintTracking::Global;
}
diff --git a/python/ql/src/experimental/semmle/python/security/LDAPInsecureAuth.qll b/python/ql/src/experimental/semmle/python/security/LDAPInsecureAuth.qll
index 133bb1810cc..e8249dcdff7 100644
--- a/python/ql/src/experimental/semmle/python/security/LDAPInsecureAuth.qll
+++ b/python/ql/src/experimental/semmle/python/security/LDAPInsecureAuth.qll
@@ -88,7 +88,7 @@ class LdapStringVar extends BinaryExpr {
/**
* A taint-tracking configuration for detecting LDAP insecure authentications.
*/
-private module LDAPInsecureAuthConfig implements DataFlow::ConfigSig {
+private module LdapInsecureAuthConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
source instanceof RemoteFlowSource or
source.asExpr() instanceof LdapFullHost or
@@ -104,4 +104,4 @@ private module LDAPInsecureAuthConfig implements DataFlow::ConfigSig {
}
/** Global taint-tracking for detecting "LDAP insecure authentications" vulnerabilities. */
-module LDAPInsecureAuthFlow = TaintTracking::Global;
+module LdapInsecureAuthFlow = TaintTracking::Global;
From c665c21d83901059429fe585dd1415930e6e4ba3 Mon Sep 17 00:00:00 2001
From: Rasmus Wriedt Larsen
Date: Mon, 28 Aug 2023 12:02:52 +0200
Subject: [PATCH 135/788] Python: More style-guide renaming
Split it into multiple commits to make it easier to review.
---
.../CWE-522/{LDAPInsecureAuth.qhelp => LdapInsecureAuth.qhelp} | 0
.../CWE-522/{LDAPInsecureAuth.ql => LdapInsecureAuth.ql} | 2 +-
.../security/{LDAPInsecureAuth.qll => LdapInsecureAuth.qll} | 0
.../Security/CWE-522-global-option/LDAPInsecureAuth.qlref | 1 -
.../{LDAPInsecureAuth.expected => LdapInsecureAuth.expected} | 0
.../Security/CWE-522-global-option/LdapInsecureAuth.qlref | 1 +
.../query-tests/Security/CWE-522/LDAPInsecureAuth.qlref | 1 -
.../{LDAPInsecureAuth.expected => LdapInsecureAuth.expected} | 0
.../query-tests/Security/CWE-522/LdapInsecureAuth.qlref | 1 +
9 files changed, 3 insertions(+), 3 deletions(-)
rename python/ql/src/experimental/Security/CWE-522/{LDAPInsecureAuth.qhelp => LdapInsecureAuth.qhelp} (100%)
rename python/ql/src/experimental/Security/CWE-522/{LDAPInsecureAuth.ql => LdapInsecureAuth.ql} (90%)
rename python/ql/src/experimental/semmle/python/security/{LDAPInsecureAuth.qll => LdapInsecureAuth.qll} (100%)
delete mode 100644 python/ql/test/experimental/query-tests/Security/CWE-522-global-option/LDAPInsecureAuth.qlref
rename python/ql/test/experimental/query-tests/Security/CWE-522-global-option/{LDAPInsecureAuth.expected => LdapInsecureAuth.expected} (100%)
create mode 100644 python/ql/test/experimental/query-tests/Security/CWE-522-global-option/LdapInsecureAuth.qlref
delete mode 100644 python/ql/test/experimental/query-tests/Security/CWE-522/LDAPInsecureAuth.qlref
rename python/ql/test/experimental/query-tests/Security/CWE-522/{LDAPInsecureAuth.expected => LdapInsecureAuth.expected} (100%)
create mode 100644 python/ql/test/experimental/query-tests/Security/CWE-522/LdapInsecureAuth.qlref
diff --git a/python/ql/src/experimental/Security/CWE-522/LDAPInsecureAuth.qhelp b/python/ql/src/experimental/Security/CWE-522/LdapInsecureAuth.qhelp
similarity index 100%
rename from python/ql/src/experimental/Security/CWE-522/LDAPInsecureAuth.qhelp
rename to python/ql/src/experimental/Security/CWE-522/LdapInsecureAuth.qhelp
diff --git a/python/ql/src/experimental/Security/CWE-522/LDAPInsecureAuth.ql b/python/ql/src/experimental/Security/CWE-522/LdapInsecureAuth.ql
similarity index 90%
rename from python/ql/src/experimental/Security/CWE-522/LDAPInsecureAuth.ql
rename to python/ql/src/experimental/Security/CWE-522/LdapInsecureAuth.ql
index 284f20b2c39..8b72780d91a 100644
--- a/python/ql/src/experimental/Security/CWE-522/LDAPInsecureAuth.ql
+++ b/python/ql/src/experimental/Security/CWE-522/LdapInsecureAuth.ql
@@ -12,7 +12,7 @@
// determine precision above
import python
-import experimental.semmle.python.security.LDAPInsecureAuth
+import experimental.semmle.python.security.LdapInsecureAuth
import LdapInsecureAuthFlow::PathGraph
from LdapInsecureAuthFlow::PathNode source, LdapInsecureAuthFlow::PathNode sink
diff --git a/python/ql/src/experimental/semmle/python/security/LDAPInsecureAuth.qll b/python/ql/src/experimental/semmle/python/security/LdapInsecureAuth.qll
similarity index 100%
rename from python/ql/src/experimental/semmle/python/security/LDAPInsecureAuth.qll
rename to python/ql/src/experimental/semmle/python/security/LdapInsecureAuth.qll
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-522-global-option/LDAPInsecureAuth.qlref b/python/ql/test/experimental/query-tests/Security/CWE-522-global-option/LDAPInsecureAuth.qlref
deleted file mode 100644
index 8bb2c1e9b52..00000000000
--- a/python/ql/test/experimental/query-tests/Security/CWE-522-global-option/LDAPInsecureAuth.qlref
+++ /dev/null
@@ -1 +0,0 @@
-experimental/Security/CWE-522/LDAPInsecureAuth.ql
\ No newline at end of file
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-522-global-option/LDAPInsecureAuth.expected b/python/ql/test/experimental/query-tests/Security/CWE-522-global-option/LdapInsecureAuth.expected
similarity index 100%
rename from python/ql/test/experimental/query-tests/Security/CWE-522-global-option/LDAPInsecureAuth.expected
rename to python/ql/test/experimental/query-tests/Security/CWE-522-global-option/LdapInsecureAuth.expected
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-522-global-option/LdapInsecureAuth.qlref b/python/ql/test/experimental/query-tests/Security/CWE-522-global-option/LdapInsecureAuth.qlref
new file mode 100644
index 00000000000..7b867cb3186
--- /dev/null
+++ b/python/ql/test/experimental/query-tests/Security/CWE-522-global-option/LdapInsecureAuth.qlref
@@ -0,0 +1 @@
+experimental/Security/CWE-522/LdapInsecureAuth.ql
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-522/LDAPInsecureAuth.qlref b/python/ql/test/experimental/query-tests/Security/CWE-522/LDAPInsecureAuth.qlref
deleted file mode 100644
index 8bb2c1e9b52..00000000000
--- a/python/ql/test/experimental/query-tests/Security/CWE-522/LDAPInsecureAuth.qlref
+++ /dev/null
@@ -1 +0,0 @@
-experimental/Security/CWE-522/LDAPInsecureAuth.ql
\ No newline at end of file
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-522/LDAPInsecureAuth.expected b/python/ql/test/experimental/query-tests/Security/CWE-522/LdapInsecureAuth.expected
similarity index 100%
rename from python/ql/test/experimental/query-tests/Security/CWE-522/LDAPInsecureAuth.expected
rename to python/ql/test/experimental/query-tests/Security/CWE-522/LdapInsecureAuth.expected
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-522/LdapInsecureAuth.qlref b/python/ql/test/experimental/query-tests/Security/CWE-522/LdapInsecureAuth.qlref
new file mode 100644
index 00000000000..7b867cb3186
--- /dev/null
+++ b/python/ql/test/experimental/query-tests/Security/CWE-522/LdapInsecureAuth.qlref
@@ -0,0 +1 @@
+experimental/Security/CWE-522/LdapInsecureAuth.ql
From e8e8d975e3e068a4625f6a5b15d654f617813616 Mon Sep 17 00:00:00 2001
From: Rasmus Wriedt Larsen
Date: Mon, 28 Aug 2023 15:34:19 +0200
Subject: [PATCH 136/788] Python: Remove all usage of DataFlow2+TaintTracking2
(and any higher number as well)
---
.../security/dataflow/PolynomialReDoSCustomizations.qll | 1 -
.../experimental/semmle/python/security/TimingAttack.qll | 6 ++----
2 files changed, 2 insertions(+), 5 deletions(-)
diff --git a/python/ql/lib/semmle/python/security/dataflow/PolynomialReDoSCustomizations.qll b/python/ql/lib/semmle/python/security/dataflow/PolynomialReDoSCustomizations.qll
index 09d787de57f..a6ba053e2d2 100644
--- a/python/ql/lib/semmle/python/security/dataflow/PolynomialReDoSCustomizations.qll
+++ b/python/ql/lib/semmle/python/security/dataflow/PolynomialReDoSCustomizations.qll
@@ -6,7 +6,6 @@
private import python
private import semmle.python.dataflow.new.DataFlow
-private import semmle.python.dataflow.new.DataFlow2
private import semmle.python.dataflow.new.TaintTracking
private import semmle.python.Concepts
private import semmle.python.dataflow.new.RemoteFlowSources
diff --git a/python/ql/src/experimental/semmle/python/security/TimingAttack.qll b/python/ql/src/experimental/semmle/python/security/TimingAttack.qll
index 23bd4dc268d..f072f212305 100644
--- a/python/ql/src/experimental/semmle/python/security/TimingAttack.qll
+++ b/python/ql/src/experimental/semmle/python/security/TimingAttack.qll
@@ -1,8 +1,6 @@
private import python
-private import semmle.python.dataflow.new.TaintTracking2
private import semmle.python.dataflow.new.TaintTracking
private import semmle.python.dataflow.new.DataFlow
-private import semmle.python.dataflow.new.DataFlow2
private import semmle.python.ApiGraphs
private import semmle.python.dataflow.new.RemoteFlowSources
private import semmle.python.frameworks.Flask
@@ -164,7 +162,7 @@ class NonConstantTimeComparisonSink extends DataFlow::Node {
/** Holds if remote user input was used in the comparison. */
predicate includesUserInput() {
- UserInputInComparisonFlow::flowTo(DataFlow2::exprNode(anotherParameter))
+ UserInputInComparisonFlow::flowTo(DataFlow::exprNode(anotherParameter))
}
}
@@ -175,7 +173,7 @@ class SecretSource extends DataFlow::Node {
SecretSource() { secret = this.asExpr() }
/** Holds if the secret was deliverd by remote user. */
- predicate includesUserInput() { UserInputSecretFlow::flowTo(DataFlow2::exprNode(secret)) }
+ predicate includesUserInput() { UserInputSecretFlow::flowTo(DataFlow::exprNode(secret)) }
}
/** A string for `match` that identifies strings that look like they represent secret data. */
From ce6335866b84f7cc0eeed65e06ed21c69d879190 Mon Sep 17 00:00:00 2001
From: Rasmus Wriedt Larsen
Date: Mon, 28 Aug 2023 15:43:00 +0200
Subject: [PATCH 137/788] Python: Move `ModificationOfParameterWithDefault` to
new dataflow API
---
.../ModificationOfParameterWithDefault.ql | 8 ++---
.../ModificationOfParameterWithDefault.qll | 33 ++++++++++++++++++-
.../test.ql | 2 +-
3 files changed, 37 insertions(+), 6 deletions(-)
diff --git a/python/ql/src/Functions/ModificationOfParameterWithDefault.ql b/python/ql/src/Functions/ModificationOfParameterWithDefault.ql
index 88b346fd2a0..3c601091694 100644
--- a/python/ql/src/Functions/ModificationOfParameterWithDefault.ql
+++ b/python/ql/src/Functions/ModificationOfParameterWithDefault.ql
@@ -13,11 +13,11 @@
import python
import semmle.python.functions.ModificationOfParameterWithDefault
-import DataFlow::PathGraph
+import ModificationOfParameterWithDefault::Flow::PathGraph
from
- ModificationOfParameterWithDefault::Configuration config, DataFlow::PathNode source,
- DataFlow::PathNode sink
-where config.hasFlowPath(source, sink)
+ ModificationOfParameterWithDefault::Flow::PathNode source,
+ ModificationOfParameterWithDefault::Flow::PathNode sink
+where ModificationOfParameterWithDefault::Flow::flowPath(source, sink)
select sink.getNode(), source, sink, "This expression mutates a $@.", source.getNode(),
"default value"
diff --git a/python/ql/src/semmle/python/functions/ModificationOfParameterWithDefault.qll b/python/ql/src/semmle/python/functions/ModificationOfParameterWithDefault.qll
index 24103a33ace..a0838772515 100644
--- a/python/ql/src/semmle/python/functions/ModificationOfParameterWithDefault.qll
+++ b/python/ql/src/semmle/python/functions/ModificationOfParameterWithDefault.qll
@@ -16,9 +16,11 @@ module ModificationOfParameterWithDefault {
import ModificationOfParameterWithDefaultCustomizations::ModificationOfParameterWithDefault
/**
+ * DEPRECATED: Use `Flow` module instead.
+ *
* A data-flow configuration for detecting modifications of a parameters default value.
*/
- class Configuration extends DataFlow::Configuration {
+ deprecated class Configuration extends DataFlow::Configuration {
/** Record whether the default value being tracked is non-empty. */
boolean nonEmptyDefault;
@@ -43,4 +45,33 @@ module ModificationOfParameterWithDefault {
nonEmptyDefault = false and node instanceof MustBeNonEmpty
}
}
+
+ private module Config implements DataFlow::StateConfigSig {
+ class FlowState = boolean;
+
+ predicate isSource(DataFlow::Node source, FlowState state) {
+ source.(Source).isNonEmpty() = state
+ }
+
+ predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
+
+ predicate isSink(DataFlow::Node sink, FlowState state) {
+ // dummy implementation since this predicate is required, but actual logic is in
+ // the predicate above.
+ none()
+ }
+
+ predicate isBarrier(DataFlow::Node node, FlowState state) {
+ // if we are tracking a non-empty default, then it is ok to modify empty values,
+ // so our tracking ends at those.
+ state = true and node instanceof MustBeEmpty
+ or
+ // if we are tracking a empty default, then it is ok to modify non-empty values,
+ // so our tracking ends at those.
+ state = false and node instanceof MustBeNonEmpty
+ }
+ }
+
+ /** Global data-flow for detecting modifications of a parameters default value. */
+ module Flow = DataFlow::GlobalWithState;
}
diff --git a/python/ql/test/query-tests/Functions/ModificationOfParameterWithDefault/test.ql b/python/ql/test/query-tests/Functions/ModificationOfParameterWithDefault/test.ql
index 97a01fd4b5f..eaf935d573b 100644
--- a/python/ql/test/query-tests/Functions/ModificationOfParameterWithDefault/test.ql
+++ b/python/ql/test/query-tests/Functions/ModificationOfParameterWithDefault/test.ql
@@ -8,7 +8,7 @@ module ModificationOfParameterWithDefaultTest implements TestSig {
string getARelevantTag() { result = "modification" }
private predicate relevant_node(DataFlow::Node sink) {
- exists(ModificationOfParameterWithDefault::Configuration cfg | cfg.hasFlowTo(sink))
+ ModificationOfParameterWithDefault::Flow::flowTo(sink)
}
predicate hasActualResult(Location location, string element, string tag, string value) {
From 3476437bfe4529dd66c35efc8b0258d34cec4503 Mon Sep 17 00:00:00 2001
From: Tamas Vajk
Date: Thu, 31 Aug 2023 13:12:43 +0200
Subject: [PATCH 138/788] C#: Add test case with recursive generics
---
.../ExtractortMessages.expected | 0
.../ExtractortMessages.ql | 6 +++++
.../diag_recursive_generics/Types.expected | 0
.../diag_recursive_generics/Types.ql | 5 ++++
.../diag_recursive_generics/test.cs | 23 +++++++++++++++++++
.../diag_recursive_generics/test.csproj | 12 ++++++++++
.../diag_recursive_generics/test.py | 3 +++
7 files changed, 49 insertions(+)
create mode 100644 csharp/ql/integration-tests/all-platforms/diag_recursive_generics/ExtractortMessages.expected
create mode 100644 csharp/ql/integration-tests/all-platforms/diag_recursive_generics/ExtractortMessages.ql
create mode 100644 csharp/ql/integration-tests/all-platforms/diag_recursive_generics/Types.expected
create mode 100644 csharp/ql/integration-tests/all-platforms/diag_recursive_generics/Types.ql
create mode 100644 csharp/ql/integration-tests/all-platforms/diag_recursive_generics/test.cs
create mode 100644 csharp/ql/integration-tests/all-platforms/diag_recursive_generics/test.csproj
create mode 100644 csharp/ql/integration-tests/all-platforms/diag_recursive_generics/test.py
diff --git a/csharp/ql/integration-tests/all-platforms/diag_recursive_generics/ExtractortMessages.expected b/csharp/ql/integration-tests/all-platforms/diag_recursive_generics/ExtractortMessages.expected
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/csharp/ql/integration-tests/all-platforms/diag_recursive_generics/ExtractortMessages.ql b/csharp/ql/integration-tests/all-platforms/diag_recursive_generics/ExtractortMessages.ql
new file mode 100644
index 00000000000..10b9822fc2e
--- /dev/null
+++ b/csharp/ql/integration-tests/all-platforms/diag_recursive_generics/ExtractortMessages.ql
@@ -0,0 +1,6 @@
+import csharp
+import semmle.code.csharp.commons.Diagnostics
+
+query predicate extractorMessages(ExtractorMessage msg, int severity, string elementText) {
+ msg.getSeverity() = severity and msg.getElementText() = elementText
+}
diff --git a/csharp/ql/integration-tests/all-platforms/diag_recursive_generics/Types.expected b/csharp/ql/integration-tests/all-platforms/diag_recursive_generics/Types.expected
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/csharp/ql/integration-tests/all-platforms/diag_recursive_generics/Types.ql b/csharp/ql/integration-tests/all-platforms/diag_recursive_generics/Types.ql
new file mode 100644
index 00000000000..c7b1545c51d
--- /dev/null
+++ b/csharp/ql/integration-tests/all-platforms/diag_recursive_generics/Types.ql
@@ -0,0 +1,5 @@
+import csharp
+
+from Class c
+where c.fromSource()
+select c, c.getBaseClass().getQualifiedName()
diff --git a/csharp/ql/integration-tests/all-platforms/diag_recursive_generics/test.cs b/csharp/ql/integration-tests/all-platforms/diag_recursive_generics/test.cs
new file mode 100644
index 00000000000..35f5c68d5fa
--- /dev/null
+++ b/csharp/ql/integration-tests/all-platforms/diag_recursive_generics/test.cs
@@ -0,0 +1,23 @@
+public class GenA { };
+public class GenB : GenA>> { };
+
+class P { }
+class C : P> { }
+class D : P> { }
+
+class A : System.IEquatable>
+{
+ public bool Equals(A other) { return true; }
+}
+
+public class Class
+{
+ public static int Main()
+ {
+ GenB a = new GenB();
+ P> b = new C();
+ A c = new A();
+
+ return 0;
+ }
+}
diff --git a/csharp/ql/integration-tests/all-platforms/diag_recursive_generics/test.csproj b/csharp/ql/integration-tests/all-platforms/diag_recursive_generics/test.csproj
new file mode 100644
index 00000000000..97ae9f860c1
--- /dev/null
+++ b/csharp/ql/integration-tests/all-platforms/diag_recursive_generics/test.csproj
@@ -0,0 +1,12 @@
+
+
+
+ Exe
+ net7.0
+
+
+
+
+
+
+
diff --git a/csharp/ql/integration-tests/all-platforms/diag_recursive_generics/test.py b/csharp/ql/integration-tests/all-platforms/diag_recursive_generics/test.py
new file mode 100644
index 00000000000..24cc83b4f2d
--- /dev/null
+++ b/csharp/ql/integration-tests/all-platforms/diag_recursive_generics/test.py
@@ -0,0 +1,3 @@
+from create_database_utils import *
+
+run_codeql_database_create(['dotnet build'], lang="csharp", extra_args=["--extractor-option=cil=false"])
From d4bc6e434a06b7bfb69af8eeba9d8bfd691f4b12 Mon Sep 17 00:00:00 2001
From: erik-krogh
Date: Thu, 31 Aug 2023 13:40:47 +0200
Subject: [PATCH 139/788] add test with false positive
---
.../CWE-601-UrlRedirect/UrlRedirect.expected | 14 ++++++++++++++
.../Security/CWE-601-UrlRedirect/test.py | 14 ++++++++++++++
2 files changed, 28 insertions(+)
diff --git a/python/ql/test/query-tests/Security/CWE-601-UrlRedirect/UrlRedirect.expected b/python/ql/test/query-tests/Security/CWE-601-UrlRedirect/UrlRedirect.expected
index 167e5270c95..21f498c5d94 100644
--- a/python/ql/test/query-tests/Security/CWE-601-UrlRedirect/UrlRedirect.expected
+++ b/python/ql/test/query-tests/Security/CWE-601-UrlRedirect/UrlRedirect.expected
@@ -8,6 +8,7 @@ edges
| test.py:1:26:1:32 | GSSA Variable request | test.py:67:17:67:23 | ControlFlowNode for request |
| test.py:1:26:1:32 | GSSA Variable request | test.py:74:17:74:23 | ControlFlowNode for request |
| test.py:1:26:1:32 | GSSA Variable request | test.py:81:17:81:23 | ControlFlowNode for request |
+| test.py:1:26:1:32 | GSSA Variable request | test.py:90:17:90:23 | ControlFlowNode for request |
| test.py:7:5:7:10 | SSA variable target | test.py:8:21:8:26 | ControlFlowNode for target |
| test.py:7:14:7:20 | ControlFlowNode for request | test.py:7:14:7:25 | ControlFlowNode for Attribute |
| test.py:7:14:7:25 | ControlFlowNode for Attribute | test.py:7:14:7:43 | ControlFlowNode for Attribute() |
@@ -47,6 +48,11 @@ edges
| test.py:81:17:81:28 | ControlFlowNode for Attribute | test.py:81:17:81:46 | ControlFlowNode for Attribute() |
| test.py:81:17:81:46 | ControlFlowNode for Attribute() | test.py:81:5:81:13 | SSA variable untrusted |
| test.py:82:5:82:10 | SSA variable unsafe | test.py:83:21:83:26 | ControlFlowNode for unsafe |
+| test.py:90:5:90:13 | SSA variable untrusted | test.py:93:18:93:26 | ControlFlowNode for untrusted |
+| test.py:90:5:90:13 | SSA variable untrusted | test.py:95:25:95:33 | ControlFlowNode for untrusted |
+| test.py:90:17:90:23 | ControlFlowNode for request | test.py:90:17:90:28 | ControlFlowNode for Attribute |
+| test.py:90:17:90:28 | ControlFlowNode for Attribute | test.py:90:17:90:46 | ControlFlowNode for Attribute() |
+| test.py:90:17:90:46 | ControlFlowNode for Attribute() | test.py:90:5:90:13 | SSA variable untrusted |
nodes
| test.py:1:26:1:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember |
| test.py:1:26:1:32 | GSSA Variable request | semmle.label | GSSA Variable request |
@@ -97,6 +103,12 @@ nodes
| test.py:81:17:81:46 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| test.py:82:5:82:10 | SSA variable unsafe | semmle.label | SSA variable unsafe |
| test.py:83:21:83:26 | ControlFlowNode for unsafe | semmle.label | ControlFlowNode for unsafe |
+| test.py:90:5:90:13 | SSA variable untrusted | semmle.label | SSA variable untrusted |
+| test.py:90:17:90:23 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
+| test.py:90:17:90:28 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
+| test.py:90:17:90:46 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
+| test.py:93:18:93:26 | ControlFlowNode for untrusted | semmle.label | ControlFlowNode for untrusted |
+| test.py:95:25:95:33 | ControlFlowNode for untrusted | semmle.label | ControlFlowNode for untrusted |
subpaths
#select
| test.py:8:21:8:26 | ControlFlowNode for target | test.py:1:26:1:32 | ControlFlowNode for ImportMember | test.py:8:21:8:26 | ControlFlowNode for target | Untrusted URL redirection depends on a $@. | test.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value |
@@ -107,3 +119,5 @@ subpaths
| test.py:69:21:69:26 | ControlFlowNode for unsafe | test.py:1:26:1:32 | ControlFlowNode for ImportMember | test.py:69:21:69:26 | ControlFlowNode for unsafe | Untrusted URL redirection depends on a $@. | test.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value |
| test.py:76:21:76:26 | ControlFlowNode for unsafe | test.py:1:26:1:32 | ControlFlowNode for ImportMember | test.py:76:21:76:26 | ControlFlowNode for unsafe | Untrusted URL redirection depends on a $@. | test.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value |
| test.py:83:21:83:26 | ControlFlowNode for unsafe | test.py:1:26:1:32 | ControlFlowNode for ImportMember | test.py:83:21:83:26 | ControlFlowNode for unsafe | Untrusted URL redirection depends on a $@. | test.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value |
+| test.py:93:18:93:26 | ControlFlowNode for untrusted | test.py:1:26:1:32 | ControlFlowNode for ImportMember | test.py:93:18:93:26 | ControlFlowNode for untrusted | Untrusted URL redirection depends on a $@. | test.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value |
+| test.py:95:25:95:33 | ControlFlowNode for untrusted | test.py:1:26:1:32 | ControlFlowNode for ImportMember | test.py:95:25:95:33 | ControlFlowNode for untrusted | Untrusted URL redirection depends on a $@. | test.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value |
diff --git a/python/ql/test/query-tests/Security/CWE-601-UrlRedirect/test.py b/python/ql/test/query-tests/Security/CWE-601-UrlRedirect/test.py
index 381eb3a4bae..419ae428edd 100644
--- a/python/ql/test/query-tests/Security/CWE-601-UrlRedirect/test.py
+++ b/python/ql/test/query-tests/Security/CWE-601-UrlRedirect/test.py
@@ -81,3 +81,17 @@ def not_ok4():
untrusted = request.args.get('target', '')
unsafe = "%s?login=success" % untrusted
return redirect(unsafe, code=302)
+
+from django.utils.http import url_has_allowed_host_and_scheme
+import math
+
+@app.route('/ok6')
+def ok6():
+ untrusted = request.args.get('target', '')
+ # random chance.
+ if math.random() > 0.5:
+ redirect(untrusted, code=302) # NOT OK
+ if url_has_allowed_host_and_scheme(untrusted, allowed_hosts=None):
+ return redirect(untrusted, code=302) # OK - but is flagged!
+
+ return redirect("https://example.com", code=302) # OK
\ No newline at end of file
From 8dad4950a94fd13f597de2997ea738a0fcda9e80 Mon Sep 17 00:00:00 2001
From: erik-krogh
Date: Thu, 31 Aug 2023 13:48:42 +0200
Subject: [PATCH 140/788] add sanitizer guard for
url_has_allowed_host_and_scheme
---
.../dataflow/UrlRedirectCustomizations.qll | 27 +++++++++++++++++++
.../CWE-601-UrlRedirect/UrlRedirect.expected | 3 ---
.../Security/CWE-601-UrlRedirect/test.py | 2 +-
3 files changed, 28 insertions(+), 4 deletions(-)
diff --git a/python/ql/lib/semmle/python/security/dataflow/UrlRedirectCustomizations.qll b/python/ql/lib/semmle/python/security/dataflow/UrlRedirectCustomizations.qll
index b4843f1a8eb..1476d0381ea 100644
--- a/python/ql/lib/semmle/python/security/dataflow/UrlRedirectCustomizations.qll
+++ b/python/ql/lib/semmle/python/security/dataflow/UrlRedirectCustomizations.qll
@@ -70,4 +70,31 @@ module UrlRedirect {
* A comparison with a constant string, considered as a sanitizer-guard.
*/
class StringConstCompareAsSanitizerGuard extends Sanitizer, StringConstCompareBarrier { }
+
+ private import semmle.python.ApiGraphs
+
+ private predicate djangoUrlHasAllowedHostAndScheme(
+ DataFlow::GuardNode g, ControlFlowNode node, boolean branch
+ ) {
+ exists(API::CallNode call |
+ call =
+ API::moduleImport("django")
+ .getMember("utils")
+ .getMember("http")
+ .getMember("url_has_allowed_host_and_scheme")
+ .getACall() and
+ g = call.asCfgNode() and
+ node = call.getParameter(0, "url").asSink().asCfgNode() and
+ branch = true
+ )
+ }
+
+ /**
+ * A call to `django.utils.http.url_has_allowed_host_and_scheme`, considered as a sanitizer-guard.
+ */
+ private class DjangoAllowedUrl extends Sanitizer {
+ DjangoAllowedUrl() {
+ this = DataFlow::BarrierGuard::getABarrierNode()
+ }
+ }
}
diff --git a/python/ql/test/query-tests/Security/CWE-601-UrlRedirect/UrlRedirect.expected b/python/ql/test/query-tests/Security/CWE-601-UrlRedirect/UrlRedirect.expected
index 21f498c5d94..ea47807a211 100644
--- a/python/ql/test/query-tests/Security/CWE-601-UrlRedirect/UrlRedirect.expected
+++ b/python/ql/test/query-tests/Security/CWE-601-UrlRedirect/UrlRedirect.expected
@@ -49,7 +49,6 @@ edges
| test.py:81:17:81:46 | ControlFlowNode for Attribute() | test.py:81:5:81:13 | SSA variable untrusted |
| test.py:82:5:82:10 | SSA variable unsafe | test.py:83:21:83:26 | ControlFlowNode for unsafe |
| test.py:90:5:90:13 | SSA variable untrusted | test.py:93:18:93:26 | ControlFlowNode for untrusted |
-| test.py:90:5:90:13 | SSA variable untrusted | test.py:95:25:95:33 | ControlFlowNode for untrusted |
| test.py:90:17:90:23 | ControlFlowNode for request | test.py:90:17:90:28 | ControlFlowNode for Attribute |
| test.py:90:17:90:28 | ControlFlowNode for Attribute | test.py:90:17:90:46 | ControlFlowNode for Attribute() |
| test.py:90:17:90:46 | ControlFlowNode for Attribute() | test.py:90:5:90:13 | SSA variable untrusted |
@@ -108,7 +107,6 @@ nodes
| test.py:90:17:90:28 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| test.py:90:17:90:46 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| test.py:93:18:93:26 | ControlFlowNode for untrusted | semmle.label | ControlFlowNode for untrusted |
-| test.py:95:25:95:33 | ControlFlowNode for untrusted | semmle.label | ControlFlowNode for untrusted |
subpaths
#select
| test.py:8:21:8:26 | ControlFlowNode for target | test.py:1:26:1:32 | ControlFlowNode for ImportMember | test.py:8:21:8:26 | ControlFlowNode for target | Untrusted URL redirection depends on a $@. | test.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value |
@@ -120,4 +118,3 @@ subpaths
| test.py:76:21:76:26 | ControlFlowNode for unsafe | test.py:1:26:1:32 | ControlFlowNode for ImportMember | test.py:76:21:76:26 | ControlFlowNode for unsafe | Untrusted URL redirection depends on a $@. | test.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value |
| test.py:83:21:83:26 | ControlFlowNode for unsafe | test.py:1:26:1:32 | ControlFlowNode for ImportMember | test.py:83:21:83:26 | ControlFlowNode for unsafe | Untrusted URL redirection depends on a $@. | test.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value |
| test.py:93:18:93:26 | ControlFlowNode for untrusted | test.py:1:26:1:32 | ControlFlowNode for ImportMember | test.py:93:18:93:26 | ControlFlowNode for untrusted | Untrusted URL redirection depends on a $@. | test.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value |
-| test.py:95:25:95:33 | ControlFlowNode for untrusted | test.py:1:26:1:32 | ControlFlowNode for ImportMember | test.py:95:25:95:33 | ControlFlowNode for untrusted | Untrusted URL redirection depends on a $@. | test.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value |
diff --git a/python/ql/test/query-tests/Security/CWE-601-UrlRedirect/test.py b/python/ql/test/query-tests/Security/CWE-601-UrlRedirect/test.py
index 419ae428edd..0a02b4ac1d5 100644
--- a/python/ql/test/query-tests/Security/CWE-601-UrlRedirect/test.py
+++ b/python/ql/test/query-tests/Security/CWE-601-UrlRedirect/test.py
@@ -92,6 +92,6 @@ def ok6():
if math.random() > 0.5:
redirect(untrusted, code=302) # NOT OK
if url_has_allowed_host_and_scheme(untrusted, allowed_hosts=None):
- return redirect(untrusted, code=302) # OK - but is flagged!
+ return redirect(untrusted, code=302) # OK
return redirect("https://example.com", code=302) # OK
\ No newline at end of file
From 89e9d25f02c3ec3b5b552012eca8ae54ffc42973 Mon Sep 17 00:00:00 2001
From: Tom Hvitved
Date: Thu, 31 Aug 2023 13:05:12 +0200
Subject: [PATCH 141/788] Ruby: Hide desugared assignments from data flow path
graph
---
.../ruby/dataflow/internal/DataFlowPrivate.qll | 17 +++++++++++++----
.../dataflow/array-flow/array-flow.expected | 8 ++------
.../dataflow/hash-flow/hash-flow.expected | 4 +---
3 files changed, 16 insertions(+), 13 deletions(-)
diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPrivate.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPrivate.qll
index d0990b63063..03fc2566fe5 100644
--- a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPrivate.qll
+++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPrivate.qll
@@ -558,9 +558,7 @@ import Cached
/** Holds if `n` should be hidden from path explanations. */
predicate nodeIsHidden(Node n) {
- exists(SsaImpl::DefinitionExt def | def = n.(SsaDefinitionExtNode).getDefinitionExt() |
- not def instanceof Ssa::WriteDefinition
- )
+ n.(SsaDefinitionExtNode).isHidden()
or
n = LocalFlow::getParameterDefNode(_)
or
@@ -593,6 +591,13 @@ class SsaDefinitionExtNode extends NodeImpl, TSsaDefinitionExtNode {
/** Gets the underlying variable. */
Variable getVariable() { result = def.getSourceVariable() }
+ /** Holds if this node should be hidden from path explanations. */
+ predicate isHidden() {
+ not def instanceof Ssa::WriteDefinition
+ or
+ isDesugarNode(def.(Ssa::WriteDefinition).getWriteAccess().getExpr())
+ }
+
override CfgScope getCfgScope() { result = def.getBasicBlock().getScope() }
override Location getLocationImpl() { result = def.getLocation() }
@@ -1593,7 +1598,11 @@ class CastNode extends Node {
*/
predicate neverSkipInPathGraph(Node n) {
// ensure that all variable assignments are included in the path graph
- n.(SsaDefinitionExtNode).getDefinitionExt() instanceof Ssa::WriteDefinition
+ n =
+ any(SsaDefinitionExtNode def |
+ def.getDefinitionExt() instanceof Ssa::WriteDefinition and
+ not def.isHidden()
+ )
}
class DataFlowExpr = CfgNodes::ExprCfgNode;
diff --git a/ruby/ql/test/library-tests/dataflow/array-flow/array-flow.expected b/ruby/ql/test/library-tests/dataflow/array-flow/array-flow.expected
index cc720fde1f8..aae13446229 100644
--- a/ruby/ql/test/library-tests/dataflow/array-flow/array-flow.expected
+++ b/ruby/ql/test/library-tests/dataflow/array-flow/array-flow.expected
@@ -203,10 +203,8 @@ edges
| array_flow.rb:80:13:80:21 | call to source | array_flow.rb:80:5:80:5 | a [element 1] |
| array_flow.rb:81:8:81:8 | c | array_flow.rb:83:10:83:10 | c |
| array_flow.rb:81:8:81:8 | c | array_flow.rb:83:10:83:10 | c |
-| array_flow.rb:81:15:81:15 | __synth__3 [element 1] | array_flow.rb:81:8:81:8 | c |
-| array_flow.rb:81:15:81:15 | __synth__3 [element 1] | array_flow.rb:81:8:81:8 | c |
-| array_flow.rb:81:15:81:15 | a [element 1] | array_flow.rb:81:15:81:15 | __synth__3 [element 1] |
-| array_flow.rb:81:15:81:15 | a [element 1] | array_flow.rb:81:15:81:15 | __synth__3 [element 1] |
+| array_flow.rb:81:15:81:15 | a [element 1] | array_flow.rb:81:8:81:8 | c |
+| array_flow.rb:81:15:81:15 | a [element 1] | array_flow.rb:81:8:81:8 | c |
| array_flow.rb:88:5:88:5 | a [element 1] | array_flow.rb:89:9:89:9 | a [element 1] |
| array_flow.rb:88:5:88:5 | a [element 1] | array_flow.rb:89:9:89:9 | a [element 1] |
| array_flow.rb:88:13:88:22 | call to source | array_flow.rb:88:5:88:5 | a [element 1] |
@@ -4468,8 +4466,6 @@ nodes
| array_flow.rb:80:13:80:21 | call to source | semmle.label | call to source |
| array_flow.rb:81:8:81:8 | c | semmle.label | c |
| array_flow.rb:81:8:81:8 | c | semmle.label | c |
-| array_flow.rb:81:15:81:15 | __synth__3 [element 1] | semmle.label | __synth__3 [element 1] |
-| array_flow.rb:81:15:81:15 | __synth__3 [element 1] | semmle.label | __synth__3 [element 1] |
| array_flow.rb:81:15:81:15 | a [element 1] | semmle.label | a [element 1] |
| array_flow.rb:81:15:81:15 | a [element 1] | semmle.label | a [element 1] |
| array_flow.rb:83:10:83:10 | c | semmle.label | c |
diff --git a/ruby/ql/test/library-tests/dataflow/hash-flow/hash-flow.expected b/ruby/ql/test/library-tests/dataflow/hash-flow/hash-flow.expected
index 0ec677d4198..79f2565a590 100644
--- a/ruby/ql/test/library-tests/dataflow/hash-flow/hash-flow.expected
+++ b/ruby/ql/test/library-tests/dataflow/hash-flow/hash-flow.expected
@@ -81,8 +81,7 @@ edges
| hash_flow.rb:96:30:96:33 | hash [element :a] | hash_flow.rb:96:13:96:34 | call to try_convert [element :a] |
| hash_flow.rb:97:10:97:14 | hash2 [element :a] | hash_flow.rb:97:10:97:18 | ...[...] |
| hash_flow.rb:105:5:105:5 | b | hash_flow.rb:106:10:106:10 | b |
-| hash_flow.rb:105:21:105:30 | __synth__0 | hash_flow.rb:105:5:105:5 | b |
-| hash_flow.rb:105:21:105:30 | call to taint | hash_flow.rb:105:21:105:30 | __synth__0 |
+| hash_flow.rb:105:21:105:30 | call to taint | hash_flow.rb:105:5:105:5 | b |
| hash_flow.rb:113:5:113:5 | b | hash_flow.rb:115:10:115:10 | b |
| hash_flow.rb:113:9:113:12 | [post] hash [element :a] | hash_flow.rb:114:10:114:13 | hash [element :a] |
| hash_flow.rb:113:9:113:34 | call to store | hash_flow.rb:113:5:113:5 | b |
@@ -1063,7 +1062,6 @@ nodes
| hash_flow.rb:97:10:97:14 | hash2 [element :a] | semmle.label | hash2 [element :a] |
| hash_flow.rb:97:10:97:18 | ...[...] | semmle.label | ...[...] |
| hash_flow.rb:105:5:105:5 | b | semmle.label | b |
-| hash_flow.rb:105:21:105:30 | __synth__0 | semmle.label | __synth__0 |
| hash_flow.rb:105:21:105:30 | call to taint | semmle.label | call to taint |
| hash_flow.rb:106:10:106:10 | b | semmle.label | b |
| hash_flow.rb:113:5:113:5 | b | semmle.label | b |
From c1d80918917e8227be399e4885bdcb4c79af4593 Mon Sep 17 00:00:00 2001
From: Tamas Vajk
Date: Thu, 31 Aug 2023 13:12:55 +0200
Subject: [PATCH 142/788] C#: Exclude base type extraction of recursive
generics
---
.../Entities/Types/Type.cs | 215 +++++++++++++++++-
.../ExtractortMessages.expected | 4 +
.../diag_recursive_generics/Types.expected | 35 +++
3 files changed, 253 insertions(+), 1 deletion(-)
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/Type.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/Type.cs
index 59bb0bee4dd..f396025d3ee 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/Type.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/Type.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
@@ -82,8 +83,15 @@ namespace Semmle.Extraction.CSharp.Entities
var baseTypes = GetBaseTypeDeclarations();
+ var hasExpandingCycle = GenericsRecursionGraph.HasExpandingCycle(Symbol);
+ if (hasExpandingCycle)
+ {
+ Context.ExtractionError("Found recursive generic inheritance hierarchy. Base class of type is not extracted", Symbol.ToDisplayString(), Context.CreateLocation(ReportingLocation), severity: Util.Logging.Severity.Warning);
+ }
+
// Visit base types
- if (Symbol.GetNonObjectBaseType(Context) is INamedTypeSymbol @base)
+ if (!hasExpandingCycle
+ && Symbol.GetNonObjectBaseType(Context) is INamedTypeSymbol @base)
{
var bts = GetBaseTypeDeclarations(baseTypes, @base);
@@ -347,6 +355,211 @@ namespace Semmle.Extraction.CSharp.Entities
}
public override int GetHashCode() => SymbolEqualityComparer.Default.GetHashCode(Symbol);
+
+ ///
+ /// Class to detect recursive generic inheritance hierarchies.
+ ///
+ /// Details can be found in https://www.ecma-international.org/wp-content/uploads/ECMA-335_6th_edition_june_2012.pdf Chapter II.9.2 Generics and recursive inheritance graphs
+ /// The dotnet runtime already implements this check as a runtime validation: https://github.com/dotnet/runtime/blob/e48e88d0fe9c2e494c0e6fd0c7c1fb54e7ddbdb1/src/coreclr/vm/generics.cpp#L748
+ ///
+ public class GenericsRecursionGraph
+ {
+ private static readonly ConcurrentDictionary resultCache = new(SymbolEqualityComparer.Default);
+
+ ///
+ /// Checks whether the given type has a recursive generic inheritance hierarchy. The result is cached.
+ ///
+ public static bool HasExpandingCycle(ITypeSymbol start)
+ {
+ if (start.OriginalDefinition is not INamedTypeSymbol namedTypeDefinition ||
+ !namedTypeDefinition.IsGenericType)
+ {
+ return false;
+ }
+
+ if (resultCache.TryGetValue(namedTypeDefinition, out var result))
+ {
+ return result;
+ }
+
+ result = new GenericsRecursionGraph(namedTypeDefinition).HasExpandingCycle();
+ resultCache.TryAdd(namedTypeDefinition, result);
+
+ return result;
+ }
+
+ private readonly INamedTypeSymbol startSymbol;
+ private readonly HashSet instantiationClosure = new(SymbolEqualityComparer.Default);
+ private readonly Dictionary> edges = new(SymbolEqualityComparer.Default);
+
+ private GenericsRecursionGraph(INamedTypeSymbol startSymbol)
+ {
+ this.startSymbol = startSymbol;
+
+ ComputeInstantiationClosure();
+ ComputeGraphEdges();
+ }
+
+ private void ComputeGraphEdges()
+ {
+ foreach (var reference in instantiationClosure)
+ {
+ var definition = reference.OriginalDefinition;
+ if (SymbolEqualityComparer.Default.Equals(reference, definition))
+ {
+ // It's a definition, so no edges
+ continue;
+ }
+
+ for (var i = 0; i < reference.TypeArguments.Length; i++)
+ {
+ var target = definition.TypeParameters[i];
+ if (reference.TypeArguments[i] is ITypeParameterSymbol source)
+ {
+ // non-expanding
+ if (!edges.TryGetValue(source, out var targets))
+ {
+ targets = new List<(ITypeParameterSymbol, bool)>();
+ edges.Add(source, targets);
+ }
+ targets.Add((target, false));
+ }
+ else if (reference.TypeArguments[i] is INamedTypeSymbol namedType)
+ {
+ // expanding
+ var sources = GetAllNestedTypeParameters(namedType);
+ foreach (var s in sources)
+ {
+ if (!edges.TryGetValue(s, out var targets))
+ {
+ targets = new List<(ITypeParameterSymbol, bool)>();
+ edges.Add(s, targets);
+ }
+ targets.Add((target, true));
+ }
+ }
+ }
+ }
+ }
+
+ private List GetAllNestedTypeParameters(INamedTypeSymbol symbol)
+ {
+ var res = new List();
+
+ foreach (var typeArgument in symbol.TypeArguments)
+ {
+ if (typeArgument is ITypeParameterSymbol typeParameter)
+ {
+ res.Add(typeParameter);
+ }
+ else if (typeArgument is INamedTypeSymbol namedType)
+ {
+ res.AddRange(GetAllNestedTypeParameters(namedType));
+ }
+ }
+
+ return res;
+ }
+
+ private void ComputeInstantiationClosure()
+ {
+ var workQueue = new Queue();
+ workQueue.Enqueue(startSymbol);
+
+ while (workQueue.Count > 0)
+ {
+ var current = workQueue.Dequeue();
+ if (instantiationClosure.Contains(current) ||
+ !current.IsGenericType)
+ {
+ continue;
+ }
+
+ instantiationClosure.Add(current);
+
+ if (SymbolEqualityComparer.Default.Equals(current, current.OriginalDefinition))
+ {
+ // Definition, so enqueue all base types and interfaces
+ if (current.BaseType != null)
+ {
+ workQueue.Enqueue(current.BaseType);
+ }
+
+ foreach (var i in current.Interfaces)
+ {
+ workQueue.Enqueue(i);
+ }
+ }
+ else
+ {
+ // Reference, so enqueue all type arguments and their original definitions:
+ foreach (var namedTypeArgument in current.TypeArguments.OfType())
+ {
+ workQueue.Enqueue(namedTypeArgument);
+ workQueue.Enqueue(namedTypeArgument.OriginalDefinition);
+ }
+ }
+ }
+ }
+
+ private bool HasExpandingCycle()
+ {
+ return startSymbol.TypeParameters.Any(HasExpandingCycle);
+ }
+
+ private bool HasExpandingCycle(ITypeParameterSymbol start)
+ {
+ var visited = new HashSet(SymbolEqualityComparer.Default);
+ var recStack = new HashSet(SymbolEqualityComparer.Default);
+ var hasExpandingCycle = HasExpandingCycle(start, visited, recStack, start, hasSeenExpandingEdge: false);
+ return hasExpandingCycle;
+ }
+
+ private List<(ITypeParameterSymbol To, bool IsExpanding)> GetOutgoingEdges(ITypeParameterSymbol typeParameter)
+ {
+ return edges.TryGetValue(typeParameter, out var outgoingEdges)
+ ? outgoingEdges
+ : new List<(ITypeParameterSymbol, bool)>();
+ }
+
+ ///
+ /// A modified cycle detection algorithm based on DFS.
+ ///
+ /// The current node that is being visited
+ /// The nodes that have already been visited by any path.
+ /// The nodes already visited on the current path. Could be a List<> if the order was important.
+ /// The start and end of the cycle. We're not looking for any cycle, but a cycle that goes back to the start.
+ /// Whether an expanding edge was already seen in this path. We're looking for a cycle that has at least one expanding edge.
+ ///
+ private bool HasExpandingCycle(ITypeParameterSymbol current, HashSet visited, HashSet currentPath, ITypeParameterSymbol start, bool hasSeenExpandingEdge)
+ {
+ if (currentPath.Count > 0 && SymbolEqualityComparer.Default.Equals(current, start))
+ {
+ return hasSeenExpandingEdge;
+ }
+
+ if (visited.Contains(current))
+ {
+ return false;
+ }
+
+ visited.Add(current);
+ currentPath.Add(current);
+
+ var outgoingEdges = GetOutgoingEdges(current);
+
+ foreach (var outgoingEdge in outgoingEdges)
+ {
+ if (HasExpandingCycle(outgoingEdge.To, visited, currentPath, start, hasSeenExpandingEdge: hasSeenExpandingEdge || outgoingEdge.IsExpanding))
+ {
+ return true;
+ }
+ }
+
+ currentPath.Remove(current);
+ return false;
+ }
+ }
}
internal abstract class Type : Type where T : ITypeSymbol
diff --git a/csharp/ql/integration-tests/all-platforms/diag_recursive_generics/ExtractortMessages.expected b/csharp/ql/integration-tests/all-platforms/diag_recursive_generics/ExtractortMessages.expected
index e69de29bb2d..88d88c203f2 100644
--- a/csharp/ql/integration-tests/all-platforms/diag_recursive_generics/ExtractortMessages.expected
+++ b/csharp/ql/integration-tests/all-platforms/diag_recursive_generics/ExtractortMessages.expected
@@ -0,0 +1,4 @@
+| test.cs:2:14:2:20 | Found recursive generic inheritance hierarchy. Base class of type is not extracted | 4 | GenB> |
+| test.cs:2:14:2:20 | Found recursive generic inheritance hierarchy. Base class of type is not extracted | 4 | GenB> |
+| test.cs:2:14:2:20 | Found recursive generic inheritance hierarchy. Base class of type is not extracted | 4 | GenB |
+| test.cs:2:14:2:20 | Found recursive generic inheritance hierarchy. Base class of type is not extracted | 4 | GenB |
diff --git a/csharp/ql/integration-tests/all-platforms/diag_recursive_generics/Types.expected b/csharp/ql/integration-tests/all-platforms/diag_recursive_generics/Types.expected
index e69de29bb2d..1d9a1d04aff 100644
--- a/csharp/ql/integration-tests/all-platforms/diag_recursive_generics/Types.expected
+++ b/csharp/ql/integration-tests/all-platforms/diag_recursive_generics/Types.expected
@@ -0,0 +1,35 @@
+| test.cs:1:14:1:20 | GenA<> | System.Object |
+| test.cs:1:14:1:20 | GenA>> | System.Object |
+| test.cs:1:14:1:20 | GenA>> | System.Object |
+| test.cs:2:14:2:20 | GenB<> | System.Object |
+| test.cs:2:14:2:20 | GenB> | System.Object |
+| test.cs:2:14:2:20 | GenB> | System.Object |
+| test.cs:2:14:2:20 | GenB | System.Object |
+| test.cs:4:7:4:10 | P<> | System.Object |
+| test.cs:4:7:4:10 | P> | System.Object |
+| test.cs:4:7:4:10 | P> | System.Object |
+| test.cs:4:7:4:10 | P> | System.Object |
+| test.cs:4:7:4:10 | P> | System.Object |
+| test.cs:4:7:4:10 | P> | System.Object |
+| test.cs:4:7:4:10 | P> | System.Object |
+| test.cs:4:7:4:10 | P> | System.Object |
+| test.cs:4:7:4:10 | P> | System.Object |
+| test.cs:4:7:4:10 | P> | System.Object |
+| test.cs:4:7:4:10 | P> | System.Object |
+| test.cs:4:7:4:10 | P> | System.Object |
+| test.cs:4:7:4:10 | P> | System.Object |
+| test.cs:5:7:5:13 | C<,> | P> |
+| test.cs:5:7:5:13 | C | P> |
+| test.cs:5:7:5:13 | C | P> |
+| test.cs:5:7:5:13 | C | P> |
+| test.cs:5:7:5:13 | C | P> |
+| test.cs:5:7:5:13 | C | P> |
+| test.cs:6:7:6:13 | D<,> | P> |
+| test.cs:6:7:6:13 | D | P> |
+| test.cs:6:7:6:13 | D | P> |
+| test.cs:6:7:6:13 | D | P> |
+| test.cs:6:7:6:13 | D | P> |
+| test.cs:6:7:6:13 | D | P