Skip to content

Commit 5723a75

Browse files
committed
Swift: Add heuristic model for init(contentsOfFile) and similar.
1 parent 94cb09e commit 5723a75

File tree

3 files changed

+54
-5
lines changed

3 files changed

+54
-5
lines changed

swift/ql/lib/codeql/swift/frameworks/Frameworks.qll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ private import SQL.SQL
88
private import StandardLibrary.StandardLibrary
99
private import UIKit.UIKit
1010
private import Xml.Xml
11+
private import Heuristic
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/**
2+
* Provides heuristic models that match taint sources and flow through unknown
3+
* classes and libraries.
4+
*/
5+
6+
import swift
7+
private import codeql.swift.dataflow.DataFlow
8+
private import codeql.swift.dataflow.FlowSources
9+
10+
/**
11+
* An imprecise flow source for an initializer call with a "contentsOf"
12+
* argument that appears to be remote. For example:
13+
* ```
14+
* let myObject = MyClass(contentsOf: url)
15+
* ```
16+
*/
17+
private class InitializerContentsOfRemoteSource extends RemoteFlowSource {
18+
InitializerContentsOfRemoteSource() {
19+
exists(InitializerCallExpr ce, Argument arg |
20+
ce.getAnArgument() = arg and
21+
arg.getLabel() = ["contentsOf", "contentsOfFile", "contentsOfPath", "contentsOfDirectory"] and
22+
arg.getExpr().getType().getUnderlyingType().getName() = ["URL", "NSURL"] and
23+
this.asExpr() = ce
24+
)
25+
}
26+
27+
override string getSourceType() { result = "contentsOf initializer" }
28+
}
29+
30+
/**
31+
* An imprecise flow source for an initializer call with a "contentsOf"
32+
* argument that appears to be local. For example:
33+
* ```
34+
* let myObject = MyClass(contentsOfFile: "foo.txt")
35+
* ```
36+
*/
37+
private class InitializerContentsOfLocalSource extends LocalFlowSource {
38+
InitializerContentsOfLocalSource() {
39+
exists(InitializerCallExpr ce, Argument arg |
40+
ce.getAnArgument() = arg and
41+
arg.getLabel() = ["contentsOf", "contentsOfFile", "contentsOfPath", "contentsOfDirectory"] and
42+
not arg.getExpr().getType().getUnderlyingType().getName() = ["URL", "NSURL"] and
43+
this.asExpr() = ce
44+
)
45+
}
46+
47+
override string getSourceType() { result = "contentsOf initializer" }
48+
}

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

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,12 @@ class MyClass {
2222
func testCustom() {
2323
let url = URL(string: "http://example.com/")!
2424

25-
let x = MyClass(contentsOfFile: "foo.txt") // $ MISSING: source=remote
26-
_ = MyClass(contentsOfFile: "foo.txt", options: []) // $ MISSING: source=remote
27-
_ = MyClass(contentsOf: url, fileTypeHint: 1) // $ MISSING: source=remote
25+
let x = MyClass(contentsOfFile: "foo.txt") // $ source=local
26+
_ = MyClass(contentsOfFile: "foo.txt", options: []) // $ source=local
27+
_ = MyClass(contentsOf: url, fileTypeHint: 1) // $ source=remote
2828

29-
_ = MyClass(contentsOfPath: "/foo/bar") // $ MISSING: source=remote
30-
_ = MyClass(contentsOfDirectory: "/foo/bar") // $ MISSING: source=remote
29+
_ = MyClass(contentsOfPath: "/foo/bar") // $ source=local
30+
_ = MyClass(contentsOfDirectory: "/foo/bar") // $ source=local
3131

3232
x.append(contentsOf: "abcdef") // (not a flow source)
3333
_ = x.appending(contentsOf: "abcdef") // (not a flow source)

0 commit comments

Comments
 (0)