Skip to content

Commit 4cdcebf

Browse files
authored
Merge pull request #11161 from geoffw0/localflowsource
Swift: Add LocalFlowSource class and a few sources.
2 parents 6fb021a + 25b4296 commit 4cdcebf

File tree

6 files changed

+93
-9
lines changed

6 files changed

+93
-9
lines changed

swift/ql/lib/codeql/swift/dataflow/FlowSources.qll

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,35 @@
55
private import ExternalFlow
66
private import internal.DataFlowPublic
77

8-
/** A data flow source of remote user input. */
9-
abstract class RemoteFlowSource extends Node {
10-
/** Gets a string that describes the type of this remote flow source. */
8+
/**
9+
* A data flow source of user input, whether local or remote.
10+
*/
11+
abstract class FlowSource extends Node {
12+
/** Gets a string that describes the type of this flow source. */
1113
abstract string getSourceType();
1214
}
1315

16+
/**
17+
* A data flow source of local user input, that is, user input from the same
18+
* device as the code is running on.
19+
*/
20+
abstract class LocalFlowSource extends FlowSource { }
21+
22+
/**
23+
* A data flow source of remote user input. In this context, 'remote' means
24+
* either across a network or from another application that is not trusted.
25+
*/
26+
abstract class RemoteFlowSource extends FlowSource { }
27+
28+
/**
29+
* A data flow source of local user input that is defined through 'models as data'.
30+
*/
31+
private class ExternalLocalFlowSource extends RemoteFlowSource {
32+
ExternalLocalFlowSource() { sourceNode(this, "local") }
33+
34+
override string getSourceType() { result = "external" }
35+
}
36+
1437
/**
1538
* A data flow source of remote user input that is defined through 'models as data'.
1639
*/

swift/ql/lib/codeql/swift/frameworks/StandardLibrary/String.qll

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,13 @@ private class StringSource extends SourceModelCsv {
66
row =
77
[
88
// String(contentsOf:) is a remote flow source
9-
";String;true;init(contentsOf:);(URL);;ReturnValue;remote"
9+
";String;true;init(contentsOf:);(URL);;ReturnValue;remote",
10+
";String;true;init(contentsOf:encoding:);(URL,String.Encoding);;ReturnValue;remote",
11+
";String;true;init(contentsOf:usedEncoding:);(URL,String.Encoding);;ReturnValue;remote",
12+
// String(contentsOfFile:) is a local flow source
13+
";String;true;init(contentsOfFile:);(String);;ReturnValue;local",
14+
";String;true;init(contentsOfFile:encoding:);(String,String.Encoding);;ReturnValue;local",
15+
";String;true;init(contentsOfFile:usedEncoding:);(String,String.Encoding);;ReturnValue;local"
1016
]
1117
}
1218
}

swift/ql/src/queries/Summary/FlowSources.ql

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,11 @@
1212
import swift
1313
import codeql.swift.dataflow.FlowSources
1414

15-
from RemoteFlowSource s
16-
select s, "Flow source: " + s.getSourceType()
15+
string sourceClass(FlowSource s) {
16+
s instanceof LocalFlowSource and result = "LocalFlowSource"
17+
or
18+
s instanceof RemoteFlowSource and result = "RemoteFlowSource"
19+
}
20+
21+
from FlowSource s
22+
select s, sourceClass(s) + ": " + s.getSourceType()

swift/ql/src/queries/Summary/SummaryStats.ql

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ predicate statistic(string what, int value) {
1515
or
1616
what = "Expressions" and value = count(Expr e | not e.getFile() instanceof UnknownFile)
1717
or
18+
what = "Local flow sources" and value = count(LocalFlowSource s)
19+
or
1820
what = "Remote flow sources" and value = count(RemoteFlowSource s)
1921
or
2022
what = "Sensitive expressions" and value = count(SensitiveExpr e)

swift/ql/test/library-tests/dataflow/flowsources/FlowSources.expected

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,18 @@
33
| customurlschemes.swift:38:52:38:62 | url | external |
44
| customurlschemes.swift:43:9:43:28 | ...[...] | Remote URL in UIApplicationDelegate.application.launchOptions |
55
| customurlschemes.swift:48:9:48:28 | ...[...] | Remote URL in UIApplicationDelegate.application.launchOptions |
6-
| string.swift:27:21:27:21 | call to init(contentsOf:) | external |
7-
| string.swift:27:21:27:44 | call to init(contentsOf:) | external |
6+
| string.swift:56:21:56:21 | call to init(contentsOf:) | external |
7+
| string.swift:56:21:56:44 | call to init(contentsOf:) | external |
8+
| string.swift:57:21:57:21 | call to init(contentsOf:encoding:) | external |
9+
| string.swift:57:21:57:77 | call to init(contentsOf:encoding:) | external |
10+
| string.swift:59:21:59:21 | call to init(contentsOf:usedEncoding:) | external |
11+
| string.swift:59:21:59:69 | call to init(contentsOf:usedEncoding:) | external |
12+
| string.swift:62:21:62:21 | call to init(contentsOfFile:) | external |
13+
| string.swift:62:21:62:48 | call to init(contentsOfFile:) | external |
14+
| string.swift:63:21:63:21 | call to init(contentsOfFile:encoding:) | external |
15+
| string.swift:63:21:63:81 | call to init(contentsOfFile:encoding:) | external |
16+
| string.swift:64:21:64:21 | call to init(contentsOfFile:usedEncoding:) | external |
17+
| string.swift:64:21:64:73 | call to init(contentsOfFile:usedEncoding:) | external |
818
| url.swift:53:15:53:19 | .resourceBytes | external |
919
| url.swift:60:15:60:19 | .lines | external |
1020
| url.swift:67:16:67:22 | .lines | external |

swift/ql/test/library-tests/dataflow/flowsources/string.swift

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,41 @@ struct URL
77
}
88

99
extension String {
10-
init(contentsOf: URL) throws {
10+
struct Encoding {
11+
var rawValue: UInt
12+
13+
init(rawValue: UInt) { self.rawValue = rawValue }
14+
15+
static let ascii = Encoding(rawValue: 1)
16+
}
17+
18+
init(contentsOf url: URL) throws {
1119
var data = ""
1220

1321
// ...
1422

1523
self.init(data)
1624
}
25+
26+
init(contentsOf url: URL, encoding enc: String.Encoding) throws {
27+
self.init("")
28+
}
29+
30+
init(contentsOf url: URL, usedEncoding: inout String.Encoding) throws {
31+
self.init("")
32+
}
33+
34+
init(contentsOfFile path: String) throws {
35+
self.init("")
36+
}
37+
38+
init(contentsOfFile path: String, encoding enc: String.Encoding) throws {
39+
self.init("")
40+
}
41+
42+
init(contentsOfFile path: String, usedEncoding: inout String.Encoding) throws {
43+
self.init("")
44+
}
1745
}
1846

1947
// --- tests ---
@@ -23,8 +51,17 @@ func testStrings() {
2351
{
2452
let string1 = String()
2553
let string2 = String(repeating: "abc", count: 10)
54+
2655
let url = URL(string: "http://example.com/")
2756
let string3 = try String(contentsOf: url!) // SOURCE
57+
let string4 = try String(contentsOf: url!, encoding: String.Encoding.ascii) // SOURCE
58+
var encoding = String.Encoding.ascii
59+
let string5 = try String(contentsOf: url!, usedEncoding: &encoding) // SOURCE
60+
61+
let path = "file.txt"
62+
let string6 = try String(contentsOfFile: path) // SOURCE
63+
let string7 = try String(contentsOfFile: path, encoding: String.Encoding.ascii) // SOURCE
64+
let string8 = try String(contentsOfFile: path, usedEncoding: &encoding) // SOURCE
2865
} catch {
2966
// ...
3067
}

0 commit comments

Comments
 (0)