Skip to content

Commit b93442a

Browse files
authored
Merge pull request github#14523 from geoffw0/appendingformat
Swift: Model StringProtocol.appendingformat and String.decodecstring
2 parents 53e80e0 + 0a96eb0 commit b93442a

File tree

3 files changed

+49
-2
lines changed

3 files changed

+49
-2
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
category: minorAnalysis
3+
---
4+
5+
* Added taint models for `StringProtocol.appendingFormat` and `String.decodeCString`.

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ private class StringSummaries extends SummaryModelCsv {
4040
";StringProtocol;true;addingPercentEncoding(withAllowedCharacter:);;;Argument[-1];ReturnValue;taint",
4141
";StringProtocol;true;addingPercentEscapes(using:);;;Argument[-1];ReturnValue;taint",
4242
";StringProtocol;true;appending(_:);;;Argument[-1..0];ReturnValue;taint",
43-
";StringProtocol;true;appendingFormat(_:_:);;;Argument[-1..0];ReturnValue;taint", //-1..
43+
";StringProtocol;true;appendingFormat(_:_:);;;Argument[-1..0];ReturnValue;taint",
44+
";StringProtocol;true;appendingFormat(_:_:);;;Argument[1].CollectionElement;ReturnValue;taint",
4445
";StringProtocol;true;applyingTransform(_:reverse:);;;Argument[-1];ReturnValue;taint",
4546
";StringProtocol;true;cString(using:);;;Argument[-1];ReturnValue;taint",
4647
";StringProtocol;true;capitalized(with:);;;Argument[-1];ReturnValue;taint",
@@ -123,6 +124,8 @@ private class StringSummaries extends SummaryModelCsv {
123124
";String;true;randomElement(using:);;;Argument[-1];ReturnValue;taint",
124125
";String;true;enumerated();;;Argument[-1];ReturnValue;taint",
125126
";String;true;encode(to:);;;Argument[-1];Argument[0];taint",
127+
";String;true;decodeCString(_:as:repairingInvalidCodeUnits:);;;Argument[0];ReturnValue.TupleElement[0];taint",
128+
";String;true;decodeCString(_:as:repairingInvalidCodeUnits:);;;Argument[0].CollectionElement;ReturnValue.TupleElement[0];taint",
126129
";LosslessStringConvertible;true;init(_:);;;Argument[0];ReturnValue;taint",
127130
]
128131
}

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

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ struct Locale {
2424

2525

2626

27-
2827

2928
enum CInterop {
3029
typealias Char = CChar
@@ -104,6 +103,7 @@ extension StringProtocol {
104103
func substring(from index: Self.Index) -> String { return "" }
105104
func trimmingCharacters(in set: CharacterSet) -> String { return "" }
106105
func appending<T>(_ aString: T) -> String where T : StringProtocol { return "" }
106+
func appendingFormat<T>(_ format: T, _ arguments: CVarArg...) -> String where T : StringProtocol { return "" }
107107
func padding<T>(toLength newLength: Int, withPad padString: T, startingAt padIndex: Int) -> String where T: StringProtocol { return "" }
108108
func components(separatedBy separator: CharacterSet) -> [String] { return [] }
109109
func folding(options: String.CompareOptions = [], locale: Locale?) -> String { return "" }
@@ -648,3 +648,42 @@ func furtherTaintThroughCallbacks() {
648648
let result6 = try? tainted.withContiguousStorageIfAvailable(callbackWithTaintedPointer)
649649
sink(arg: result6!) // $ tainted=612
650650
}
651+
652+
func testAppendingFormat() {
653+
var s1 = source2()
654+
sink(arg: s1.appendingFormat("%s %i", "", 0)) // $ tainted=653
655+
656+
var s2 = ""
657+
sink(arg: s2.appendingFormat(source2(), "", 0)) // $ tainted=657
658+
659+
var s3 = ""
660+
sink(arg: s3.appendingFormat("%s %i", source2(), 0)) // $ tainted=660
661+
662+
var s4 = ""
663+
sink(arg: s4.appendingFormat("%s %i", "", source())) // $ tainted=663
664+
}
665+
666+
func sourceUInt8() -> UInt8 { return 0 }
667+
668+
func testDecodeCString() {
669+
var input : [UInt8] = [1, 2, 3, sourceUInt8()]
670+
671+
let (str1, repaired1) = String.decodeCString(input, as: UTF8.self)!
672+
sink(arg: str1) // $ tainted=669
673+
sink(arg: repaired1)
674+
675+
input.withUnsafeBufferPointer({
676+
ptr in
677+
let (str2, repaired2) = String.decodeCString(ptr.baseAddress, as: UTF8.self)!
678+
sink(arg: str2) // $ MISSING: tainted=669
679+
sink(arg: repaired2)
680+
})
681+
682+
let (str3, repaired3) = String.decodeCString(source2(), as: UTF8.self)!
683+
sink(arg: str3) // $ tainted=682
684+
sink(arg: repaired3)
685+
686+
let (str4, repaired4) = String.decodeCString(&input, as: UTF8.self)!
687+
sink(arg: str4) // $ tainted=669
688+
sink(arg: repaired4)
689+
}

0 commit comments

Comments
 (0)