Skip to content

Commit a520602

Browse files
committed
Swift: Expand a test to explore why it fails (lack of pointer models and closure capture flow).
1 parent d3063e8 commit a520602

File tree

1 file changed

+61
-48
lines changed
  • swift/ql/test/library-tests/dataflow/taint/libraries

1 file changed

+61
-48
lines changed

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

Lines changed: 61 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -449,26 +449,38 @@ func taintFromUInt8Array() {
449449
var cleanUInt8Values: [UInt8] = [0x41, 0x42, 0x43, 0] // "ABC"
450450
var taintedUInt8Values: [UInt8] = [source4()]
451451

452-
sink(arg: String(unsafeUninitializedCapacity: 256, initializingUTF8With: {
452+
sink(arg: taintedUInt8Values[0]) // $ tainted=450
453+
let r1 = String(unsafeUninitializedCapacity: 256, initializingUTF8With: {
453454
(buffer: UnsafeMutableBufferPointer<UInt8>) -> Int in
454455
sink(arg: buffer[0])
455456
let _ = buffer.initialize(from: cleanUInt8Values)
456457
sink(arg: buffer[0])
457458
return 3
458459
}
459-
))
460-
sink(arg: String(unsafeUninitializedCapacity: 256, initializingUTF8With: { // $ MISSING: tainted=450
460+
)
461+
sink(arg: r1)
462+
let r2 = String(unsafeUninitializedCapacity: 256, initializingUTF8With: {
461463
(buffer: UnsafeMutableBufferPointer<UInt8>) -> Int in
462464
sink(arg: buffer[0])
465+
sink(arg: taintedUInt8Values[0]) // $ MISSING: tainted=450
463466
let _ = buffer.initialize(from: taintedUInt8Values)
464467
sink(arg: buffer[0]) // $ MISSING: tainted=450
465468
return 256
466469
}
467-
))
470+
)
471+
sink(arg: r2) // $ MISSING: tainted=450
472+
let r3 = String(unsafeUninitializedCapacity: 256, initializingUTF8With: {
473+
(buffer: UnsafeMutableBufferPointer<UInt8>) -> Int in
474+
sink(arg: buffer[0])
475+
buffer.update(repeating: source4())
476+
sink(arg: buffer[0]) // $ tainted=475
477+
return 256
478+
}
479+
)
480+
sink(arg: r3) // $ MISSING: tainted=475
468481

469482
sink(arg: String(bytes: cleanUInt8Values, encoding: String.Encoding.utf8)!)
470483
sink(arg: String(bytes: taintedUInt8Values, encoding: String.Encoding.utf8)!) // $ tainted=450
471-
472484
sink(arg: String(cString: cleanUInt8Values))
473485
sink(arg: String(cString: taintedUInt8Values)) // $ tainted=450
474486

@@ -484,7 +496,6 @@ func taintFromUInt8Array() {
484496
sink(arg: buffer.baseAddress!) // $ MISSING: tainted=450
485497
sink(arg: String(cString: buffer.baseAddress!)) // $ MISSING: tainted=450
486498
})
487-
488499
try! cleanUInt8Values.withUnsafeMutableBytes({
489500
(buffer: UnsafeMutableRawBufferPointer) throws in
490501
sink(arg: buffer[0])
@@ -515,15 +526,15 @@ func taintThroughCCharArray() {
515526
})
516527
taintedCCharValues.withUnsafeBufferPointer({
517528
ptr in
518-
sink(arg: ptr[0]) // $ tainted=506
519-
sink(arg: ptr.baseAddress!) // $ MISSING: tainted=506
520-
sink(arg: String(utf8String: ptr.baseAddress!)!) // $ MISSING: tainted=506
521-
sink(arg: String(validatingUTF8: ptr.baseAddress!)!) // $ MISSING: tainted=506
522-
sink(arg: String(cString: ptr.baseAddress!)) // $ MISSING: tainted=506
529+
sink(arg: ptr[0]) // $ tainted=517
530+
sink(arg: ptr.baseAddress!) // $ MISSING: tainted=517
531+
sink(arg: String(utf8String: ptr.baseAddress!)!) // $ MISSING: tainted=517
532+
sink(arg: String(validatingUTF8: ptr.baseAddress!)!) // $ MISSING: tainted=517
533+
sink(arg: String(cString: ptr.baseAddress!)) // $ MISSING: tainted=517
523534
})
524535

525536
sink(arg: String(cString: cleanCCharValues))
526-
sink(arg: String(cString: taintedCCharValues)) // $ tainted=506
537+
sink(arg: String(cString: taintedCCharValues)) // $ tainted=517
527538
}
528539

529540
func source6() -> unichar { return 0 }
@@ -541,10 +552,10 @@ func taintThroughUnicharArray() {
541552
})
542553
taintedUnicharValues.withUnsafeBufferPointer({
543554
ptr in
544-
sink(arg: ptr[0]) // $ tainted=533
545-
sink(arg: ptr.baseAddress!) // $ MISSING: tainted=533
546-
sink(arg: String(utf16CodeUnits: ptr.baseAddress!, count: ptr.count)) // $ MISSING: tainted=533
547-
sink(arg: String(utf16CodeUnitsNoCopy: ptr.baseAddress!, count: ptr.count, freeWhenDone: false)) // $ MISSING: tainted=533
555+
sink(arg: ptr[0]) // $ tainted=544
556+
sink(arg: ptr.baseAddress!) // $ MISSING: tainted=544
557+
sink(arg: String(utf16CodeUnits: ptr.baseAddress!, count: ptr.count)) // $ MISSING: tainted=5344
558+
sink(arg: String(utf16CodeUnitsNoCopy: ptr.baseAddress!, count: ptr.count, freeWhenDone: false)) // $ MISSING: tainted=544
548559
})
549560
}
550561

@@ -553,43 +564,45 @@ func source7() -> Substring { return Substring() }
553564
func taintThroughSubstring() {
554565
let tainted = source2()
555566

556-
sink(arg: source7()) // $ tainted=556
567+
sink(arg: source7()) // $ tainted=567
557568

558569
let sub1 = tainted[tainted.startIndex ..< tainted.endIndex]
559-
sink(arg: sub1) // $ tainted=554
560-
sink(arg: String(sub1)) // $ tainted=554
570+
sink(arg: sub1) // $ tainted=565
571+
sink(arg: String(sub1)) // $ tainted=565
561572

562573
let sub2 = tainted.prefix(10)
563-
sink(arg: sub2) // $ tainted=554
564-
sink(arg: String(sub2)) // $ tainted=554
574+
sink(arg: sub2) // $ tainted=565
575+
sink(arg: String(sub2)) // $ tainted=565
565576

566577
let sub3 = tainted.prefix(through: tainted.endIndex)
567-
sink(arg: sub3) // $ tainted=554
568-
sink(arg: String(sub3)) // $ tainted=554
578+
sink(arg: sub3) // $ tainted=565
579+
sink(arg: String(sub3)) // $ tainted=565
569580

570581
let sub4 = tainted.prefix(upTo: tainted.endIndex)
571-
sink(arg: sub4) // $ tainted=554
572-
sink(arg: String(sub4)) // $ tainted=554
582+
sink(arg: sub4) // $ tainted=565
583+
sink(arg: String(sub4)) // $ tainted=565
573584

574585
let sub5 = tainted.suffix(10)
575-
sink(arg: sub5) // $ tainted=554
576-
sink(arg: String(sub5)) // $ tainted=554
586+
sink(arg: sub5) // $ tainted=565
587+
sink(arg: String(sub5)) // $ tainted=565
577588

578589
let sub6 = tainted.suffix(from: tainted.startIndex)
579-
sink(arg: sub6) // $ tainted=554
580-
sink(arg: String(sub6)) // $ tainted=554
590+
sink(arg: sub6) // $ tainted=565
591+
sink(arg: String(sub6)) // $ tainted=565
581592
}
582593

583594
func taintedThroughConversion() {
584595
sink(arg: String(0))
585-
sink(arg: String(source())) // $ tainted=585
596+
sink(arg: String(source())) // $ tainted=596
597+
586598
sink(arg: Int(0).description)
587-
sink(arg: source().description) // $ tainted=587
599+
sink(arg: source().description) // $ tainted=599
600+
588601
sink(arg: String(describing: 0))
589-
sink(arg: String(describing: source())) // $ tainted=589
602+
sink(arg: String(describing: source())) // $ tainted=602
590603

591604
sink(arg: Int("123")!)
592-
sink(arg: Int(source2())!) // $ tainted=592
605+
sink(arg: Int(source2())!) // $ tainted=605
593606
}
594607

595608
func untaintedFields() {
@@ -607,7 +620,7 @@ func callbackWithCleanPointer(ptr: UnsafeBufferPointer<String.Element>) throws -
607620
}
608621

609622
func callbackWithTaintedPointer(ptr: UnsafeBufferPointer<String.Element>) throws -> Int {
610-
sink(arg: ptr[0]) // $ tainted=617
623+
sink(arg: ptr[0]) // $ tainted=630
611624

612625
return source()
613626
}
@@ -626,7 +639,7 @@ func furtherTaintThroughCallbacks() {
626639
ptr in
627640
return source()
628641
})
629-
sink(arg: result2!) // $ tainted=627
642+
sink(arg: result2!) // $ tainted=640
630643

631644
// return values from the closure (2)
632645
if let result3 = clean.withContiguousStorageIfAvailable({
@@ -639,28 +652,28 @@ func furtherTaintThroughCallbacks() {
639652
ptr in
640653
return source()
641654
}) {
642-
sink(arg: result4) // $ tainted=640
655+
sink(arg: result4) // $ tainted=653
643656
}
644657

645658
// using a non-closure function
646659
let result5 = try? clean.withContiguousStorageIfAvailable(callbackWithCleanPointer)
647660
sink(arg: result5!)
648661
let result6 = try? tainted.withContiguousStorageIfAvailable(callbackWithTaintedPointer)
649-
sink(arg: result6!) // $ tainted=612
662+
sink(arg: result6!) // $ tainted=625
650663
}
651664

652665
func testAppendingFormat() {
653666
var s1 = source2()
654-
sink(arg: s1.appendingFormat("%s %i", "", 0)) // $ tainted=653
667+
sink(arg: s1.appendingFormat("%s %i", "", 0)) // $ tainted=666
655668

656669
var s2 = ""
657-
sink(arg: s2.appendingFormat(source2(), "", 0)) // $ tainted=657
670+
sink(arg: s2.appendingFormat(source2(), "", 0)) // $ tainted=670
658671

659672
var s3 = ""
660-
sink(arg: s3.appendingFormat("%s %i", source2(), 0)) // $ tainted=660
673+
sink(arg: s3.appendingFormat("%s %i", source2(), 0)) // $ tainted=673
661674

662675
var s4 = ""
663-
sink(arg: s4.appendingFormat("%s %i", "", source())) // $ tainted=663
676+
sink(arg: s4.appendingFormat("%s %i", "", source())) // $ tainted=676
664677
}
665678

666679
func sourceUInt8() -> UInt8 { return 0 }
@@ -669,22 +682,22 @@ func testDecodeCString() {
669682
var input : [UInt8] = [1, 2, 3, sourceUInt8()]
670683

671684
let (str1, repaired1) = String.decodeCString(input, as: UTF8.self)!
672-
sink(arg: str1) // $ tainted=669
685+
sink(arg: str1) // $ tainted=682
673686
sink(arg: repaired1)
674687

675688
input.withUnsafeBufferPointer({
676689
ptr in
677690
let (str2, repaired2) = String.decodeCString(ptr.baseAddress, as: UTF8.self)!
678-
sink(arg: str2) // $ MISSING: tainted=669
691+
sink(arg: str2) // $ MISSING: tainted=682
679692
sink(arg: repaired2)
680693
})
681694

682695
let (str3, repaired3) = String.decodeCString(source2(), as: UTF8.self)!
683-
sink(arg: str3) // $ tainted=682
696+
sink(arg: str3) // $ tainted=695
684697
sink(arg: repaired3)
685698

686699
let (str4, repaired4) = String.decodeCString(&input, as: UTF8.self)!
687-
sink(arg: str4) // $ tainted=669
700+
sink(arg: str4) // $ tainted=682
688701
sink(arg: repaired4)
689702
}
690703

@@ -696,9 +709,9 @@ func taintMutableCharacters() {
696709
chars in
697710
sink(arg: chars)
698711
chars.append(source2())
699-
sink(arg: chars) // $ tainted=698
712+
sink(arg: chars) // $ tainted=711
700713
return source()
701714
})
702-
sink(arg: rtn) // $ tainted=700
703-
sink(arg: str) // $ tainted=698
715+
sink(arg: rtn) // $ tainted=713
716+
sink(arg: str) // $ tainted=711
704717
}

0 commit comments

Comments
 (0)