Skip to content

Commit 2284127

Browse files
committed
Add MaD rows for the Data class
1 parent cac6e94 commit 2284127

File tree

3 files changed

+290
-17
lines changed

3 files changed

+290
-17
lines changed
Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,47 @@
11
import swift
22
private import codeql.swift.dataflow.ExternalFlow
33

4+
private class DataSources extends SourceModelCsv {
5+
override predicate row(string row) {
6+
row = ";Data;true;init(contentsOf:options:);;;ReturnValue;remote"
7+
}
8+
}
9+
410
private class DataSummaries extends SummaryModelCsv {
5-
override predicate row(string row) { row = ";Data;true;init(_:);;;Argument[0];ReturnValue;taint" }
11+
override predicate row(string row) {
12+
row =
13+
[
14+
";Data;true;init(_:);;;Argument[0];ReturnValue;taint",
15+
";Data;true;init(base64Encoded:options:);;;Argument[0];ReturnValue;taint",
16+
";Data;true;init(buffer:);;;Argument[0];ReturnValue;taint",
17+
";Data;true;init(bytes:count:);;;Argument[0];ReturnValue;taint",
18+
";Data;true;init(contentsOf:options:);;;Argument[0];ReturnValue;taint",
19+
";Data;true;init(bytesNoCopy:count:deallocator:);;;Argument[0];ReturnValue;taint",
20+
";Data;true;init(referencing:);;;Argument[0];ReturnValue;taint",
21+
";Data;true;append(_:);;;Argument[0];Argument[-1];taint",
22+
";Data;true;append(_:count:);;;Argument[0];Argument[-1];taint",
23+
";Data;true;append(contentsOf:);;;Argument[0];Argument[-1];taint",
24+
";Data;true;base64EncodedData(options:);;;Argument[-1];ReturnValue;taint",
25+
";Data;true;base64EncodedString(options:);;;Argument[-1];ReturnValue;taint",
26+
";Data;true;compactMap(_:);;;Argument[-1];ReturnValue;taint",
27+
";Data;true;copyBytes(to:);;;Argument[-1];Argument[0];taint",
28+
";Data;true;copyBytes(to:count:);;;Argument[-1];Argument[0];taint",
29+
";Data;true;copyBytes(to:from:);;;Argument[-1];Argument[0];taint",
30+
";Data;true;flatMap(_:);;;Argument[-1];ReturnValue;taint",
31+
";Data;true;insert(_:at:);;;Argument[0];Argument[-1];taint",
32+
";Data;true;insert(contentsOf:at:);;;Argument[0];Argument[-1];taint",
33+
";Data;true;map(_:);;;Argument[-1];ReturnValue;taint",
34+
";Data;true;reduce(into:_:);;;Argument[-1];ReturnValue;taint",
35+
";Data;true;replace(_:with:maxReplacements:);;;Argument[1];Argument[-1];taint",
36+
";Data;true;replaceSubrange(_:with:);;;Argument[1];Argument[-1];taint",
37+
";Data;true;replaceSubrange(_:with:count:);;;Argument[1];Argument[-1];taint",
38+
";Data;true;replacing(_:with:maxReplacements:);;;Argument[1];Argument[-1];taint",
39+
";Data;true;replacing(_:with:subrange:maxReplacements:);;;Argument[1];Argument[-1];taint",
40+
";Data;true;shuffled();;;Argument[-1];ReturnValue;taint",
41+
";Data;true;shuffled(using:);;;Argument[-1];ReturnValue;taint",
42+
";Data;true;sorted(using:);;;Argument[-1];ReturnValue;taint",
43+
";Data;true;trimmingPrefix(_:);;;Argument[-1];ReturnValue;taint",
44+
";Data;true;trimmingPrefix(while:);;;Argument[-1];ReturnValue;taint"
45+
]
46+
}
647
}
Lines changed: 224 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,241 @@
1+
// --- stubs ---
2+
struct URL {}
13

2-
class Data
4+
class NSData {}
5+
6+
protocol SortComparator {
7+
associatedtype Compared
8+
}
9+
struct Data
310
{
11+
struct Base64EncodingOptions : OptionSet { let rawValue: Int }
12+
struct Base64DecodingOptions : OptionSet { let rawValue: Int }
13+
enum Deallocator { case none }
14+
struct ReadingOptions : OptionSet { let rawValue: Int }
15+
typealias Index = Int
416
init<S>(_ elements: S) {}
17+
init(base64Encoded: Data, options: Data.Base64DecodingOptions) {}
18+
init<SourceType>(buffer: UnsafeBufferPointer<SourceType>) {}
19+
init<SourceType>(buffer: UnsafeMutablePointer<SourceType>) {}
20+
init(bytes: UnsafeRawPointer, count: Int) {}
21+
init(bytesNoCopy: UnsafeRawPointer, count: Int, deallocator: Data.Deallocator) {}
22+
init(contentsOf: URL, options: ReadingOptions) {}
23+
init(referencing: NSData) {}
24+
func append(_: Data) {}
25+
func append(_: UInt8) {}
26+
func append<SourceType>(_: UnsafeBufferPointer<SourceType>) {}
27+
func append(_: UnsafePointer<UInt8>, count: Int) {}
28+
func append(contentsOf: [UInt8]) {}
29+
func append<S>(contentsOf: S) {}
30+
func base64EncodedData(options: Data.Base64EncodingOptions) -> Data { return Data("") }
31+
func base64EncodedString(options: Data.Base64EncodingOptions) -> String { return "" }
32+
func compactMap<ElementOfResult>(_: (UInt8) -> ElementOfResult) -> [ElementOfResult] { return [] }
33+
func copyBytes(to: UnsafeMutableRawBufferPointer) {}
34+
func copyBytes(to: UnsafeMutablePointer<UInt8>, count: Int) {}
35+
func copyBytes(to: UnsafeMutablePointer<UInt8>, from: Range<Data.Index>) {}
36+
func flatMap<SegmentOfResult>(_: (UInt8) -> SegmentOfResult) -> [SegmentOfResult.Element] where SegmentOfResult : Sequence { return [] }
37+
func flatMap<ElementOfResult>(_: (UInt8) -> ElementOfResult?) -> [ElementOfResult] { return [] }
38+
func insert(_: UInt8, at: Int) {}
39+
func insert<C>(contentsOf: C, at: Int) where C : Collection, UInt8 == C.Element {}
40+
func map<T>(_: (UInt8) -> T) -> [T] { return [] }
41+
func reduce<Result>(into initialResult: Result, _: (inout Result, UInt8) -> ()) -> Result { return initialResult }
42+
func replace<C, Replacement>(_: C, with: Replacement, maxReplacements: Int) where C : Collection, Replacement : Collection, UInt8 == C.Element, C.Element == Replacement.Element {}
43+
func replaceSubrange(_: Range<Data.Index>, with: Data) {}
44+
func replaceSubrange<ByteCollection>(_: Range<Data.Index>, with: ByteCollection) where ByteCollection : Collection, ByteCollection.Element == UInt8 {}
45+
func replaceSubrange<SourceType>(_: Range<Data.Index>, with: UnsafeBufferPointer<SourceType>) {}
46+
func replaceSubrange(_: Range<Data.Index>, with: UnsafeRawPointer, count: Int) {}
47+
func replaceSubrange<C, R>(_: R, with: C) where C : Collection, R : RangeExpression, UInt8 == C.Element, Int == R.Bound {}
48+
func replacing<C, Replacement>(_: C, with: Replacement, maxReplacements: Int = .max) -> Data where C : Collection, Replacement : Collection, UInt8 == C.Element, C.Element == Replacement.Element { return Data("") }
49+
func replacing<C, Replacement>(_: C, with: Replacement, subrange: Range<Int>, maxReplacements: Int = .max) -> Data where C : Collection, Replacement : Collection, UInt8 == C.Element, C.Element == Replacement.Element { return Data("") }
50+
func shuffled() -> [UInt8] { return [] }
51+
func shuffled<T>(using: inout T) -> [UInt8] { return [] }
52+
func sorted<Comparator>(using: Comparator) -> [UInt8] where Comparator : SortComparator, UInt8 == Comparator.Compared { return [] }
53+
func trimmingPrefix<Prefix>(_ prefix: Prefix) -> Data where Prefix : Sequence, UInt8 == Prefix.Element { return Data("") }
54+
func trimmingPrefix(while: (UInt8) -> Bool) -> Data { return Data("") }
555
}
656

7-
extension String {
8-
struct Encoding {
9-
static let utf8 = Encoding()
10-
}
57+
// --- tests ---
1158

12-
init?(data: Data, encoding: Encoding) { self.init() }
59+
class UInt8SortCompartor : SortComparator {
60+
typealias Compared = UInt8
1361
}
1462

15-
func source() -> String { return "" }
16-
func sink(arg: Data) {}
17-
func sink2(arg: String) {}
63+
func source() -> Any { return "" }
64+
func sink(arg: Any) {}
65+
func rng() -> RandomNumberGenerator? { return nil }
66+
func cmp() -> UInt8SortCompartor? { return nil }
1867

1968
func taintThroughData() {
69+
// ";Data;true;init(_:);;;Argument[0];ReturnValue;taint",
2070
let dataClean = Data("123456".utf8)
21-
let dataTainted = Data(source().utf8)
71+
let dataTainted = Data((source() as! String).utf8)
2272
let dataTainted2 = Data(dataTainted)
2373

2474
sink(arg: dataClean)
25-
sink(arg: dataTainted) // $ MISSING: tainted=13
26-
sink(arg: dataTainted2) // $ MISSING: tainted=13
75+
sink(arg: dataTainted) // $ MISSING: tainted=71
76+
sink(arg: dataTainted2) // $ MISSING: tainted=71
77+
78+
// ";Data;true;init(base64Encoded:options:);;;Argument[0];ReturnValue;taint",
79+
let dataTainted3 = Data(base64Encoded: source() as! Data, options: [])
80+
sink(arg: dataTainted3) // $ tainted=79
81+
82+
// ";Data;true;init(buffer:);;;Argument[0];ReturnValue;taint",
83+
let dataTainted4 = Data(buffer: source() as! UnsafeBufferPointer<UInt8>)
84+
sink(arg: dataTainted4) // $ tainted=83
85+
let dataTainted5 = Data(buffer: source() as! UnsafeMutablePointer<UInt8>)
86+
sink(arg: dataTainted5) // $ tainted=85
87+
88+
// ";Data;true;init(bytes:count:);;;Argument[0];ReturnValue;taint",
89+
let dataTainted6 = Data(bytes: source() as! UnsafeRawPointer, count: 0)
90+
sink(arg: dataTainted6) // $ tainted=89
91+
92+
// ";Data;true;init(bytesNoCopy:count:deallocator:);;;Argument[0];ReturnValue;taint",
93+
let dataTainted7 = Data(bytesNoCopy: source() as! UnsafeRawPointer, count: 0, deallocator: Data.Deallocator.none)
94+
sink(arg: dataTainted7) // $ tainted=93
95+
96+
// ";Data;true;init(contentsOf:options:);;;Argument[0];ReturnValue;taint",
97+
let dataTainted8 = Data(contentsOf: source() as! URL, options: [])
98+
sink(arg: dataTainted8) // $ tainted=97
99+
100+
// ";Data;true;init(referencing:);;;Argument[0];ReturnValue;taint",
101+
let dataTainted9 = Data(referencing: source() as! NSData)
102+
sink(arg: dataTainted9) // $ tainted=101
103+
104+
// ";Data;true;append(_:);;;Argument[0];Argument[-1];taint",
105+
let dataTainted10 = Data("")
106+
dataTainted10.append(source() as! Data)
107+
sink(arg: dataTainted10) // $ tainted=106
108+
109+
let dataTainted11 = Data("")
110+
dataTainted11.append(source() as! UInt8)
111+
sink(arg: dataTainted11) // $ tainted=110
112+
113+
let dataTainted12 = Data("")
114+
dataTainted12.append(source() as! UnsafeBufferPointer<UInt8>)
115+
sink(arg: dataTainted12) // $ tainted=114
116+
117+
// ";Data;true;append(_:count:);;;Argument[0];Argument[-1];taint",
118+
let dataTainted13 = Data("")
119+
dataTainted13.append(source() as! UnsafePointer<UInt8>, count: 0)
120+
sink(arg: dataTainted13) // $ tainted=119
121+
122+
// ";Data;true;append(contentsOf:);;;Argument[0];Argument[-1];taint",
123+
let dataTainted14 = Data("")
124+
dataTainted14.append(contentsOf: source() as! [UInt8])
125+
sink(arg: dataTainted14) // $ tainted=124
126+
127+
// ";Data;true;base64EncodedData(options:);;;Argument[-1];ReturnValue;taint",
128+
let dataTainted15 = source() as! Data
129+
sink(arg: dataTainted15.base64EncodedData(options: [])) // $ tainted=128
130+
131+
// ";Data;true;base64EncodedString(options:);;;Argument[-1];ReturnValue;taint",
132+
let dataTainted16 = source() as! Data
133+
sink(arg: dataTainted16.base64EncodedString(options: [])) // $ tainted=132
134+
135+
// ";Data;true;compactMap(_:);;;Argument[-1];ReturnValue;taint",
136+
let dataTainted17 = source() as! Data
137+
let compactMapped: [Int] = dataTainted17.compactMap { str in Int(str) }
138+
sink(arg: compactMapped) // $ tainted=136
139+
140+
// ";Data;true;copyBytes(to:);;;Argument[-1];Argument[0];taint",
141+
let dataTainted18 = source() as! Data
142+
let pointerTainted18 = UnsafeMutableRawBufferPointer.allocate(byteCount: 0, alignment: 0)
143+
dataTainted18.copyBytes(to: pointerTainted18)
144+
sink(arg: pointerTainted18) // $ tainted=141
145+
146+
// ";Data;true;copyBytes(to:count:);;;Argument[-1];Argument[0];taint",
147+
let dataTainted19 = source() as! Data
148+
let pointerTainted19 = UnsafeMutablePointer<UInt8>.allocate(capacity: 0)
149+
dataTainted19.copyBytes(to: pointerTainted19, count: 0)
150+
sink(arg: pointerTainted19) // $ MISSING: tainted=147
151+
152+
// ";Data;true;copyBytes(to:from:);;;Argument[-1];Argument[0];taint",
153+
let dataTainted20 = source() as! Data
154+
let pointerTainted20 = UnsafeMutablePointer<UInt8>.allocate(capacity: 0)
155+
dataTainted20.copyBytes(to: pointerTainted20, from: 0..<1)
156+
sink(arg: pointerTainted20) // $ MISSING: tainted=153
157+
158+
// ";Data;true;flatMap(_:);;;Argument[-1];ReturnValue;taint",
159+
let dataTainted21 = source() as! Data
160+
let flatMapped = dataTainted21.flatMap { Array(repeating: $0, count: 0) }
161+
sink(arg: flatMapped) // $ tainted=159
162+
163+
let dataTainted22 = source() as! Data
164+
let flatMapped2 = dataTainted22.flatMap { str in Int(str) }
165+
sink(arg: flatMapped2) // $ tainted=163
166+
167+
// ";Data;true;insert(_:at:);;;Argument[0];Argument[-1];taint",
168+
let dataTainted23 = Data("")
169+
dataTainted23.insert(source() as! UInt8, at: 0)
170+
sink(arg: dataTainted23) // $ tainted=169
171+
172+
// ";Data;true;insert(contentsOf:at:);;;Argument[0];Argument[-1];taint",
173+
let dataTainted24 = Data("")
174+
dataTainted24.insert(contentsOf: source() as! [UInt8], at: 0)
175+
sink(arg: dataTainted24) // $ tainted=174
176+
177+
// ";Data;true;map(_:);;;Argument[-1];ReturnValue;taint",
178+
let dataTainted25 = source() as! Data
179+
let mapped = dataTainted25.map { $0 }
180+
sink(arg: mapped) // $ tainted=178
181+
182+
// ";Data;true;reduce(into:_:);;;Argument[-1];ReturnValue;taint",
183+
let dataTainted26 = source() as! Data
184+
let reduced = dataTainted26.reduce(into: [:]) { c, i in c[i, default: 0] += 1 }
185+
sink(arg: reduced) // $ tainted=183
186+
187+
// ";Data;true;replace(_:with:maxReplacements:);;;Argument[1];Argument[-1];taint",
188+
let dataTainted27 = Data("")
189+
dataTainted27.replace([0], with: source() as! [UInt8], maxReplacements: .max)
190+
sink(arg: dataTainted27) // $ tainted=189
191+
192+
// ";Data;true;replaceSubrange(_:with:);;;Argument[1];Argument[-1];taint",
193+
let dataTainted28 = Data("")
194+
dataTainted28.replaceSubrange(1..<3, with: source() as! Data)
195+
sink(arg: dataTainted28) // $ tainted=194
196+
197+
let dataTainted29 = Data("")
198+
dataTainted29.replaceSubrange(1..<3, with: source() as! [UInt8])
199+
sink(arg: dataTainted29) // $ tainted=198
200+
201+
let dataTainted30 = Data("")
202+
dataTainted30.replaceSubrange(1..<3, with: source() as! UnsafeBufferPointer<UInt8>)
203+
sink(arg: dataTainted30) // $ tainted=202
204+
205+
// ";Data;true;replaceSubrange(_:with:count:);;;Argument[1];Argument[-1];taint",
206+
let dataTainted31 = Data("")
207+
dataTainted31.replaceSubrange(1..<3, with: source() as! UnsafeRawPointer, count: 0)
208+
sink(arg: dataTainted31) // $ tainted=207
209+
210+
// ";Data;true;replacing(_:with:maxReplacements:);;;Argument[1];Argument[-1];taint",
211+
let dataTainted32 = Data("")
212+
dataTainted32.replacing([0], with: source() as! [UInt8], maxReplacements: 0)
213+
sink(arg: dataTainted32) // $ tainted=212
214+
215+
// ";Data;true;replacing(_:with:subrange:maxReplacements:);;;Argument[1];Argument[-1];taint",
216+
let dataTainted33 = Data("")
217+
dataTainted33.replacing([0], with: source() as! [UInt8], subrange: 1..<3, maxReplacements: 0)
218+
sink(arg: dataTainted33) // $ tainted=217
219+
220+
// ";Data;true;shuffled();;;Argument[-1];ReturnValue;taint",
221+
let dataTainted34 = source() as! Data
222+
sink(arg: dataTainted34.shuffled()) // $ tainted=221
223+
224+
// ";Data;true;shuffled(using:);;;Argument[-1];ReturnValue;taint",
225+
let dataTainted35 = source() as! Data
226+
var rng = rng()!
227+
sink(arg: dataTainted35.shuffled(using: &rng)) // $ tainted=225
228+
229+
// ";Data;true;sorted(using:);;;Argument[-1];ReturnValue;taint",
230+
let dataTainted36 = source() as! Data
231+
sink(arg: dataTainted36.sorted(using: cmp()!)) // $ tainted=230
232+
233+
// ";Data;true;trimmingPrefix(_:);;;Argument[-1];ReturnValue;taint",
234+
let dataTainted37 = source() as! Data
235+
sink(arg: dataTainted37.trimmingPrefix([0])) // $ tainted=234
27236

28-
let stringClean = String(data: dataClean, encoding: String.Encoding.utf8)
29-
let stringTainted = String(data: dataTainted, encoding: String.Encoding.utf8)
237+
// ";Data;true;trimmingPrefix(while:);;;Argument[-1];ReturnValue;taint"
238+
let dataTainted38 = source() as! Data
239+
sink(arg: dataTainted38.trimmingPrefix { _ in false }) // $ tainted=238
30240

31-
sink2(arg: stringClean!) // $ MISSING: tainted=13
32-
sink2(arg: stringTainted!) // $ MISSING: tainted=13
33241
}

swift/ql/test/library-tests/dataflow/taint/string.swift

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,3 +87,27 @@ func taintThroughStringOperations() {
8787
sink(arg: clean.debugDescription)
8888
sink(arg: tainted.debugDescription) // $ MISSING: tainted=74
8989
}
90+
91+
class Data
92+
{
93+
init<S>(_ elements: S) {}
94+
}
95+
96+
extension String {
97+
struct Encoding {
98+
static let utf8 = Encoding()
99+
}
100+
101+
init?(data: Data, encoding: Encoding) { self.init() }
102+
}
103+
104+
105+
func source3() -> Data { return Data("") }
106+
107+
func taintThroughData() {
108+
let stringClean = String(data: Data(""), encoding: String.Encoding.utf8)
109+
let stringTainted = String(data: source3(), encoding: String.Encoding.utf8)
110+
111+
sink(arg: stringClean!)
112+
sink(arg: stringTainted!) // $ MISSING: tainted=100
113+
}

0 commit comments

Comments
 (0)