Skip to content

Commit fe69bbf

Browse files
committed
Swift: It turns out NSString.length always exactly matches String.utf16.count.
1 parent 70ca37a commit fe69bbf

File tree

3 files changed

+17
-9
lines changed

3 files changed

+17
-9
lines changed

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

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,20 +18,29 @@ import DataFlow::PathGraph
1818
* A flow state for this query, which is a type of Swift string encoding.
1919
*/
2020
class StringLengthConflationFlowState extends string {
21+
string equivClass;
2122
string singular;
2223

2324
StringLengthConflationFlowState() {
24-
this = "String" and singular = "a String"
25+
this = "String" and singular = "a String" and equivClass = "String"
2526
or
26-
this = "NSString" and singular = "an NSString"
27+
this = "NSString" and singular = "an NSString" and equivClass = "NSString"
2728
or
28-
this = "String.utf8" and singular = "a String.utf8"
29+
this = "String.utf8" and singular = "a String.utf8" and equivClass = "String.utf8"
2930
or
30-
this = "String.utf16" and singular = "a String.utf16"
31+
this = "String.utf16" and singular = "a String.utf16" and equivClass = "NSString"
3132
or
32-
this = "String.unicodeScalars" and singular = "a String.unicodeScalars"
33+
this = "String.unicodeScalars" and
34+
singular = "a String.unicodeScalars" and
35+
equivClass = "String.unicodeScalars"
3336
}
3437

38+
/**
39+
* Gets the equivalence class for this flow state. If these are equal,
40+
* they should be treated as equivalent.
41+
*/
42+
string getEquivClass() { result = equivClass }
43+
3544
/**
3645
* Gets text for the singular form of this flow state.
3746
*/
@@ -183,7 +192,8 @@ class StringLengthConflationConfiguration extends DataFlow::Configuration {
183192
// should report.
184193
exists(string correctFlowState |
185194
isSinkImpl(node, correctFlowState) and
186-
flowstate.(StringLengthConflationFlowState) != correctFlowState
195+
flowstate.(StringLengthConflationFlowState).getEquivClass() !=
196+
correctFlowState.(StringLengthConflationFlowState).getEquivClass()
187197
)
188198
}
189199

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

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ nodes
2626
| StringLengthConflation.swift:72:33:72:35 | .count | semmle.label | .count |
2727
| StringLengthConflation.swift:78:47:78:49 | .count | semmle.label | .count |
2828
| StringLengthConflation.swift:79:47:79:54 | .count | semmle.label | .count |
29-
| StringLengthConflation.swift:80:47:80:55 | .count | semmle.label | .count |
3029
| StringLengthConflation.swift:81:47:81:64 | .count | semmle.label | .count |
3130
| StringLengthConflation.swift:96:28:96:31 | .length : | semmle.label | .length : |
3231
| StringLengthConflation.swift:96:28:96:40 | ... call to -(_:_:) ... | semmle.label | ... call to -(_:_:) ... |
@@ -65,7 +64,6 @@ subpaths
6564
| 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. |
6665
| 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. |
6766
| StringLengthConflation.swift:79:47:79:54 | .count | StringLengthConflation.swift:79:47:79:54 | .count | StringLengthConflation.swift:79:47:79:54 | .count | This String.utf8 length is used in an NSString, but it may not be equivalent. |
68-
| StringLengthConflation.swift:80:47:80:55 | .count | StringLengthConflation.swift:80:47:80:55 | .count | StringLengthConflation.swift:80:47:80:55 | .count | This String.utf16 length is used in an NSString, but it may not be equivalent. |
6967
| StringLengthConflation.swift:81:47:81:64 | .count | StringLengthConflation.swift:81:47:81:64 | .count | StringLengthConflation.swift:81:47:81:64 | .count | This String.unicodeScalars length is used in an NSString, but it may not be equivalent. |
7068
| StringLengthConflation.swift:96:28:96:40 | ... call to -(_:_:) ... | StringLengthConflation.swift:96:28:96:31 | .length : | StringLengthConflation.swift:96:28:96:40 | ... call to -(_:_:) ... | This NSString length is used in a String, but it may not be equivalent. |
7169
| StringLengthConflation.swift:100:27:100:39 | ... call to -(_:_:) ... | StringLengthConflation.swift:100:27:100:30 | .length : | StringLengthConflation.swift:100:27:100:39 | ... 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: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ func test(s: String) {
7777
let range5 = NSRange(location: 0, length: ns.length) // GOOD
7878
let range6 = NSRange(location: 0, length: s.count) // BAD: String length used in NSMakeRange
7979
let range7 = NSRange(location: 0, length: s.utf8.count) // BAD: String.utf8 length used in NSMakeRange
80-
let range8 = NSRange(location: 0, length: s.utf16.count) // BAD: String.utf16 length used in NSMakeRange
80+
let range8 = NSRange(location: 0, length: s.utf16.count) // GOOD: String.utf16 length and NSRange count are equivalent
8181
let range9 = NSRange(location: 0, length: s.unicodeScalars.count) // BAD: String.unicodeScalars length used in NSMakeRange
8282
print("NSRange '\(range5.description)' / '\(range6.description)' '\(range7.description)' '\(range8.description)' '\(range9.description)'")
8383

0 commit comments

Comments
 (0)