Swift: Add an example with flow through a callback function.

This commit is contained in:
Mathias Vorreiter Pedersen
2022-10-06 00:43:07 +01:00
parent 197f036797
commit 1edd4d855a
5 changed files with 111 additions and 32 deletions

View File

@@ -80,6 +80,7 @@ private import internal.FlowSummaryImplSpecific
private module Frameworks {
private import codeql.swift.frameworks.StandardLibrary.String
private import codeql.swift.frameworks.StandardLibrary.Url
private import codeql.swift.frameworks.StandardLibrary.UrlSession
}
/**

View File

@@ -0,0 +1,8 @@
private import codeql.swift.dataflow.ExternalFlow
private class UrlSessionSummaries extends SummaryModelCsv {
override predicate row(string row) {
row =
";URLSession;true;dataTask(with:completionHandler:);;;Argument[0];Argument[1].Parameter[0];taint"
}
}

View File

@@ -123,17 +123,17 @@
| string.swift:39:13:39:19 | ... .+(_:_:) ... | string.swift:39:13:39:29 | ... .+(_:_:) ... |
| string.swift:39:19:39:19 | tainted | string.swift:39:13:39:19 | ... .+(_:_:) ... |
| string.swift:39:29:39:29 | < | string.swift:39:13:39:29 | ... .+(_:_:) ... |
| url.swift:14:29:14:29 | clean | url.swift:14:17:14:34 | call to init(string:) |
| url.swift:15:31:15:31 | tainted | url.swift:15:19:15:38 | call to init(string:) |
| url.swift:20:24:20:24 | clean | url.swift:20:12:20:46 | call to init(string:relativeTo:) |
| url.swift:20:43:20:43 | nil | url.swift:20:12:20:46 | call to init(string:relativeTo:) |
| url.swift:21:24:21:24 | tainted | url.swift:21:12:21:48 | call to init(string:relativeTo:) |
| url.swift:21:45:21:45 | nil | url.swift:21:12:21:48 | call to init(string:relativeTo:) |
| url.swift:22:24:22:24 | clean | url.swift:22:12:22:51 | call to init(string:relativeTo:) |
| url.swift:22:43:22:43 | urlClean | url.swift:22:12:22:51 | call to init(string:relativeTo:) |
| url.swift:23:24:23:24 | clean | url.swift:23:12:23:53 | call to init(string:relativeTo:) |
| url.swift:23:43:23:43 | urlTainted | url.swift:23:12:23:53 | call to init(string:relativeTo:) |
| url.swift:25:25:25:25 | clean | url.swift:25:13:25:30 | call to init(string:) |
| url.swift:29:25:29:25 | tainted | url.swift:29:13:29:32 | call to init(string:) |
| url.swift:34:26:34:26 | clean | url.swift:34:14:34:31 | call to init(string:) |
| url.swift:38:28:38:28 | tainted | url.swift:38:16:38:35 | call to init(string:) |
| url.swift:40:29:40:29 | clean | url.swift:40:17:40:34 | call to init(string:) |
| url.swift:41:31:41:31 | tainted | url.swift:41:19:41:38 | call to init(string:) |
| url.swift:46:24:46:24 | clean | url.swift:46:12:46:46 | call to init(string:relativeTo:) |
| url.swift:46:43:46:43 | nil | url.swift:46:12:46:46 | call to init(string:relativeTo:) |
| url.swift:47:24:47:24 | tainted | url.swift:47:12:47:48 | call to init(string:relativeTo:) |
| url.swift:47:45:47:45 | nil | url.swift:47:12:47:48 | call to init(string:relativeTo:) |
| url.swift:48:24:48:24 | clean | url.swift:48:12:48:51 | call to init(string:relativeTo:) |
| url.swift:48:43:48:43 | urlClean | url.swift:48:12:48:51 | call to init(string:relativeTo:) |
| url.swift:49:24:49:24 | clean | url.swift:49:12:49:53 | call to init(string:relativeTo:) |
| url.swift:49:43:49:43 | urlTainted | url.swift:49:12:49:53 | call to init(string:relativeTo:) |
| url.swift:51:25:51:25 | clean | url.swift:51:13:51:30 | call to init(string:) |
| url.swift:55:25:55:25 | tainted | url.swift:55:13:55:32 | call to init(string:) |
| url.swift:60:26:60:26 | clean | url.swift:60:14:60:31 | call to init(string:) |
| url.swift:64:28:64:28 | tainted | url.swift:64:16:64:35 | call to init(string:) |

View File

@@ -1,4 +1,5 @@
edges
| file://:0:0:0:0 | [summary] to write: argument 1.parameter 0 in dataTask(with:completionHandler:) : | url.swift:67:61:67:61 | data : |
| string.swift:5:11:5:18 | call to source() : | string.swift:7:13:7:13 | "..." |
| string.swift:5:11:5:18 | call to source() : | string.swift:9:13:9:13 | "..." |
| string.swift:5:11:5:18 | call to source() : | string.swift:11:13:11:13 | "..." |
@@ -12,11 +13,34 @@ edges
| try.swift:9:17:9:24 | call to source() : | try.swift:9:13:9:24 | try ... |
| try.swift:15:17:15:24 | call to source() : | try.swift:15:12:15:24 | try! ... |
| try.swift:18:18:18:25 | call to source() : | try.swift:18:12:18:27 | ...! |
| url.swift:13:16:13:23 | call to source() : | url.swift:18:12:18:12 | urlTainted |
| url.swift:13:16:13:23 | call to source() : | url.swift:21:12:21:49 | ...! |
| url.swift:13:16:13:23 | call to source() : | url.swift:23:12:23:54 | ...! |
| url.swift:13:16:13:23 | call to source() : | url.swift:39:12:39:12 | ...! |
| url.swift:8:2:8:25 | [summary param] 0 in init(string:) : | file://:0:0:0:0 | [summary] to write: return (return) in init(string:) : |
| url.swift:8:8:8:16 | string : | file://:0:0:0:0 | [summary] to write: return (return) in init(string:) : |
| url.swift:26:2:29:55 | [summary param] 0 in dataTask(with:completionHandler:) : | file://:0:0:0:0 | [summary] to write: argument 1.parameter 0 in dataTask(with:completionHandler:) : |
| url.swift:27:5:27:15 | url : | file://:0:0:0:0 | [summary] to write: argument 1.parameter 0 in dataTask(with:completionHandler:) : |
| url.swift:39:16:39:23 | call to source() : | url.swift:41:31:41:31 | tainted : |
| url.swift:39:16:39:23 | call to source() : | url.swift:44:12:44:12 | urlTainted |
| url.swift:39:16:39:23 | call to source() : | url.swift:47:12:47:49 | ...! |
| url.swift:39:16:39:23 | call to source() : | url.swift:49:12:49:54 | ...! |
| url.swift:39:16:39:23 | call to source() : | url.swift:64:28:64:28 | tainted : |
| url.swift:39:16:39:23 | call to source() : | url.swift:65:12:65:12 | ...! |
| url.swift:39:16:39:23 | call to source() : | url.swift:67:46:67:46 | urlTainted : |
| url.swift:41:19:41:38 | call to init(string:) : | url.swift:44:12:44:12 | urlTainted |
| url.swift:41:19:41:38 | call to init(string:) : | url.swift:49:12:49:54 | ...! |
| url.swift:41:19:41:38 | call to init(string:) : | url.swift:67:46:67:46 | urlTainted : |
| url.swift:41:31:41:31 | tainted : | url.swift:8:2:8:25 | [summary param] 0 in init(string:) : |
| url.swift:41:31:41:31 | tainted : | url.swift:8:8:8:16 | string : |
| url.swift:41:31:41:31 | tainted : | url.swift:41:19:41:38 | call to init(string:) : |
| url.swift:64:16:64:35 | call to init(string:) : | url.swift:65:12:65:12 | ...! |
| url.swift:64:28:64:28 | tainted : | url.swift:8:2:8:25 | [summary param] 0 in init(string:) : |
| url.swift:64:28:64:28 | tainted : | url.swift:8:8:8:16 | string : |
| url.swift:64:28:64:28 | tainted : | url.swift:64:16:64:35 | call to init(string:) : |
| url.swift:67:46:67:46 | urlTainted : | url.swift:26:2:29:55 | [summary param] 0 in dataTask(with:completionHandler:) : |
| url.swift:67:46:67:46 | urlTainted : | url.swift:27:5:27:15 | url : |
| url.swift:67:61:67:61 | data : | url.swift:68:15:68:19 | ...! |
nodes
| file://:0:0:0:0 | [summary] to write: argument 1.parameter 0 in dataTask(with:completionHandler:) : | semmle.label | [summary] to write: argument 1.parameter 0 in dataTask(with:completionHandler:) : |
| file://:0:0:0:0 | [summary] to write: return (return) in init(string:) : | semmle.label | [summary] to write: return (return) in init(string:) : |
| file://:0:0:0:0 | [summary] to write: return (return) in init(string:) : | semmle.label | [summary] to write: return (return) in init(string:) : |
| string.swift:5:11:5:18 | call to source() : | semmle.label | call to source() : |
| string.swift:7:13:7:13 | "..." | semmle.label | "..." |
| string.swift:9:13:9:13 | "..." | semmle.label | "..." |
@@ -35,12 +59,27 @@ nodes
| try.swift:15:17:15:24 | call to source() : | semmle.label | call to source() : |
| try.swift:18:12:18:27 | ...! | semmle.label | ...! |
| try.swift:18:18:18:25 | call to source() : | semmle.label | call to source() : |
| url.swift:13:16:13:23 | call to source() : | semmle.label | call to source() : |
| url.swift:18:12:18:12 | urlTainted | semmle.label | urlTainted |
| url.swift:21:12:21:49 | ...! | semmle.label | ...! |
| url.swift:23:12:23:54 | ...! | semmle.label | ...! |
| url.swift:39:12:39:12 | ...! | semmle.label | ...! |
| url.swift:8:2:8:25 | [summary param] 0 in init(string:) : | semmle.label | [summary param] 0 in init(string:) : |
| url.swift:8:8:8:16 | string : | semmle.label | string : |
| url.swift:26:2:29:55 | [summary param] 0 in dataTask(with:completionHandler:) : | semmle.label | [summary param] 0 in dataTask(with:completionHandler:) : |
| url.swift:27:5:27:15 | url : | semmle.label | url : |
| url.swift:39:16:39:23 | call to source() : | semmle.label | call to source() : |
| url.swift:41:19:41:38 | call to init(string:) : | semmle.label | call to init(string:) : |
| url.swift:41:31:41:31 | tainted : | semmle.label | tainted : |
| url.swift:44:12:44:12 | urlTainted | semmle.label | urlTainted |
| url.swift:47:12:47:49 | ...! | semmle.label | ...! |
| url.swift:49:12:49:54 | ...! | semmle.label | ...! |
| url.swift:64:16:64:35 | call to init(string:) : | semmle.label | call to init(string:) : |
| url.swift:64:28:64:28 | tainted : | semmle.label | tainted : |
| url.swift:65:12:65:12 | ...! | semmle.label | ...! |
| url.swift:67:46:67:46 | urlTainted : | semmle.label | urlTainted : |
| url.swift:67:61:67:61 | data : | semmle.label | data : |
| url.swift:68:15:68:19 | ...! | semmle.label | ...! |
subpaths
| url.swift:41:31:41:31 | tainted : | url.swift:8:2:8:25 | [summary param] 0 in init(string:) : | file://:0:0:0:0 | [summary] to write: return (return) in init(string:) : | url.swift:41:19:41:38 | call to init(string:) : |
| url.swift:41:31:41:31 | tainted : | url.swift:8:8:8:16 | string : | file://:0:0:0:0 | [summary] to write: return (return) in init(string:) : | url.swift:41:19:41:38 | call to init(string:) : |
| url.swift:64:28:64:28 | tainted : | url.swift:8:2:8:25 | [summary param] 0 in init(string:) : | file://:0:0:0:0 | [summary] to write: return (return) in init(string:) : | url.swift:64:16:64:35 | call to init(string:) : |
| url.swift:64:28:64:28 | tainted : | url.swift:8:8:8:16 | string : | file://:0:0:0:0 | [summary] to write: return (return) in init(string:) : | url.swift:64:16:64:35 | call to init(string:) : |
#select
| string.swift:7:13:7:13 | "..." | string.swift:5:11:5:18 | call to source() : | string.swift:7:13:7:13 | "..." | result |
| string.swift:9:13:9:13 | "..." | string.swift:5:11:5:18 | call to source() : | string.swift:9:13:9:13 | "..." | result |
@@ -55,7 +94,8 @@ subpaths
| try.swift:9:13:9:24 | try ... | try.swift:9:17:9:24 | call to source() : | try.swift:9:13:9:24 | try ... | result |
| try.swift:15:12:15:24 | try! ... | try.swift:15:17:15:24 | call to source() : | try.swift:15:12:15:24 | try! ... | result |
| try.swift:18:12:18:27 | ...! | try.swift:18:18:18:25 | call to source() : | try.swift:18:12:18:27 | ...! | result |
| url.swift:18:12:18:12 | urlTainted | url.swift:13:16:13:23 | call to source() : | url.swift:18:12:18:12 | urlTainted | result |
| url.swift:21:12:21:49 | ...! | url.swift:13:16:13:23 | call to source() : | url.swift:21:12:21:49 | ...! | result |
| url.swift:23:12:23:54 | ...! | url.swift:13:16:13:23 | call to source() : | url.swift:23:12:23:54 | ...! | result |
| url.swift:39:12:39:12 | ...! | url.swift:13:16:13:23 | call to source() : | url.swift:39:12:39:12 | ...! | result |
| url.swift:44:12:44:12 | urlTainted | url.swift:39:16:39:23 | call to source() : | url.swift:44:12:44:12 | urlTainted | result |
| url.swift:47:12:47:49 | ...! | url.swift:39:16:39:23 | call to source() : | url.swift:47:12:47:49 | ...! | result |
| url.swift:49:12:49:54 | ...! | url.swift:39:16:39:23 | call to source() : | url.swift:49:12:49:54 | ...! | result |
| url.swift:65:12:65:12 | ...! | url.swift:39:16:39:23 | call to source() : | url.swift:65:12:65:12 | ...! | result |
| url.swift:68:15:68:19 | ...! | url.swift:39:16:39:23 | call to source() : | url.swift:68:15:68:19 | ...! | result |

View File

@@ -1,12 +1,38 @@
class NSObject
{
}
struct URL
{
init?(string: String) {}
init?(string: String, relativeTo: URL?) {}
}
class Data
{
init<S>(_ elements: S) {}
}
class URLResponse : NSObject {}
class URLSessionTask : NSObject { }
class URLSessionDataTask : URLSessionTask { }
class URLSession {
class var shared: URLSession { get { return URLSession() } }
func dataTask(
with url: URL,
completionHandler: (Data?, URLResponse?, Error?) -> Void
) -> URLSessionDataTask { return URLSessionDataTask() }
}
func source() -> String { return "" }
func sink(arg: URL) {}
func sink(data: Data) {}
func sink(string: String) {}
func taintThroughURL() {
let clean = "http://example.com/"
@@ -15,19 +41,19 @@ func taintThroughURL() {
let urlTainted = URL(string: tainted)!
sink(arg: urlClean)
sink(arg: urlTainted) // $ tainted=13
sink(arg: urlTainted) // $ tainted=39
sink(arg: URL(string: clean, relativeTo: nil)!)
sink(arg: URL(string: tainted, relativeTo: nil)!) // $ tainted=13
sink(arg: URL(string: tainted, relativeTo: nil)!) // $ tainted=39
sink(arg: URL(string: clean, relativeTo: urlClean)!)
sink(arg: URL(string: clean, relativeTo: urlTainted)!) // $ tainted=13
sink(arg: URL(string: clean, relativeTo: urlTainted)!) // $ tainted=39
if let x = URL(string: clean) {
sink(arg: x)
}
if let y = URL(string: tainted) {
sink(arg: y) // $ MISSING: tainted=13
sink(arg: y) // $ MISSING: tainted=39
}
var urlClean2 : URL!
@@ -36,5 +62,9 @@ func taintThroughURL() {
var urlTainted2 : URL!
urlTainted2 = URL(string: tainted)
sink(arg: urlTainted2) // $ tainted=13
sink(arg: urlTainted2) // $ tainted=39
let task = URLSession.shared.dataTask(with: urlTainted) { (data, response, error) in
sink(data: data!) // $ tainted=39
}
}