Skip to content

Commit 99caafb

Browse files
committed
Swift: Model NSString.
1 parent d763c5a commit 99caafb

File tree

6 files changed

+1221
-103
lines changed

6 files changed

+1221
-103
lines changed

swift/ql/lib/codeql/swift/dataflow/ExternalFlow.qll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ private module Frameworks {
8484
private import codeql.swift.frameworks.StandardLibrary.FilePath
8585
private import codeql.swift.frameworks.StandardLibrary.InputStream
8686
private import codeql.swift.frameworks.StandardLibrary.NsData
87+
private import codeql.swift.frameworks.StandardLibrary.NsString
8788
private import codeql.swift.frameworks.StandardLibrary.NsUrl
8889
private import codeql.swift.frameworks.StandardLibrary.Sequence
8990
private import codeql.swift.frameworks.StandardLibrary.String
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
/**
2+
* Provides models for `NSString` and related Swift classes.
3+
*/
4+
5+
import swift
6+
private import codeql.swift.dataflow.DataFlow
7+
private import codeql.swift.dataflow.ExternalFlow
8+
private import codeql.swift.dataflow.FlowSteps
9+
10+
/**
11+
* A model for `NSString` members that are sources of remote flow.
12+
*/
13+
private class NsStringSource extends SourceModelCsv {
14+
override predicate row(string row) {
15+
row =
16+
[
17+
// NSString(contentsOf:) is a remote flow source
18+
";NSString;true;init(contentsOf:);;;ReturnValue;remote",
19+
";NSString;true;init(contentsOf:encoding:);;;ReturnValue;remote",
20+
";NSString;true;init(contentsOf:usedEncoding:);;;ReturnValue;remote",
21+
";NSString;true;string(withContentsOf:);;;ReturnValue;remote",
22+
// NSString(contentsOfFile:) is a local flow source
23+
";NSString;true;init(contentsOfFile:);;;ReturnValue;local",
24+
";NSString;true;init(contentsOfFile:encoding:);;;ReturnValue;local",
25+
";NSString;true;init(contentsOfFile:usedEncoding:);;;ReturnValue;local",
26+
";NSString;true;string(withContentsOfFile:);;;ReturnValue;local"
27+
]
28+
}
29+
}
30+
31+
/**
32+
* A model for `NSString` and `NSMtableString` members that permit taint flow.
33+
*/
34+
private class NsStringSummaries extends SummaryModelCsv {
35+
override predicate row(string row) {
36+
row = [
37+
";NSString;true;init(bytes:length:encoding:);;;Argument[0];ReturnValue;taint",
38+
";NSString;true;init(bytesNoCopy:length:encoding:freeWhenDone:);;;Argument[0];ReturnValue;taint",
39+
";NSString;true;init(bytesNoCopy:length:encoding:deallocator:);;;Argument[0];ReturnValue;taint",
40+
";NSString;true;init(characters:length:);;;Argument[0];ReturnValue;taint",
41+
";NSString;true;init(charactersNoCopy:length:freeWhenDone:);;;Argument[0];ReturnValue;taint",
42+
";NSString;true;init(charactersNoCopy:length:dellocator:);;;Argument[0];ReturnValue;taint",
43+
";NSString;true;init(string:);;;Argument[0];ReturnValue;taint",
44+
";NSString;true;init(cString:);;;Argument[0];ReturnValue;taint",
45+
";NSString;true;init(cString:encoding:);;;Argument[0];ReturnValue;taint",
46+
";NSString;true;init(cString:length:);;;Argument[0];ReturnValue;taint",
47+
";NSString;true;init(cStringNoCopy:length:freeWhenDone:);;;Argument[0];ReturnValue;taint",
48+
";NSString;true;init(utf8String:);;;Argument[0];ReturnValue;taint",
49+
";NSString;true;init(format:arguments:);;;Argument[0..1];ReturnValue;taint",
50+
";NSString;true;init(format:locale:arguments:);;;Argument[0];ReturnValue;taint",
51+
";NSString;true;init(format:locale:arguments:);;;Argument[2];ReturnValue;taint",
52+
";NSString;true;init(format:_:);;;Argument[0];ReturnValue;taint", //0..
53+
";NSString;true;init(format:locale:_:);;;Argument[0];ReturnValue;taint", //0,2..
54+
";NSString;true;init(data:encoding:);;;Argument[0];ReturnValue;taint",
55+
";NSString;true;init(contentsOfFile:);;;Argument[0];ReturnValue;taint",
56+
";NSString;true;init(contentsOfFile:encoding:);;;Argument[0];ReturnValue;taint",
57+
";NSString;true;init(contentsOfFile:usedEncoding:);;;Argument[0];ReturnValue;taint",
58+
";NSString;true;init(contentsOf:);;;Argument[0];ReturnValue;taint",
59+
";NSString;true;init(contentsOf:encoding:);;;Argument[0];ReturnValue;taint",
60+
";NSString;true;init(contentsOf:usedEncoding:);;;Argument[0];ReturnValue;taint",
61+
";NSString;true;init(coder:);;;Argument[0];ReturnValue;taint",
62+
";NSString;true;localizedStringWithFormat(_:_:);;;Argument[0];ReturnValue;taint", //0..
63+
";NSString;true;character(at:);;;Argument[-1];ReturnValue;taint",
64+
";NSString;true;getCharacters(_:);;;Argument[-1];Argument[0];taint",
65+
";NSString;true;getCharacters(_:range:);;;Argument[-1];Argument[0];taint",
66+
";NSString;true;getBytes(_:maxLength:usedLength:encoding:options:range:remaining:);;;Argument[-1];Argument[0];taint",
67+
";NSString;true;cString(using:);;;Argument[-1];ReturnValue;taint",
68+
";NSString;true;cString();;;Argument[-1];ReturnValue;taint",
69+
";NSString;true;lossyCString();;;Argument[-1];ReturnValue;taint",
70+
";NSString;true;getCString(_:);;;Argument[-1];Argument[0];taint",
71+
";NSString;true;getCString(_:maxLength:);;;Argument[-1];Argument[0];taint",
72+
";NSString;true;getCString(_:maxLength:encoding:);;;Argument[-1];Argument[0];taint",
73+
";NSString;true;getCString(_:maxLength:range:remaining:);;;Argument[-1];Argument[0];taint",
74+
";NSString;true;appendingFormat(_:_:);;;Argument[-1..0];ReturnValue;taint", // -1..
75+
";NSString;true;appending(_:);;;Argument[-1..0];ReturnValue;taint",
76+
";NSString;true;padding(toLength:withPad:startingAt:);;;Argument[-1];ReturnValue;taint",
77+
";NSString;true;padding(toLength:withPad:startingAt:);;;Argument[1];ReturnValue;taint",
78+
";NSString;true;lowercased(with:);;;Argument[-1];ReturnValue;taint",
79+
";NSString;true;uppercased(with:);;;Argument[-1];ReturnValue;taint",
80+
";NSString;true;capitalized(with:);;;Argument[-1];ReturnValue;taint",
81+
";NSString;true;components(separatedBy:);;;Argument[-1];ReturnValue;taint",
82+
";NSString;true;trimmingCharacters(in:);;;Argument[-1];ReturnValue;taint",
83+
";NSString;true;substring(from:);;;Argument[-1];ReturnValue;taint",
84+
";NSString;true;substring(with:);;;Argument[-1];ReturnValue;taint",
85+
";NSString;true;substring(to:);;;Argument[-1];ReturnValue;taint",
86+
";NSString;true;folding(options:locale:);;;Argument[-1];ReturnValue;taint",
87+
";NSString;true;applyingTransform(_:reverse:);;;Argument[-1];ReturnValue;taint",
88+
";NSString;true;replacingOccurrences(of:with:);;;Argument[-1];ReturnValue;taint",
89+
";NSString;true;replacingOccurrences(of:with:);;;Argument[1];ReturnValue;taint",
90+
";NSString;true;replacingOccurrences(of:with:);;;Argument[-1];ReturnValue;taint",
91+
";NSString;true;replacingOccurrences(of:with:);;;Argument[1];ReturnValue;taint",
92+
";NSString;true;replacingCharacters(in:with:);;;Argument[-1];ReturnValue;taint",
93+
";NSString;true;replacingCharacters(in:with:);;;Argument[1];ReturnValue;taint",
94+
";NSString;true;propertyList();;;Argument[-1];ReturnValue;taint",
95+
";NSString;true;propertyListFromStringsFileFormat();;;Argument[-1];ReturnValue;taint",
96+
";NSString;true;variantFittingPresentationWidth(_:);;;Argument[-1];ReturnValue;taint",
97+
";NSString;true;stringEncoding(for:encodingOptions:convertedString:usedLossyCompression:);;;Argument[0];Argument[2];taint",
98+
";NSString;true;data(using:);;;Argument[-1];ReturnValue;taint",
99+
";NSString;true;data(using:allowLossyConversion:);;;Argument[-1];ReturnValue;taint",
100+
";NSString;true;path(withComponents:);;;Argument[0];ReturnValue;taint",
101+
";NSString;true;completePath(into:caseSensitive:matchesInto:filterTypes:);;;Argument[-1];Argument[0];taint",
102+
";NSString;true;completePath(into:caseSensitive:matchesInto:filterTypes:);;;Argument[-1];Argument[2];taint",
103+
";NSString;true;getFileSystemRepresentation(_:maxLength:);;;Argument[-1];Argument[0];taint",
104+
";NSString;true;appendingPathComponent(_:);;;Argument[-1..0];ReturnValue;taint",
105+
";NSString;true;appendingPathComponent(_:conformingTo:);;;Argument[-1..0];ReturnValue;taint",
106+
";NSString;true;appendingPathExtension(_:);;;Argument[-1..0];ReturnValue;taint",
107+
";NSString;true;strings(byAppendingPaths:);;;Argument[-1..0];ReturnValue;taint",
108+
";NSString;true;addingPercentEncoding(withAllowedCharacters:);;;Argument[-1];ReturnValue;taint",
109+
";NSString;true;string(withCString:);;;Argument[0];ReturnValue;taint",
110+
";NSString;true;string(withCString:length:);;;Argument[0];ReturnValue;taint",
111+
";NSString;true;string(withContentsOfFile:);;;Argument[0];ReturnValue;taint",
112+
";NSString;true;string(withContentsOf:);;;Argument[0];ReturnValue;taint",
113+
";NSString;true;addingPercentEscapes(using:);;;Argument[-1];ReturnValue;taint",
114+
";NSString;true;replacingPercentEscapes(using:);;;Argument[-1];ReturnValue;taint",
115+
";NSString;true;applyTransform(_:reverse:range:updatedRange:();;;Argument[-1];ReturnValue;taint",
116+
]
117+
}
118+
}
119+
120+
/**
121+
* A content implying that, if a `NsString` is tainted, then many of its fields are
122+
* tainted.
123+
*/
124+
private class NsStringFieldsInheritTaint extends TaintInheritingContent,
125+
DataFlow::Content::FieldContent {
126+
NsStringFieldsInheritTaint() {
127+
exists(FieldDecl f | this.getField() = f |
128+
(
129+
f.getEnclosingDecl().(NominalTypeDecl).getName() = "NSString" or
130+
f.getEnclosingDecl().(ExtensionDecl).getExtendedTypeDecl().getName() = "NSString"
131+
) and
132+
f.getName() =
133+
[
134+
"utf8String", "lowercased", "localizedLowedCase", "uppercased", "localizedUppercase",
135+
"capitalized", "localizedCapitalized", "decomposedStringWithCanonicalMapping",
136+
"decomposedStringWithCompatibilityMapping", "precomposedStringWithCanonicalMapping",
137+
"precomposedStringWithCompatibilityMapping", "doubleValue", "floatValue", "intValue",
138+
"integerValue", "longLongValue", "boolValue", "description", "pathComponents",
139+
"fileSystemRepresentation", "lastPathComponent", "pathExtension",
140+
"abbreviatingWithTildeInPath", "deletingLastPathComponent", "deletingPathExtension",
141+
"expandingTildeInPath", "resolvingSymlinksInPath", "standardizingPath",
142+
"removingPercentEncoding"
143+
]
144+
)
145+
}
146+
}

swift/ql/test/library-tests/dataflow/flowsources/FlowSources.expected

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,14 @@
8585
| generics.swift:163:9:163:22 | call to source3() | external |
8686
| nsdata.swift:18:17:18:40 | call to NSData.init(contentsOf:) | external |
8787
| nsdata.swift:19:17:19:53 | call to NSData.init(contentsOf:options:) | external |
88+
| nsstring.swift:31:21:31:50 | call to Self.init(contentsOfFile:) | external |
89+
| nsstring.swift:32:21:32:63 | call to Self.init(contentsOfFile:encoding:) | external |
90+
| nsstring.swift:33:21:33:69 | call to Self.init(contentsOfFile:usedEncoding:) | external |
91+
| nsstring.swift:34:17:34:57 | call to string(withContentsOfFile:) | external |
92+
| nsstring.swift:37:21:37:45 | call to Self.init(contentsOf:) | external |
93+
| nsstring.swift:38:21:38:58 | call to Self.init(contentsOf:encoding:) | external |
94+
| nsstring.swift:39:21:39:64 | call to Self.init(contentsOf:usedEncoding:) | external |
95+
| nsstring.swift:40:17:40:52 | call to string(withContentsOf:) | external |
8896
| string.swift:56:21:56:44 | call to String.init(contentsOf:) | external |
8997
| string.swift:57:21:57:77 | call to String.init(contentsOf:encoding:) | external |
9098
| string.swift:59:21:59:69 | call to String.init(contentsOf:usedEncoding:) | external |

0 commit comments

Comments
 (0)