Skip to content

Commit 34ffd1a

Browse files
committed
Swift: Support String.Index and flow through * /.
1 parent d60d245 commit 34ffd1a

File tree

3 files changed

+22
-7
lines changed

3 files changed

+22
-7
lines changed

swift/ql/src/queries/Security/CWE-135/StringLengthConflation.ql

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -95,17 +95,25 @@ class StringLengthConflationConfiguration extends DataFlow::Configuration {
9595
// arguments to function calls...
9696
exists(string funcName, string paramName, CallExpr call, int arg |
9797
(
98-
// `dropFirst`, `dropLast`, `removeFirst`, `removeLast`
98+
// `String.dropFirst`, `String.dropLast`, `String.removeFirst`, `String.removeLast`
9999
funcName = ["dropFirst(_:)", "dropLast(_:)", "removeFirst(_:)", "removeLast(_:)"] and
100100
paramName = "k"
101101
or
102-
// `prefix`, `suffix`
102+
// `String.prefix`, `String.suffix`
103103
funcName = ["prefix(_:)", "suffix(_:)"] and
104104
paramName = "maxLength"
105105
or
106106
// `String.Index.init`
107107
funcName = "init(encodedOffset:)" and
108108
paramName = "offset"
109+
or
110+
// `String.index`
111+
funcName = ["index(_:offsetBy:)", "index(_:offsetBy:limitBy:)"] and
112+
paramName = "n"
113+
or
114+
// `String.formIndex`
115+
funcName = ["formIndex(_:offsetBy:)", "formIndex(_:offsetBy:limitBy:)"] and
116+
paramName = "distance"
109117
) and
110118
call.getFunction().(ApplyExpr).getStaticTarget().getName() = funcName and
111119
call.getFunction()
@@ -119,9 +127,8 @@ class StringLengthConflationConfiguration extends DataFlow::Configuration {
119127
}
120128

121129
override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
122-
// allow flow through `+` and `-`.
123-
node2.asExpr().(AddExpr).getAnOperand() = node1.asExpr() or
124-
node2.asExpr().(SubExpr).getAnOperand() = node1.asExpr()
130+
// allow flow through `+`, `-`, `*` etc.
131+
node2.asExpr().(ArithmeticOperation).getAnOperand() = node1.asExpr()
125132
}
126133
}
127134

swift/ql/test/query-tests/Security/CWE-135/StringLengthConflation.expected

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
edges
2+
| StringLengthConflation.swift:60:47:60:50 | .length : | StringLengthConflation.swift:60:47:60:59 | ... call to /(_:_:) ... |
3+
| StringLengthConflation.swift:66:33:66:36 | .length : | StringLengthConflation.swift:66:33:66:45 | ... call to /(_:_:) ... |
24
| StringLengthConflation.swift:93:28:93:31 | .length : | StringLengthConflation.swift:93:28:93:40 | ... call to -(_:_:) ... |
35
| StringLengthConflation.swift:97:27:97:30 | .length : | StringLengthConflation.swift:97:27:97:39 | ... call to -(_:_:) ... |
46
| StringLengthConflation.swift:101:25:101:28 | .length : | StringLengthConflation.swift:101:25:101:37 | ... call to -(_:_:) ... |
@@ -14,6 +16,10 @@ edges
1416
| StringLengthConflation.swift:141:28:141:30 | .count : | StringLengthConflation.swift:141:28:141:38 | ... call to -(_:_:) ... |
1517
nodes
1618
| StringLengthConflation.swift:53:43:53:46 | .length | semmle.label | .length |
19+
| StringLengthConflation.swift:60:47:60:50 | .length : | semmle.label | .length : |
20+
| StringLengthConflation.swift:60:47:60:59 | ... call to /(_:_:) ... | semmle.label | ... call to /(_:_:) ... |
21+
| StringLengthConflation.swift:66:33:66:36 | .length : | semmle.label | .length : |
22+
| StringLengthConflation.swift:66:33:66:45 | ... call to /(_:_:) ... | semmle.label | ... call to /(_:_:) ... |
1723
| StringLengthConflation.swift:72:33:72:35 | .count | semmle.label | .count |
1824
| StringLengthConflation.swift:78:47:78:49 | .count | semmle.label | .count |
1925
| StringLengthConflation.swift:93:28:93:31 | .length : | semmle.label | .length : |
@@ -45,6 +51,8 @@ nodes
4551
subpaths
4652
#select
4753
| StringLengthConflation.swift:53:43:53:46 | .length | StringLengthConflation.swift:53:43:53:46 | .length | StringLengthConflation.swift:53:43:53:46 | .length | This NSString length is used in a String, but it may not be equivalent. |
54+
| StringLengthConflation.swift:60:47:60:59 | ... call to /(_:_:) ... | StringLengthConflation.swift:60:47:60:50 | .length : | StringLengthConflation.swift:60:47:60:59 | ... call to /(_:_:) ... | This NSString length is used in a String, but it may not be equivalent. |
55+
| StringLengthConflation.swift:66:33:66:45 | ... call to /(_:_:) ... | StringLengthConflation.swift:66:33:66:36 | .length : | StringLengthConflation.swift:66:33:66:45 | ... call to /(_:_:) ... | This NSString length is used in a String, but it may not be equivalent. |
4856
| StringLengthConflation.swift:72:33:72:35 | .count | StringLengthConflation.swift:72:33:72:35 | .count | StringLengthConflation.swift:72:33:72:35 | .count | This String length is used in an NSString, but it may not be equivalent. |
4957
| StringLengthConflation.swift:78:47:78:49 | .count | StringLengthConflation.swift:78:47:78:49 | .count | StringLengthConflation.swift:78:47:78:49 | .count | This String length is used in an NSString, but it may not be equivalent. |
5058
| StringLengthConflation.swift:93:28:93:40 | ... call to -(_:_:) ... | StringLengthConflation.swift:93:28:93:31 | .length : | StringLengthConflation.swift:93:28:93:40 | ... call to -(_:_:) ... | This NSString length is used in a String, but it may not be equivalent. |

swift/ql/test/query-tests/Security/CWE-135/StringLengthConflation.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,13 +57,13 @@ func test(s: String) {
5757
print("String.Index '\(ix1.encodedOffset)' / '\(ix2.encodedOffset)' '\(ix3.encodedOffset)' '\(ix4.encodedOffset)' '\(ix5.encodedOffset)'")
5858

5959
let ix6 = s.index(s.startIndex, offsetBy: s.count / 2) // GOOD
60-
let ix7 = s.index(s.startIndex, offsetBy: ns.length / 2) // BAD: NSString length used in String.Index [NOT DETECTED]
60+
let ix7 = s.index(s.startIndex, offsetBy: ns.length / 2) // BAD: NSString length used in String.Index
6161
print("index '\(ix6.encodedOffset)' / '\(ix7.encodedOffset)'")
6262

6363
var ix8 = s.startIndex
6464
s.formIndex(&ix8, offsetBy: s.count / 2) // GOOD
6565
var ix9 = s.startIndex
66-
s.formIndex(&ix9, offsetBy: ns.length / 2) // BAD: NSString length used in String.Index [NOT DETECTED]
66+
s.formIndex(&ix9, offsetBy: ns.length / 2) // BAD: NSString length used in String.Index
6767
print("formIndex '\(ix8.encodedOffset)' / '\(ix9.encodedOffset)'")
6868

6969
// --- constructing an NSRange from integers ---

0 commit comments

Comments
 (0)