Skip to content

Commit 142ca0c

Browse files
committed
Swift: Model StringProtocol initializers.
1 parent d888510 commit 142ca0c

File tree

4 files changed

+63
-3
lines changed

4 files changed

+63
-3
lines changed

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

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ private import codeql.swift.dataflow.DataFlow
33
private import codeql.swift.dataflow.ExternalFlow
44
private import codeql.swift.dataflow.FlowSteps
55

6+
/**
7+
* A model for `String` members that are sources of remote flow.
8+
*/
69
private class StringSource extends SourceModelCsv {
710
override predicate row(string row) {
811
row =
@@ -19,6 +22,20 @@ private class StringSource extends SourceModelCsv {
1922
}
2023
}
2124

25+
/**
26+
* A model for `String` and `StringProtocol` members that permit taint flow.
27+
*/
28+
private class StringSummaries extends SummaryModelCsv {
29+
override predicate row(string row) {
30+
row =
31+
[
32+
";StringProtocol;true;init(cString:);;;Argument[0];ReturnValue;taint",
33+
";StringProtocol;true;init(decoding:as:);;;Argument[0];ReturnValue;taint",
34+
";StringProtocol;true;init(decodingCString:as:);;;Argument[0];ReturnValue;taint",
35+
]
36+
}
37+
}
38+
2239
/**
2340
* A content implying that, if a `String` is tainted, then all its fields are
2441
* tainted. This also includes fields declared in `StringProtocol`.

swift/ql/test/library-tests/dataflow/taint/LocalTaint.expected

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1373,7 +1373,9 @@
13731373
| string.swift:341:23:341:77 | call to String.init(data:encoding:) | string.swift:341:7:341:7 | SSA def(stringTainted) |
13741374
| string.swift:343:12:343:12 | stringClean | string.swift:343:12:343:23 | ...! |
13751375
| string.swift:344:12:344:12 | stringTainted | string.swift:344:12:344:25 | ...! |
1376+
| string.swift:346:30:346:37 | call to Data.init(_:) | string.swift:346:13:346:53 | call to String.init(decoding:as:) |
13761377
| string.swift:346:35:346:35 | | string.swift:346:30:346:37 | call to Data.init(_:) |
1378+
| string.swift:347:30:347:38 | call to source3() | string.swift:347:13:347:54 | call to String.init(decoding:as:) |
13771379
| string.swift:351:7:351:7 | SSA def(clean) | string.swift:354:3:354:3 | clean |
13781380
| string.swift:351:15:351:15 | | string.swift:351:7:351:7 | SSA def(clean) |
13791381
| string.swift:352:7:352:7 | SSA def(tainted) | string.swift:359:3:359:3 | tainted |
@@ -1420,6 +1422,7 @@
14201422
| string.swift:385:5:385:5 | buffer | string.swift:385:5:385:5 | SSA def(buffer) |
14211423
| string.swift:386:15:386:15 | buffer | string.swift:387:31:387:31 | buffer |
14221424
| string.swift:387:31:387:38 | .baseAddress | string.swift:387:31:387:49 | ...! |
1425+
| string.swift:387:31:387:49 | ...! | string.swift:387:15:387:50 | call to String.init(cString:) |
14231426
| string.swift:389:7:389:7 | SSA def(arrayString2) | string.swift:390:13:390:13 | arrayString2 |
14241427
| string.swift:389:22:389:22 | [post] tainted | string.swift:408:3:408:3 | tainted |
14251428
| string.swift:389:22:389:22 | tainted | string.swift:408:3:408:3 | tainted |
@@ -1429,6 +1432,7 @@
14291432
| string.swift:392:5:392:5 | buffer | string.swift:392:5:392:5 | SSA def(buffer) |
14301433
| string.swift:393:15:393:15 | buffer | string.swift:394:31:394:31 | buffer |
14311434
| string.swift:394:31:394:38 | .baseAddress | string.swift:394:31:394:49 | ...! |
1435+
| string.swift:394:31:394:49 | ...! | string.swift:394:15:394:50 | call to String.init(cString:) |
14321436
| string.swift:397:3:397:3 | [post] clean | string.swift:420:3:420:3 | clean |
14331437
| string.swift:397:3:397:3 | clean | string.swift:420:3:420:3 | clean |
14341438
| string.swift:398:5:398:5 | SSA def(ptr) | string.swift:399:15:399:15 | ptr |
@@ -1479,7 +1483,9 @@
14791483
| string.swift:455:27:455:27 | cleanUInt8Values | string.swift:458:29:458:29 | cleanUInt8Values |
14801484
| string.swift:456:13:456:77 | call to String.init(bytes:encoding:) | string.swift:456:13:456:78 | ...! |
14811485
| string.swift:456:27:456:27 | taintedUInt8Values | string.swift:459:29:459:29 | taintedUInt8Values |
1486+
| string.swift:458:29:458:29 | cleanUInt8Values | string.swift:458:13:458:45 | call to String.init(cString:) |
14821487
| string.swift:458:29:458:29 | cleanUInt8Values | string.swift:461:8:461:8 | cleanUInt8Values |
1488+
| string.swift:459:29:459:29 | taintedUInt8Values | string.swift:459:13:459:47 | call to String.init(cString:) |
14831489
| string.swift:459:29:459:29 | taintedUInt8Values | string.swift:467:8:467:8 | taintedUInt8Values |
14841490
| string.swift:461:8:461:8 | [post] cleanUInt8Values | string.swift:474:8:474:8 | cleanUInt8Values |
14851491
| string.swift:461:8:461:8 | cleanUInt8Values | string.swift:474:8:474:8 | cleanUInt8Values |
@@ -1491,6 +1497,7 @@
14911497
| string.swift:464:15:464:15 | buffer | string.swift:465:31:465:31 | buffer |
14921498
| string.swift:464:15:464:22 | .baseAddress | string.swift:464:15:464:33 | ...! |
14931499
| string.swift:465:31:465:38 | .baseAddress | string.swift:465:31:465:49 | ...! |
1500+
| string.swift:465:31:465:49 | ...! | string.swift:465:15:465:50 | call to String.init(cString:) |
14941501
| string.swift:467:8:467:8 | [post] taintedUInt8Values | string.swift:480:8:480:8 | taintedUInt8Values |
14951502
| string.swift:467:8:467:8 | taintedUInt8Values | string.swift:480:8:480:8 | taintedUInt8Values |
14961503
| string.swift:467:8:472:4 | call to withUnsafeBufferPointer(_:) | string.swift:467:3:472:4 | try! ... |
@@ -1501,6 +1508,7 @@
15011508
| string.swift:470:15:470:15 | buffer | string.swift:471:31:471:31 | buffer |
15021509
| string.swift:470:15:470:22 | .baseAddress | string.swift:470:15:470:33 | ...! |
15031510
| string.swift:471:31:471:38 | .baseAddress | string.swift:471:31:471:49 | ...! |
1511+
| string.swift:471:31:471:49 | ...! | string.swift:471:15:471:50 | call to String.init(cString:) |
15041512
| string.swift:474:8:474:8 | cleanUInt8Values | string.swift:474:8:474:8 | &... |
15051513
| string.swift:474:8:479:4 | call to withUnsafeMutableBytes(_:) | string.swift:474:3:479:4 | try! ... |
15061514
| string.swift:475:6:475:14 | SSA def(buffer) | string.swift:476:15:476:15 | buffer |
@@ -1548,6 +1556,7 @@
15481556
| string.swift:499:38:499:38 | ptr | string.swift:500:31:500:31 | ptr |
15491557
| string.swift:499:38:499:42 | .baseAddress | string.swift:499:38:499:53 | ...! |
15501558
| string.swift:500:31:500:35 | .baseAddress | string.swift:500:31:500:46 | ...! |
1559+
| string.swift:500:31:500:46 | ...! | string.swift:500:15:500:47 | call to String.init(cString:) |
15511560
| string.swift:502:3:502:3 | [post] taintedCCharValues | string.swift:512:29:512:29 | taintedCCharValues |
15521561
| string.swift:502:3:502:3 | taintedCCharValues | string.swift:512:29:512:29 | taintedCCharValues |
15531562
| string.swift:503:5:503:5 | SSA def(ptr) | string.swift:504:15:504:15 | ptr |
@@ -1565,6 +1574,9 @@
15651574
| string.swift:507:38:507:38 | ptr | string.swift:508:31:508:31 | ptr |
15661575
| string.swift:507:38:507:42 | .baseAddress | string.swift:507:38:507:53 | ...! |
15671576
| string.swift:508:31:508:35 | .baseAddress | string.swift:508:31:508:46 | ...! |
1577+
| string.swift:508:31:508:46 | ...! | string.swift:508:15:508:47 | call to String.init(cString:) |
1578+
| string.swift:511:29:511:29 | cleanCCharValues | string.swift:511:13:511:45 | call to String.init(cString:) |
1579+
| string.swift:512:29:512:29 | taintedCCharValues | string.swift:512:13:512:47 | call to String.init(cString:) |
15681580
| string.swift:518:7:518:35 | SSA def(cleanUnicharValues) | string.swift:521:3:521:3 | cleanUnicharValues |
15691581
| string.swift:518:39:518:59 | [...] | string.swift:518:7:518:35 | SSA def(cleanUnicharValues) |
15701582
| string.swift:519:7:519:37 | SSA def(taintedUnicharValues) | string.swift:528:3:528:3 | taintedUnicharValues |

swift/ql/test/library-tests/dataflow/taint/Taint.expected

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,9 @@ edges
158158
| data.swift:261:22:261:29 | call to source() : | data.swift:262:12:262:12 | dataTainted41 : |
159159
| data.swift:262:12:262:12 | dataTainted41 : | data.swift:64:2:64:72 | [summary param] this in trimmingPrefix(while:) : |
160160
| data.swift:262:12:262:12 | dataTainted41 : | data.swift:262:12:262:54 | call to trimmingPrefix(while:) |
161+
| file://:0:0:0:0 | [summary param] 0 in String.init(cString:) : | file://:0:0:0:0 | [summary] to write: return (return) in String.init(cString:) : |
162+
| file://:0:0:0:0 | [summary param] 0 in String.init(cString:) : | file://:0:0:0:0 | [summary] to write: return (return) in String.init(cString:) : |
163+
| file://:0:0:0:0 | [summary param] 0 in String.init(decoding:as:) : | file://:0:0:0:0 | [summary] to write: return (return) in String.init(decoding:as:) : |
161164
| file://:0:0:0:0 | [summary] to write: argument 0.parameter 0 in enumerateBytes(_:) : | nsdata.swift:110:9:110:9 | bytes : |
162165
| file://:0:0:0:0 | [summary] to write: argument 1.parameter 0 in dataTask(with:completionHandler:) : | url.swift:154:61:154:61 | data : |
163166
| nsdata.swift:22:9:22:9 | self : | file://:0:0:0:0 | .bytes : |
@@ -606,6 +609,14 @@ edges
606609
| string.swift:326:14:326:22 | call to source2() : | string.swift:329:13:329:13 | str5 |
607610
| string.swift:331:14:331:22 | call to source2() : | string.swift:332:13:332:13 | str6 |
608611
| string.swift:331:14:331:22 | call to source2() : | string.swift:334:13:334:13 | str6 |
612+
| string.swift:347:30:347:38 | call to source3() : | file://:0:0:0:0 | [summary param] 0 in String.init(decoding:as:) : |
613+
| string.swift:347:30:347:38 | call to source3() : | string.swift:347:13:347:54 | call to String.init(decoding:as:) |
614+
| string.swift:436:28:436:36 | call to source4() : | string.swift:459:29:459:29 | taintedUInt8Values : |
615+
| string.swift:459:29:459:29 | taintedUInt8Values : | file://:0:0:0:0 | [summary param] 0 in String.init(cString:) : |
616+
| string.swift:459:29:459:29 | taintedUInt8Values : | string.swift:459:13:459:47 | call to String.init(cString:) |
617+
| string.swift:492:37:492:45 | call to source5() : | string.swift:512:29:512:29 | taintedCCharValues : |
618+
| string.swift:512:29:512:29 | taintedCCharValues : | file://:0:0:0:0 | [summary param] 0 in String.init(cString:) : |
619+
| string.swift:512:29:512:29 | taintedCCharValues : | string.swift:512:13:512:47 | call to String.init(cString:) |
609620
| string.swift:540:17:540:25 | call to source2() : | string.swift:545:13:545:13 | sub1 |
610621
| subscript.swift:13:15:13:22 | call to source() : | subscript.swift:13:15:13:25 | ...[...] |
611622
| subscript.swift:14:15:14:23 | call to source2() : | subscript.swift:14:15:14:26 | ...[...] |
@@ -1067,6 +1078,9 @@ nodes
10671078
| file://:0:0:0:0 | .url : | semmle.label | .url : |
10681079
| file://:0:0:0:0 | .urlContexts : | semmle.label | .urlContexts : |
10691080
| file://:0:0:0:0 | .userActivities : | semmle.label | .userActivities : |
1081+
| file://:0:0:0:0 | [summary param] 0 in String.init(cString:) : | semmle.label | [summary param] 0 in String.init(cString:) : |
1082+
| file://:0:0:0:0 | [summary param] 0 in String.init(cString:) : | semmle.label | [summary param] 0 in String.init(cString:) : |
1083+
| file://:0:0:0:0 | [summary param] 0 in String.init(decoding:as:) : | semmle.label | [summary param] 0 in String.init(decoding:as:) : |
10701084
| file://:0:0:0:0 | [summary] to write: argument 0 in copyBytes(to:) : | semmle.label | [summary] to write: argument 0 in copyBytes(to:) : |
10711085
| file://:0:0:0:0 | [summary] to write: argument 0 in getBytes(_:) : | semmle.label | [summary] to write: argument 0 in getBytes(_:) : |
10721086
| file://:0:0:0:0 | [summary] to write: argument 0 in getBytes(_:length:) : | semmle.label | [summary] to write: argument 0 in getBytes(_:length:) : |
@@ -1124,6 +1138,9 @@ nodes
11241138
| file://:0:0:0:0 | [summary] to write: return (return) in NSData.init(contentsOfFile:options:) : | semmle.label | [summary] to write: return (return) in NSData.init(contentsOfFile:options:) : |
11251139
| file://:0:0:0:0 | [summary] to write: return (return) in NSData.init(contentsOfMappedFile:) : | semmle.label | [summary] to write: return (return) in NSData.init(contentsOfMappedFile:) : |
11261140
| file://:0:0:0:0 | [summary] to write: return (return) in NSData.init(data:) : | semmle.label | [summary] to write: return (return) in NSData.init(data:) : |
1141+
| file://:0:0:0:0 | [summary] to write: return (return) in String.init(cString:) : | semmle.label | [summary] to write: return (return) in String.init(cString:) : |
1142+
| file://:0:0:0:0 | [summary] to write: return (return) in String.init(cString:) : | semmle.label | [summary] to write: return (return) in String.init(cString:) : |
1143+
| file://:0:0:0:0 | [summary] to write: return (return) in String.init(decoding:as:) : | semmle.label | [summary] to write: return (return) in String.init(decoding:as:) : |
11271144
| file://:0:0:0:0 | [summary] to write: return (return) in URL.init(string:) : | semmle.label | [summary] to write: return (return) in URL.init(string:) : |
11281145
| file://:0:0:0:0 | [summary] to write: return (return) in URL.init(string:relativeTo:) : | semmle.label | [summary] to write: return (return) in URL.init(string:relativeTo:) : |
11291146
| file://:0:0:0:0 | [summary] to write: return (return) in URL.init(string:relativeTo:) : | semmle.label | [summary] to write: return (return) in URL.init(string:relativeTo:) : |
@@ -1393,6 +1410,14 @@ nodes
13931410
| string.swift:331:14:331:22 | call to source2() : | semmle.label | call to source2() : |
13941411
| string.swift:332:13:332:13 | str6 | semmle.label | str6 |
13951412
| string.swift:334:13:334:13 | str6 | semmle.label | str6 |
1413+
| string.swift:347:13:347:54 | call to String.init(decoding:as:) | semmle.label | call to String.init(decoding:as:) |
1414+
| string.swift:347:30:347:38 | call to source3() : | semmle.label | call to source3() : |
1415+
| string.swift:436:28:436:36 | call to source4() : | semmle.label | call to source4() : |
1416+
| string.swift:459:13:459:47 | call to String.init(cString:) | semmle.label | call to String.init(cString:) |
1417+
| string.swift:459:29:459:29 | taintedUInt8Values : | semmle.label | taintedUInt8Values : |
1418+
| string.swift:492:37:492:45 | call to source5() : | semmle.label | call to source5() : |
1419+
| string.swift:512:13:512:47 | call to String.init(cString:) | semmle.label | call to String.init(cString:) |
1420+
| string.swift:512:29:512:29 | taintedCCharValues : | semmle.label | taintedCCharValues : |
13961421
| string.swift:540:17:540:25 | call to source2() : | semmle.label | call to source2() : |
13971422
| string.swift:542:13:542:21 | call to source7() | semmle.label | call to source7() |
13981423
| string.swift:545:13:545:13 | sub1 | semmle.label | sub1 |
@@ -1713,6 +1738,9 @@ subpaths
17131738
| string.swift:250:13:250:13 | tainted : | string.swift:107:8:107:8 | self : | string.swift:107:3:107:78 | self[return] : | string.swift:250:13:250:13 | [post] tainted : |
17141739
| string.swift:251:13:251:13 | tainted : | string.swift:107:8:107:8 | self : | string.swift:107:3:107:78 | self[return] : | string.swift:251:13:251:13 | [post] tainted : |
17151740
| string.swift:258:13:258:13 | tainted : | string.swift:109:8:109:8 | self : | string.swift:109:3:109:79 | self[return] : | string.swift:258:13:258:13 | [post] tainted : |
1741+
| string.swift:347:30:347:38 | call to source3() : | file://:0:0:0:0 | [summary param] 0 in String.init(decoding:as:) : | file://:0:0:0:0 | [summary] to write: return (return) in String.init(decoding:as:) : | string.swift:347:13:347:54 | call to String.init(decoding:as:) |
1742+
| string.swift:459:29:459:29 | taintedUInt8Values : | file://:0:0:0:0 | [summary param] 0 in String.init(cString:) : | file://:0:0:0:0 | [summary] to write: return (return) in String.init(cString:) : | string.swift:459:13:459:47 | call to String.init(cString:) |
1743+
| string.swift:512:29:512:29 | taintedCCharValues : | file://:0:0:0:0 | [summary param] 0 in String.init(cString:) : | file://:0:0:0:0 | [summary] to write: return (return) in String.init(cString:) : | string.swift:512:13:512:47 | call to String.init(cString:) |
17161744
| ui.swift:55:10:55:10 | tainted : | ui.swift:16:9:16:9 | self : | file://:0:0:0:0 | .url : | ui.swift:55:10:55:18 | .url |
17171745
| ui.swift:64:10:64:10 | tainted : | ui.swift:32:13:32:13 | self : | file://:0:0:0:0 | .userActivities : | ui.swift:64:10:64:18 | .userActivities |
17181746
| ui.swift:68:10:68:10 | tainted : | ui.swift:34:13:34:13 | self : | file://:0:0:0:0 | .urlContexts : | ui.swift:68:10:68:18 | .urlContexts |
@@ -1885,6 +1913,9 @@ subpaths
18851913
| string.swift:329:13:329:13 | str5 | string.swift:326:14:326:22 | call to source2() : | string.swift:329:13:329:13 | str5 | result |
18861914
| string.swift:332:13:332:13 | str6 | string.swift:331:14:331:22 | call to source2() : | string.swift:332:13:332:13 | str6 | result |
18871915
| string.swift:334:13:334:13 | str6 | string.swift:331:14:331:22 | call to source2() : | string.swift:334:13:334:13 | str6 | result |
1916+
| string.swift:347:13:347:54 | call to String.init(decoding:as:) | string.swift:347:30:347:38 | call to source3() : | string.swift:347:13:347:54 | call to String.init(decoding:as:) | result |
1917+
| string.swift:459:13:459:47 | call to String.init(cString:) | string.swift:436:28:436:36 | call to source4() : | string.swift:459:13:459:47 | call to String.init(cString:) | result |
1918+
| string.swift:512:13:512:47 | call to String.init(cString:) | string.swift:492:37:492:45 | call to source5() : | string.swift:512:13:512:47 | call to String.init(cString:) | result |
18881919
| string.swift:542:13:542:21 | call to source7() | string.swift:542:13:542:21 | call to source7() | string.swift:542:13:542:21 | call to source7() | result |
18891920
| string.swift:545:13:545:13 | sub1 | string.swift:540:17:540:25 | call to source2() : | string.swift:545:13:545:13 | sub1 | result |
18901921
| subscript.swift:13:15:13:25 | ...[...] | subscript.swift:13:15:13:22 | call to source() : | subscript.swift:13:15:13:25 | ...[...] | result |

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,7 @@ func taintThroughData() {
344344
sink(arg: stringTainted!) // $ MISSING: tainted=341
345345

346346
sink(arg: String(decoding: Data(""), as: UTF8.self))
347-
sink(arg: String(decoding: source3(), as: UTF8.self)) // $ MISSING: tainted=347
347+
sink(arg: String(decoding: source3(), as: UTF8.self)) // $ tainted=347
348348
}
349349

350350
func taintThroughEncodings() {
@@ -456,7 +456,7 @@ func taintFromUInt8Array() {
456456
sink(arg: String(bytes: taintedUInt8Values, encoding: String.Encoding.utf8)!) // $ MISSING: tainted=436
457457

458458
sink(arg: String(cString: cleanUInt8Values))
459-
sink(arg: String(cString: taintedUInt8Values)) // $ MISSING: tainted=436
459+
sink(arg: String(cString: taintedUInt8Values)) // $ tainted=436
460460

461461
try! cleanUInt8Values.withUnsafeBufferPointer({
462462
(buffer: UnsafeBufferPointer<UInt8>) throws in
@@ -509,7 +509,7 @@ func taintThroughCCharArray() {
509509
})
510510

511511
sink(arg: String(cString: cleanCCharValues))
512-
sink(arg: String(cString: taintedCCharValues)) // $ MISSING: tainted=492
512+
sink(arg: String(cString: taintedCCharValues)) // $ tainted=492
513513
}
514514

515515
func source6() -> [unichar] { return [] }

0 commit comments

Comments
 (0)