Skip to content

Commit dc59ed0

Browse files
authored
Merge pull request github#12094 from geoffw0/string2
Swift: Models for the String class
2 parents cd2fc65 + 364c173 commit dc59ed0

File tree

10 files changed

+2755
-507
lines changed

10 files changed

+2755
-507
lines changed

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,12 +78,14 @@ private import internal.FlowSummaryImplSpecific
7878
* ensuring that they are visible to the taint tracking / data flow library.
7979
*/
8080
private module Frameworks {
81+
private import codeql.swift.frameworks.StandardLibrary.Collection
8182
private import codeql.swift.frameworks.StandardLibrary.CustomUrlSchemes
8283
private import codeql.swift.frameworks.StandardLibrary.Data
8384
private import codeql.swift.frameworks.StandardLibrary.FilePath
8485
private import codeql.swift.frameworks.StandardLibrary.InputStream
8586
private import codeql.swift.frameworks.StandardLibrary.NsData
8687
private import codeql.swift.frameworks.StandardLibrary.NsUrl
88+
private import codeql.swift.frameworks.StandardLibrary.Sequence
8789
private import codeql.swift.frameworks.StandardLibrary.String
8890
private import codeql.swift.frameworks.StandardLibrary.Url
8991
private import codeql.swift.frameworks.StandardLibrary.UrlSession
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/**
2+
* Provides models for `Collection` 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 `Collection` members that permit taint flow.
12+
*/
13+
private class CollectionSummaries extends SummaryModelCsv {
14+
override predicate row(string row) {
15+
row =
16+
[
17+
";Collection;true;prefix(_:);;;Argument[-1];ReturnValue;taint",
18+
";Collection;true;prefix(through:);;;Argument[-1];ReturnValue;taint",
19+
";Collection;true;prefix(upTo:);;;Argument[-1];ReturnValue;taint",
20+
";Collection;true;prefix(while:);;;Argument[-1];ReturnValue;taint",
21+
";Collection;true;suffix(_:);;;Argument[-1];ReturnValue;taint",
22+
";Collection;true;suffix(from:);;;Argument[-1];ReturnValue;taint",
23+
";Collection;true;dropFirst(_:);;;Argument[-1];ReturnValue;taint",
24+
";Collection;true;dropLast(_:);;;Argument[-1];ReturnValue;taint",
25+
";Collection;true;split(maxSplits:omittingEmptySubsequences:whereSeparator:);;;Argument[-1];ReturnValue;taint",
26+
";Collection;true;split(separator:maxSplits:omittingEmptySubsequences:);;;Argument[-1];ReturnValue;taint",
27+
";Collection;true;removeFirst();;;Argument[-1];ReturnValue;taint",
28+
";RangeReplaceableCollection;true;remove(at:);;;Argument[-1];ReturnValue;taint",
29+
";RangeReplaceableCollection;true;removeFirst();;;Argument[-1];ReturnValue;taint",
30+
";RangeReplaceableCollection;true;removeLast();;;Argument[-1];ReturnValue;taint",
31+
";BidirectionalCollection;true;joined(separator:);;;Argument[-1..0];ReturnValue;taint",
32+
]
33+
}
34+
}

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

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,6 @@ private class DataSummaries extends SummaryModelCsv {
4141
";Data;true;replaceSubrange(_:with:count:);;;Argument[1];Argument[-1];taint",
4242
";Data;true;replacing(_:with:maxReplacements:);;;Argument[1];Argument[-1];taint",
4343
";Data;true;replacing(_:with:subrange:maxReplacements:);;;Argument[1];Argument[-1];taint",
44-
// TODO: this should be implemented by a model of BidirectionalCollection
45-
// ";Data;true;reversed();;;Argument[-1];ReturnValue;taint",
4644
";Data;true;sorted();;;Argument[-1];ReturnValue;taint",
4745
";Data;true;sorted(by:);;;Argument[-1];ReturnValue;taint",
4846
";Data;true;sorted(using:);;;Argument[-1];ReturnValue;taint",
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/**
2+
* Provides models for the `Sequence` Swift class.
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 `Sequence` members that permit taint flow.
12+
*/
13+
private class SequenceSummaries extends SummaryModelCsv {
14+
override predicate row(string row) {
15+
row =
16+
[
17+
";Sequence;true;reversed();;;Argument[-1];ReturnValue;taint",
18+
";Sequence;true;prefix(_:);;;Argument[-1];ReturnValue;taint",
19+
";Sequence;true;prefix(while:);;;Argument[-1];ReturnValue;taint",
20+
";Sequence;true;suffix(_:);;;Argument[-1];ReturnValue;taint",
21+
";Sequence;true;dropFirst(_:);;;Argument[-1];ReturnValue;taint",
22+
";Sequence;true;dropLast(_:);;;Argument[-1];ReturnValue;taint",
23+
";Sequence;true;split(maxSplits:omittingEmptySubsequences:whereSeparator:);;;Argument[-1];ReturnValue;taint",
24+
";Sequence;true;split(separator:maxSplits:omittingEmptySubsequences:);;;Argument[-1];ReturnValue;taint",
25+
";Sequence;true;joined();;;Argument[-1];ReturnValue;taint",
26+
";Sequence;true;joined(separator:);;;Argument[-1..0];ReturnValue;taint",
27+
]
28+
}
29+
}
30+
31+
/**
32+
* A content implying that, if a `Sequence` is tainted, certain fields are also
33+
* tainted.
34+
*/
35+
private class SequenceFieldsInheritTaint extends TaintInheritingContent,
36+
DataFlow::Content::FieldContent {
37+
SequenceFieldsInheritTaint() {
38+
exists(FieldDecl f | this.getField() = f |
39+
(
40+
f.getEnclosingDecl().(NominalTypeDecl).getName() = "Sequence" or
41+
f.getEnclosingDecl().(ExtensionDecl).getExtendedTypeDecl().getName() = "Sequence"
42+
) and
43+
f.getName() = "lazy"
44+
)
45+
}
46+
}

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

Lines changed: 116 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ private import codeql.swift.dataflow.DataFlow
77
private import codeql.swift.dataflow.ExternalFlow
88
private import codeql.swift.dataflow.FlowSteps
99

10+
/**
11+
* A model for `String` members that are sources of remote flow.
12+
*/
1013
private class StringSource extends SourceModelCsv {
1114
override predicate row(string row) {
1215
row =
@@ -24,13 +27,122 @@ private class StringSource extends SourceModelCsv {
2427
}
2528

2629
/**
27-
* A content implying that, if a `String` is tainted, then all its fields are tainted.
30+
* A model for `String` and `StringProtocol` members that permit taint flow.
31+
*/
32+
private class StringSummaries extends SummaryModelCsv {
33+
override predicate row(string row) {
34+
row =
35+
[
36+
";StringProtocol;true;init(cString:);;;Argument[0];ReturnValue;taint",
37+
";StringProtocol;true;init(decoding:as:);;;Argument[0];ReturnValue;taint",
38+
";StringProtocol;true;init(decodingCString:as:);;;Argument[0];ReturnValue;taint",
39+
";StringProtocol;true;addingPercentEncoding(withAllowedCharacter:);;;Argument[-1];ReturnValue;taint",
40+
";StringProtocol;true;addingPercentEscapes(using:);;;Argument[-1];ReturnValue;taint",
41+
";StringProtocol;true;appending(_:);;;Argument[-1..0];ReturnValue;taint",
42+
";StringProtocol;true;appendingFormat(_:_:);;;Argument[-1..0];ReturnValue;taint", //-1..
43+
";StringProtocol;true;applyingTransform(_:reverse:);;;Argument[-1];ReturnValue;taint",
44+
";StringProtocol;true;cString(using:);;;Argument[-1];ReturnValue;taint",
45+
";StringProtocol;true;capitalized(with:);;;Argument[-1];ReturnValue;taint",
46+
";StringProtocol;true;completePath(into:caseSensitive:matchesInto:filterTypes:);;;Argument[-1];Argument[0];taint",
47+
";StringProtocol;true;completePath(into:caseSensitive:matchesInto:filterTypes:);;;Argument[-1];Argument[2];taint",
48+
";StringProtocol;true;components(separatedBy:);;;Argument[-1];ReturnValue;taint",
49+
";StringProtocol;true;data(using:allowLossyConversion:);;;Argument[-1];ReturnValue;taint",
50+
";StringProtocol;true;folding(options:locale:);;;Argument[-1];ReturnValue;taint",
51+
";StringProtocol;true;getBytes(_:maxLength:usedLength:encoding:options:range:remaining:);;;Argument[-1];Argument[0];taint",
52+
";StringProtocol;true;getCString(_:maxLength:encoding:);;;Argument[-1];Argument[0];taint",
53+
";StringProtocol;true;lowercased();;;Argument[-1];ReturnValue;taint",
54+
";StringProtocol;true;lowercased(with:);;;Argument[-1];ReturnValue;taint",
55+
";StringProtocol;true;padding(toLength:withPad:startingAt:);;;Argument[-1];ReturnValue;taint",
56+
";StringProtocol;true;padding(toLength:withPad:startingAt:);;;Argument[1];ReturnValue;taint",
57+
";StringProtocol;true;propertyList();;;Argument[-1];ReturnValue;taint",
58+
";StringProtocol;true;propertyListFromStringsFileFormat();;;Argument[-1];ReturnValue;taint",
59+
";StringProtocol;true;replacingCharacters(in:with:);;;Argument[-1];ReturnValue;taint",
60+
";StringProtocol;true;replacingCharacters(in:with:);;;Argument[1];ReturnValue;taint",
61+
";StringProtocol;true;replacingOccurrences(of:with:options:range);;;Argument[-1];ReturnValue;taint",
62+
";StringProtocol;true;replacingOccurrences(of:with:options:range);;;Argument[1];ReturnValue;taint",
63+
";StringProtocol;true;replacingPercentEscapes(using:);;;Argument[-1];ReturnValue;taint",
64+
";StringProtocol;true;substring(from:);;;Argument[-1];ReturnValue;taint",
65+
";StringProtocol;true;substring(with:);;;Argument[-1];ReturnValue;taint",
66+
";StringProtocol;true;trimmingCharacters(in:);;;Argument[-1];ReturnValue;taint",
67+
";StringProtocol;true;uppercased();;;Argument[-1];ReturnValue;taint",
68+
";StringProtocol;true;uppercased(with:);;;Argument[-1];ReturnValue;taint",
69+
";String;true;init(decoding:);;;Argument[0];ReturnValue;taint",
70+
";String;true;init(_:);;;Argument[0];ReturnValue;taint",
71+
";String;true;init(repeating:count:);;;Argument[0];ReturnValue;taint",
72+
";String;true;init(data:encoding:);;;Argument[0];ReturnValue;taint",
73+
";String;true;init(validatingUTF8:);;;Argument[0];ReturnValue;taint",
74+
";String;true;init(utf16CodeUnits:count:);;;Argument[0];ReturnValue;taint",
75+
";String;true;init(utf16CodeUnitsNoCopy:count:freeWhenDone:);;;Argument[0];ReturnValue;taint",
76+
";String;true;init(format:_:);;;Argument[0];ReturnValue;taint", //0..
77+
";String;true;init(format:arguments:);;;Argument[0..1];ReturnValue;taint",
78+
";String;true;init(format:locale:_:);;;Argument[0];ReturnValue;taint", //0,2..
79+
";String;true;init(format:locale:arguments:);;;Argument[0];ReturnValue;taint",
80+
";String;true;init(_:radix:uppercase:);;;Argument[0];ReturnValue;taint",
81+
";String;true;init(bytes:encoding:);;;Argument[0];ReturnValue;taint",
82+
";String;true;init(bytesNoCopy:length:encoding:freeWhenDone);;;Argument[0];ReturnValue;taint",
83+
";String;true;init(describing:);;;Argument[0];ReturnValue;taint",
84+
";String;true;init(contentsOf:);;;Argument[0];ReturnValue;taint",
85+
";String;true;init(contentsOf:encoding:);;;Argument[0];ReturnValue;taint",
86+
";String;true;init(contendsOf:usedEncoding:);;;Argument[0];ReturnValue;taint",
87+
";String;true;init(contentsOfFile:);;;Argument[0];ReturnValue;taint",
88+
";String;true;init(contentsOfFile:encoding:);;;Argument[0];ReturnValue;taint",
89+
";String;true;init(contentsOfFile:usedEncoding:);;;Argument[0];ReturnValue;taint",
90+
";String;true;init(from:);;;Argument[0];ReturnValue;taint",
91+
";String;true;init(stringInterpolation:);;;Argument[0];ReturnValue;taint",
92+
";String;true;init(stringLiteral:);;;Argument[0];ReturnValue;taint",
93+
";String;true;init(unicodeScalarLiteral:);;;Argument[0];ReturnValue;taint",
94+
";String;true;init(extendedGraphemeClusterLiteral:);;;Argument[0];ReturnValue;taint",
95+
";String;true;init(cString:encoding:);;;Argument[0];ReturnValue;taint",
96+
";String;true;init(platformString:);;;Argument[0];ReturnValue;taint",
97+
";String;true;init(utf8String:);;;Argument[0];ReturnValue;taint",
98+
";String;true;init(validating:);;;Argument[0];ReturnValue;taint",
99+
";String;true;init(validatingPlatformString:);;;Argument[0];ReturnValue;taint",
100+
";String;true;localizedStringWithFormat(_:_:);;;Argument[0..1];ReturnValue;taint",
101+
";String;true;write(_:);;;Argument[0];Argument[-1];taint",
102+
";String;true;write(to:);;;Argument[-1];Argument[0];taint",
103+
";String;true;append(_:);;;Argument[0];Argument[-1];taint",
104+
";String;true;append(contentsOf:);;;Argument[0];Argument[-1];taint",
105+
";String;true;insert(_:at:);;;Argument[0];Argument[-1];taint",
106+
";String;true;insert(contentsOf:at:);;;Argument[0];Argument[-1];taint",
107+
";String;true;replaceSubrange(_:with::);;;Argument[1];Argument[-1];taint",
108+
";String;true;popLast();;;Argument[-1];ReturnValue;taint",
109+
";String;true;first(where:);;;Argument[-1];ReturnValue;taint",
110+
";String;true;last(where:);;;Argument[-1];ReturnValue;taint",
111+
";String;true;max();;;Argument[-1];ReturnValue;taint",
112+
";String;true;max(by:);;;Argument[-1];ReturnValue;taint",
113+
";String;true;min();;;Argument[-1];ReturnValue;taint",
114+
";String;true;min(by:);;;Argument[-1];ReturnValue;taint",
115+
";String;true;subscript(_:);;;Argument[-1];ReturnValue;taint",
116+
";String;true;split(maxSplits:omittingEmptySubsequences:whereSeparator:);;;Argument[-1];ReturnValue;taint",
117+
";String;true;randomElement();;;Argument[-1];ReturnValue;taint",
118+
";String;true;randomElement(using:);;;Argument[-1];ReturnValue;taint",
119+
";String;true;enumerated();;;Argument[-1];ReturnValue;taint",
120+
";String;true;encode(to:);;;Argument[-1];Argument[0];taint"
121+
]
122+
}
123+
}
124+
125+
/**
126+
* A content implying that, if a `String` is tainted, then many of its fields are
127+
* tainted. This also includes fields declared in `StringProtocol`.
28128
*/
29129
private class StringFieldsInheritTaint extends TaintInheritingContent,
30130
DataFlow::Content::FieldContent {
31131
StringFieldsInheritTaint() {
32-
this.getField().getEnclosingDecl().(ClassOrStructDecl).getFullName() = "String" or
33-
this.getField().getEnclosingDecl().(ExtensionDecl).getExtendedTypeDecl().getFullName() =
34-
"String"
132+
exists(FieldDecl f | this.getField() = f |
133+
(
134+
f.getEnclosingDecl().(NominalTypeDecl).getName() = ["String", "StringProtocol"] or
135+
f.getEnclosingDecl().(ExtensionDecl).getExtendedTypeDecl().getName() =
136+
["String", "StringProtocol"]
137+
) and
138+
f.getName() =
139+
[
140+
"first", "last", "unicodeScalars", "utf8", "utf16", "lazy", "utf8CString", "description",
141+
"debugDescription", "dataValue", "identifierValue", "capitalized", "localizedCapitalized",
142+
"localizedLowercase", "localizedUppercase", "decomposedStringWithCanonicalMapping",
143+
"decomposedStringWithCompatibilityMapping", "precomposedStringWithCanonicalMapping",
144+
"precomposedStringWithCompatibilityMapping", "removingPercentEncoding"
145+
]
146+
)
35147
}
36148
}

0 commit comments

Comments
 (0)