Skip to content

Commit 4cdc257

Browse files
committed
Swift: Add more sinks.
1 parent 315cae2 commit 4cdc257

File tree

3 files changed

+47
-8
lines changed

3 files changed

+47
-8
lines changed

swift/ql/lib/codeql/swift/security/regex/RegexInjectionExtensions.qll

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ class RegexInjectionAdditionalFlowStep extends Unit {
3131

3232
/**
3333
* A sink that is a regular expression evaluation defined in the Regex library.
34+
* This includes various methods that consume a regular expression string, but
35+
* in general misses cases where a regular expression string is converted into
36+
* an object (such as a `Regex` or `NSRegularExpression`) for later evaluation.
37+
* These cases are modelled separately.
3438
*/
3539
private class EvalRegexInjectionSink extends RegexInjectionSink {
3640
EvalRegexInjectionSink() { this.asExpr() = any(RegexEval e).getRegexInput() }
@@ -42,3 +46,14 @@ private class EvalRegexInjectionSink extends RegexInjectionSink {
4246
private class DefaultRegexInjectionSink extends RegexInjectionSink {
4347
DefaultRegexInjectionSink() { sinkNode(this, "regex-use") }
4448
}
49+
50+
private class RegexInjectionSinks extends SinkModelCsv {
51+
override predicate row(string row) {
52+
row =
53+
[
54+
";Regex;true;init(_:);;;Argument[0];regex-use",
55+
";Regex;true;init(_:as:);;;Argument[0];regex-use",
56+
";NSRegularExpression;true;init(pattern:options:);;;Argument[0];regex-use",
57+
]
58+
}
59+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,32 @@
11
edges
2+
| tests.swift:93:22:93:46 | call to String.init(contentsOf:) | tests.swift:99:16:99:16 | taintedString |
3+
| tests.swift:93:22:93:46 | call to String.init(contentsOf:) | tests.swift:102:16:102:40 | ... .+(_:_:) ... |
4+
| tests.swift:93:22:93:46 | call to String.init(contentsOf:) | tests.swift:104:16:104:16 | "..." |
5+
| tests.swift:93:22:93:46 | call to String.init(contentsOf:) | tests.swift:107:16:107:39 | ... ? ... : ... |
6+
| tests.swift:93:22:93:46 | call to String.init(contentsOf:) | tests.swift:108:16:108:37 | ... ? ... : ... |
7+
| tests.swift:93:22:93:46 | call to String.init(contentsOf:) | tests.swift:111:24:111:24 | taintedString |
8+
| tests.swift:93:22:93:46 | call to String.init(contentsOf:) | tests.swift:112:45:112:45 | taintedString |
29
| tests.swift:93:22:93:46 | call to String.init(contentsOf:) | tests.swift:118:19:118:19 | taintedString |
10+
| tests.swift:93:22:93:46 | call to String.init(contentsOf:) | tests.swift:129:39:129:39 | taintedString |
311
nodes
412
| tests.swift:93:22:93:46 | call to String.init(contentsOf:) | semmle.label | call to String.init(contentsOf:) |
13+
| tests.swift:99:16:99:16 | taintedString | semmle.label | taintedString |
14+
| tests.swift:102:16:102:40 | ... .+(_:_:) ... | semmle.label | ... .+(_:_:) ... |
15+
| tests.swift:104:16:104:16 | "..." | semmle.label | "..." |
16+
| tests.swift:107:16:107:39 | ... ? ... : ... | semmle.label | ... ? ... : ... |
17+
| tests.swift:108:16:108:37 | ... ? ... : ... | semmle.label | ... ? ... : ... |
18+
| tests.swift:111:24:111:24 | taintedString | semmle.label | taintedString |
19+
| tests.swift:112:45:112:45 | taintedString | semmle.label | taintedString |
520
| tests.swift:118:19:118:19 | taintedString | semmle.label | taintedString |
21+
| tests.swift:129:39:129:39 | taintedString | semmle.label | taintedString |
622
subpaths
723
#select
24+
| tests.swift:99:16:99:16 | taintedString | tests.swift:93:22:93:46 | call to String.init(contentsOf:) | tests.swift:99:16:99:16 | taintedString | This regular expression is constructed from a $@. | tests.swift:93:22:93:46 | call to String.init(contentsOf:) | user-provided value |
25+
| tests.swift:102:16:102:40 | ... .+(_:_:) ... | tests.swift:93:22:93:46 | call to String.init(contentsOf:) | tests.swift:102:16:102:40 | ... .+(_:_:) ... | This regular expression is constructed from a $@. | tests.swift:93:22:93:46 | call to String.init(contentsOf:) | user-provided value |
26+
| tests.swift:104:16:104:16 | "..." | tests.swift:93:22:93:46 | call to String.init(contentsOf:) | tests.swift:104:16:104:16 | "..." | This regular expression is constructed from a $@. | tests.swift:93:22:93:46 | call to String.init(contentsOf:) | user-provided value |
27+
| tests.swift:107:16:107:39 | ... ? ... : ... | tests.swift:93:22:93:46 | call to String.init(contentsOf:) | tests.swift:107:16:107:39 | ... ? ... : ... | This regular expression is constructed from a $@. | tests.swift:93:22:93:46 | call to String.init(contentsOf:) | user-provided value |
28+
| tests.swift:108:16:108:37 | ... ? ... : ... | tests.swift:93:22:93:46 | call to String.init(contentsOf:) | tests.swift:108:16:108:37 | ... ? ... : ... | This regular expression is constructed from a $@. | tests.swift:93:22:93:46 | call to String.init(contentsOf:) | user-provided value |
29+
| tests.swift:111:24:111:24 | taintedString | tests.swift:93:22:93:46 | call to String.init(contentsOf:) | tests.swift:111:24:111:24 | taintedString | This regular expression is constructed from a $@. | tests.swift:93:22:93:46 | call to String.init(contentsOf:) | user-provided value |
30+
| tests.swift:112:45:112:45 | taintedString | tests.swift:93:22:93:46 | call to String.init(contentsOf:) | tests.swift:112:45:112:45 | taintedString | This regular expression is constructed from a $@. | tests.swift:93:22:93:46 | call to String.init(contentsOf:) | user-provided value |
831
| tests.swift:118:19:118:19 | taintedString | tests.swift:93:22:93:46 | call to String.init(contentsOf:) | tests.swift:118:19:118:19 | taintedString | This regular expression is constructed from a $@. | tests.swift:93:22:93:46 | call to String.init(contentsOf:) | user-provided value |
32+
| tests.swift:129:39:129:39 | taintedString | tests.swift:93:22:93:46 | call to String.init(contentsOf:) | tests.swift:129:39:129:39 | taintedString | This regular expression is constructed from a $@. | tests.swift:93:22:93:46 | call to String.init(contentsOf:) | user-provided value |

swift/ql/test/query-tests/Security/CWE-730/tests.swift

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -96,20 +96,20 @@ func regexInjectionTests(cond: Bool, varString: String, myUrl: URL) throws {
9696

9797
_ = try Regex(constString).firstMatch(in: varString)
9898
_ = try Regex(varString).firstMatch(in: varString)
99-
_ = try Regex(taintedString).firstMatch(in: varString) // BAD [NOT DETECTED]
99+
_ = try Regex(taintedString).firstMatch(in: varString) // BAD
100100

101101
_ = try Regex("(a|" + constString + ")").firstMatch(in: varString)
102-
_ = try Regex("(a|" + taintedString + ")").firstMatch(in: varString) // BAD [NOT DETECTED]
102+
_ = try Regex("(a|" + taintedString + ")").firstMatch(in: varString) // BAD
103103
_ = try Regex("(a|\(constString))").firstMatch(in: varString)
104-
_ = try Regex("(a|\(taintedString))").firstMatch(in: varString) // BAD [NOT DETECTED]
104+
_ = try Regex("(a|\(taintedString))").firstMatch(in: varString) // BAD
105105

106106
_ = try Regex(cond ? constString : constString).firstMatch(in: varString)
107-
_ = try Regex(cond ? taintedString : constString).firstMatch(in: varString) // BAD [NOT DETECTED]
108-
_ = try Regex(cond ? constString : taintedString).firstMatch(in: varString) // BAD [NOT DETECTED]
107+
_ = try Regex(cond ? taintedString : constString).firstMatch(in: varString) // BAD
108+
_ = try Regex(cond ? constString : taintedString).firstMatch(in: varString) // BAD
109109

110110
_ = try (cond ? Regex(constString) : Regex(constString)).firstMatch(in: varString)
111-
_ = try (cond ? Regex(taintedString) : Regex(constString)).firstMatch(in: varString) // BAD [NOT DETECTED]
112-
_ = try (cond ? Regex(constString) : Regex(taintedString)).firstMatch(in: varString) // BAD [NOT DETECTED]
111+
_ = try (cond ? Regex(taintedString) : Regex(constString)).firstMatch(in: varString) // BAD
112+
_ = try (cond ? Regex(constString) : Regex(taintedString)).firstMatch(in: varString) // BAD
113113

114114
// --- RangeReplaceableCollection ---
115115

@@ -126,7 +126,7 @@ func regexInjectionTests(cond: Bool, varString: String, myUrl: URL) throws {
126126
// --- NSRegularExpression ---
127127

128128
_ = try NSRegularExpression(pattern: constString).firstMatch(in: varString, range: NSMakeRange(0, varString.utf16.count))
129-
_ = try NSRegularExpression(pattern: taintedString).firstMatch(in: varString, range: NSMakeRange(0, varString.utf16.count)) // BAD [NOT DETECTED]
129+
_ = try NSRegularExpression(pattern: taintedString).firstMatch(in: varString, range: NSMakeRange(0, varString.utf16.count)) // BAD
130130

131131
// --- NSString ---
132132

0 commit comments

Comments
 (0)