Skip to content

Commit 49428c4

Browse files
authored
Merge pull request #14683 from geoffw0/nsstringclosure
Swift: Model NSString.enumerate*
2 parents d86293f + e621d20 commit 49428c4

File tree

3 files changed

+30
-11
lines changed

3 files changed

+30
-11
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
category: minorAnalysis
3+
---
4+
* Added taint flow models for the `NSString.enumerate*` methods.

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

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ private class NsStringSummaries extends SummaryModelCsv {
8383
";NSString;true;lowercased(with:);;;Argument[-1];ReturnValue;taint",
8484
";NSString;true;uppercased(with:);;;Argument[-1];ReturnValue;taint",
8585
";NSString;true;capitalized(with:);;;Argument[-1];ReturnValue;taint",
86-
";NSString;true;components(separatedBy:);;;Argument[-1];ReturnValue;taint",
86+
";NSString;true;components(separatedBy:);;;Argument[-1];ReturnValue.CollectionElement;taint",
8787
";NSString;true;trimmingCharacters(in:);;;Argument[-1];ReturnValue;taint",
8888
";NSString;true;substring(from:);;;Argument[-1];ReturnValue;taint",
8989
";NSString;true;substring(with:);;;Argument[-1];ReturnValue;taint",
@@ -102,14 +102,15 @@ private class NsStringSummaries extends SummaryModelCsv {
102102
";NSString;true;stringEncoding(for:encodingOptions:convertedString:usedLossyCompression:);;;Argument[0];Argument[2];taint",
103103
";NSString;true;data(using:);;;Argument[-1];ReturnValue;taint",
104104
";NSString;true;data(using:allowLossyConversion:);;;Argument[-1];ReturnValue;taint",
105-
";NSString;true;path(withComponents:);;;Argument[0];ReturnValue;taint",
105+
";NSString;true;path(withComponents:);;;Argument[0].CollectionElement;ReturnValue;taint",
106106
";NSString;true;completePath(into:caseSensitive:matchesInto:filterTypes:);;;Argument[-1];Argument[0];taint",
107107
";NSString;true;completePath(into:caseSensitive:matchesInto:filterTypes:);;;Argument[-1];Argument[2];taint",
108108
";NSString;true;getFileSystemRepresentation(_:maxLength:);;;Argument[-1];Argument[0];taint",
109109
";NSString;true;appendingPathComponent(_:);;;Argument[-1..0];ReturnValue;taint",
110110
";NSString;true;appendingPathComponent(_:conformingTo:);;;Argument[-1..0];ReturnValue;taint",
111111
";NSString;true;appendingPathExtension(_:);;;Argument[-1..0];ReturnValue;taint",
112-
";NSString;true;strings(byAppendingPaths:);;;Argument[-1..0];ReturnValue;taint",
112+
";NSString;true;strings(byAppendingPaths:);;;Argument[-1];ReturnValue;taint",
113+
";NSString;true;strings(byAppendingPaths:);;;Argument[0].CollectionElement;ReturnValue;taint",
113114
";NSString;true;addingPercentEncoding(withAllowedCharacters:);;;Argument[-1];ReturnValue;taint",
114115
";NSString;true;string(withCString:);;;Argument[0];ReturnValue;taint",
115116
";NSString;true;string(withCString:length:);;;Argument[0];ReturnValue;taint",
@@ -118,6 +119,10 @@ private class NsStringSummaries extends SummaryModelCsv {
118119
";NSString;true;addingPercentEscapes(using:);;;Argument[-1];ReturnValue;taint",
119120
";NSString;true;replacingPercentEscapes(using:);;;Argument[-1];ReturnValue;taint",
120121
";NSString;true;applyTransform(_:reverse:range:updatedRange:);;;Argument[-1];ReturnValue;taint",
122+
";NSString;true;enumerateLines(_:);;;Argument[-1];Argument[0].Parameter[0];taint",
123+
";NSString;true;enumerateSubstrings(in:options:using:);;;Argument[-1];Argument[2].Parameter[0].OptionalSome;taint",
124+
";NSString;true;enumerateSubstrings(in:options:using:);;;Argument[2].Parameter[0].OptionalSome;Argument[-1];taint",
125+
";NSString;true;enumerateLinguisticTags(in:scheme:options:orthography:using:);;;Argument[-1];Argument[4].Parameter[0].OptionalSome;taint",
121126
";NSMutableString;true;append(_:);;;Argument[0];Argument[-1];taint",
122127
";NSMutableString;true;insert(_:at:);;;Argument[0];Argument[-1];taint",
123128
";NSMutableString;true;replaceCharacters(in:with:);;;Argument[1];Argument[-1];taint",

swift/ql/test/library-tests/dataflow/taint/libraries/nsstring.swift

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ protocol NSMutableCopying {
2525

2626
class NSString : NSObject, NSCopying, NSMutableCopying {
2727
struct EncodingConversionOptions : OptionSet { let rawValue: Int }
28-
2928
struct CompareOptions : OptionSet { let rawValue: Int }
29+
struct EnumerationOptions : OptionSet { let rawValue: Int }
3030

3131
init(characters: UnsafePointer<unichar>, length: Int) {}
3232
init(charactersNoCopy characters: UnsafeMutablePointer<unichar>, length: Int, freeWhenDone freeBuffer: Bool) {}
@@ -83,6 +83,7 @@ class NSString : NSObject, NSCopying, NSMutableCopying {
8383
func folding(options: NSString.CompareOptions = [], locale: Locale?) -> String { return "" }
8484
func applyingTransform(_ transform: StringTransform, reverse: Bool) -> String? { return "" }
8585
func enumerateLines(_ block: @escaping (String, UnsafeMutablePointer<ObjCBool>) -> Void) { }
86+
func enumerateSubstrings(in range: NSRange, options opts: NSString.EnumerationOptions = [], using block: @escaping (String?, NSRange, NSRange, UnsafeMutablePointer<ObjCBool>) -> Void) { }
8687
func replacingOccurrences(of target: String, with replacement: String) -> String { return "" }
8788
func replacingOccurrences(of target: String, with replacement: String, options: NSString.CompareOptions = [], range searchRange: NSRange) -> String { return "" }
8889
func propertyList() -> Any { return 0 }
@@ -136,8 +137,7 @@ class NSMutableString : NSString {
136137
func setString(_ aString: String) {}
137138
}
138139

139-
class NSArray : NSObject {
140-
}
140+
class NSArray : NSObject { }
141141

142142
struct _NSRange {
143143
init(location: Int, length: Int) {}
@@ -275,8 +275,8 @@ func taintThroughInterpolatedStrings() {
275275
sink(arg: sourceNSString().replacingOccurrences(of: "a", with: "b", range: NSRange(location: 0, length: 10))) // $ tainted=275
276276
sink(arg: harmless.replacingOccurrences(of: "a", with: sourceString(), range: NSRange(location: 0, length: 10))) // $ tainted=276
277277
sink(arg: NSString.path(withComponents: ["a", "b", "c"]))
278-
sink(arg: NSString.path(withComponents: sourceStringArray())) // $ tainted=278
279-
sink(arg: NSString.path(withComponents: ["a", sourceString(), "c"])) // $ MISSING: tainted=
278+
sink(arg: NSString.path(withComponents: sourceStringArray())) // $ MISSING: tainted=278
279+
sink(arg: NSString.path(withComponents: ["a", sourceString(), "c"])) // $ tainted=279
280280
sink(arg: NSString.string(withCString: sourceCString())) // $ tainted=280
281281
sink(arg: NSString.string(withCString: sourceCString(), length: 128)) // $ tainted=281
282282
sink(arg: NSString.string(withContentsOfFile: sourceString())) // $ tainted=282
@@ -306,8 +306,8 @@ func taintThroughInterpolatedStrings() {
306306

307307
sink(arg: harmless.strings(byAppendingPaths: [""]))
308308
sink(arg: harmless.strings(byAppendingPaths: [""])[0])
309-
sink(arg: harmless.strings(byAppendingPaths: [sourceString()])) // $ MISSING: tainted=
310-
sink(arg: harmless.strings(byAppendingPaths: [sourceString()])[0]) // $ MISSING: tainted=
309+
sink(arg: harmless.strings(byAppendingPaths: [sourceString()])) // $ tainted=309
310+
sink(arg: harmless.strings(byAppendingPaths: [sourceString()])[0]) // $ tainted=310
311311
sink(arg: sourceNSString().strings(byAppendingPaths: [""])) // $ tainted=311
312312
sink(arg: sourceNSString().strings(byAppendingPaths: [""])[0]) // $ tainted=312
313313

@@ -355,7 +355,7 @@ func taintThroughInterpolatedStrings() {
355355
}))
356356
sink(arg: sourceNSString().enumerateLines({
357357
line, stop in
358-
sink(arg: line) // $ MISSING: tainted=
358+
sink(arg: line) // $ tainted=356
359359
sink(arg: stop)
360360
}))
361361

@@ -485,3 +485,13 @@ func taintThroughData() {
485485
let str2 = NSString(data: data1, encoding: 0)!
486486
sink(arg: str2) // $ tainted=482
487487
}
488+
489+
func moreTests() {
490+
let myTainted = sourceNSString()
491+
let myRange = NSRange(location:0, length: 128)
492+
493+
sink(arg: myTainted.enumerateSubstrings(in: myRange, options: [], using: {
494+
substring, substringRange, enclosingRange, stop in
495+
sink(arg: substring!) // $ tainted=490
496+
}))
497+
}

0 commit comments

Comments
 (0)