@@ -79,7 +79,7 @@ extension String : CVarArg {
79
79
init ( platformString: UnsafePointer < CInterop . PlatformChar > ) { self . init ( ) }
80
80
81
81
func withPlatformString< Result> ( _ body: ( UnsafePointer < CInterop . PlatformChar > ) throws -> Result ) rethrows -> Result { return 0 as! Result }
82
-
82
+ mutating func withMutableCharacters < R > ( _ body : ( inout String ) -> R ) -> R { return 0 as! R }
83
83
84
84
85
85
mutating func replaceSubrange< C> ( _ subrange: Range < String . Index > , with newElements: C )
@@ -372,7 +372,7 @@ func taintThroughEncodings() {
372
372
} )
373
373
tainted. withUTF8 ( {
374
374
buffer in
375
- sink ( arg: buffer [ 0 ] ) // $ MISSING: tainted=366
375
+ sink ( arg: buffer [ 0 ] ) // $ tainted=366
376
376
sink ( arg: buffer. baseAddress!) // $ MISSING: tainted=366
377
377
} )
378
378
@@ -382,15 +382,15 @@ func taintThroughEncodings() {
382
382
} )
383
383
tainted. withCString ( {
384
384
ptr in
385
- sink ( arg: ptr [ 0 ] ) // $ MISSING: tainted=366
385
+ sink ( arg: ptr [ 0 ] ) // $ tainted=366
386
386
} )
387
387
clean. withCString ( encodedAs: UTF8 . self, {
388
388
ptr in
389
389
sink ( arg: ptr [ 0 ] )
390
390
} )
391
391
tainted. withCString ( encodedAs: UTF8 . self, {
392
392
ptr in
393
- sink ( arg: ptr [ 0 ] ) // $ MISSING: tainted=366
393
+ sink ( arg: ptr [ 0 ] ) // $ tainted=366
394
394
} )
395
395
396
396
let arrayString1 = clean. cString ( using: String . Encoding. utf8) !
@@ -421,8 +421,8 @@ func taintThroughEncodings() {
421
421
} )
422
422
tainted. withPlatformString ( {
423
423
ptr in
424
- sink ( arg: ptr [ 0 ] ) // $ MISSING: tainted=366
425
- sink ( arg: String ( platformString: ptr) ) // $ MISSING: tainted=366
424
+ sink ( arg: ptr [ 0 ] ) // $ tainted=366
425
+ sink ( arg: String ( platformString: ptr) ) // $ tainted=366
426
426
427
427
let buffer = UnsafeBufferPointer ( start: ptr, count: 10 )
428
428
let arrayString = Array ( buffer)
@@ -449,26 +449,38 @@ func taintFromUInt8Array() {
449
449
var cleanUInt8Values : [ UInt8 ] = [ 0x41 , 0x42 , 0x43 , 0 ] // "ABC"
450
450
var taintedUInt8Values : [ UInt8 ] = [ source4 ( ) ]
451
451
452
- sink ( arg: String ( unsafeUninitializedCapacity: 256 , initializingUTF8With: {
452
+ sink ( arg: taintedUInt8Values [ 0 ] ) // $ tainted=450
453
+ let r1 = String ( unsafeUninitializedCapacity: 256 , initializingUTF8With: {
453
454
( buffer: UnsafeMutableBufferPointer < UInt8 > ) -> Int in
454
455
sink ( arg: buffer [ 0 ] )
455
456
let _ = buffer. initialize ( from: cleanUInt8Values)
456
457
sink ( arg: buffer [ 0 ] )
457
458
return 3
458
459
}
459
- ) )
460
- sink ( arg: String ( unsafeUninitializedCapacity: 256 , initializingUTF8With: { // $ MISSING: tainted=450
460
+ )
461
+ sink ( arg: r1)
462
+ let r2 = String ( unsafeUninitializedCapacity: 256 , initializingUTF8With: {
461
463
( buffer: UnsafeMutableBufferPointer < UInt8 > ) -> Int in
462
464
sink ( arg: buffer [ 0 ] )
465
+ sink ( arg: taintedUInt8Values [ 0 ] ) // $ MISSING: tainted=450
463
466
let _ = buffer. initialize ( from: taintedUInt8Values)
464
467
sink ( arg: buffer [ 0 ] ) // $ MISSING: tainted=450
465
468
return 256
466
469
}
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) // $ tainted=475
468
481
469
482
sink ( arg: String ( bytes: cleanUInt8Values, encoding: String . Encoding. utf8) !)
470
483
sink ( arg: String ( bytes: taintedUInt8Values, encoding: String . Encoding. utf8) !) // $ tainted=450
471
-
472
484
sink ( arg: String ( cString: cleanUInt8Values) )
473
485
sink ( arg: String ( cString: taintedUInt8Values) ) // $ tainted=450
474
486
@@ -484,7 +496,6 @@ func taintFromUInt8Array() {
484
496
sink ( arg: buffer. baseAddress!) // $ MISSING: tainted=450
485
497
sink ( arg: String ( cString: buffer. baseAddress!) ) // $ MISSING: tainted=450
486
498
} )
487
-
488
499
try ! cleanUInt8Values. withUnsafeMutableBytes ( {
489
500
( buffer: UnsafeMutableRawBufferPointer ) throws in
490
501
sink ( arg: buffer [ 0 ] )
@@ -515,15 +526,15 @@ func taintThroughCCharArray() {
515
526
} )
516
527
taintedCCharValues. withUnsafeBufferPointer ( {
517
528
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
523
534
} )
524
535
525
536
sink ( arg: String ( cString: cleanCCharValues) )
526
- sink ( arg: String ( cString: taintedCCharValues) ) // $ tainted=506
537
+ sink ( arg: String ( cString: taintedCCharValues) ) // $ tainted=517
527
538
}
528
539
529
540
func source6( ) -> unichar { return 0 }
@@ -541,10 +552,10 @@ func taintThroughUnicharArray() {
541
552
} )
542
553
taintedUnicharValues. withUnsafeBufferPointer ( {
543
554
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
548
559
} )
549
560
}
550
561
@@ -553,43 +564,45 @@ func source7() -> Substring { return Substring() }
553
564
func taintThroughSubstring( ) {
554
565
let tainted = source2 ( )
555
566
556
- sink ( arg: source7 ( ) ) // $ tainted=556
567
+ sink ( arg: source7 ( ) ) // $ tainted=567
557
568
558
569
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
561
572
562
573
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
565
576
566
577
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
569
580
570
581
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
573
584
574
585
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
577
588
578
589
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
581
592
}
582
593
583
594
func taintedThroughConversion( ) {
584
595
sink ( arg: String ( 0 ) )
585
- sink ( arg: String ( source ( ) ) ) // $ tainted=585
596
+ sink ( arg: String ( source ( ) ) ) // $ tainted=596
597
+
586
598
sink ( arg: Int ( 0 ) . description)
587
- sink ( arg: source ( ) . description) // $ tainted=587
599
+ sink ( arg: source ( ) . description) // $ tainted=599
600
+
588
601
sink ( arg: String ( describing: 0 ) )
589
- sink ( arg: String ( describing: source ( ) ) ) // $ tainted=589
602
+ sink ( arg: String ( describing: source ( ) ) ) // $ tainted=602
590
603
591
604
sink ( arg: Int ( " 123 " ) !)
592
- sink ( arg: Int ( source2 ( ) ) !) // $ tainted=592
605
+ sink ( arg: Int ( source2 ( ) ) !) // $ tainted=605
593
606
}
594
607
595
608
func untaintedFields( ) {
@@ -607,7 +620,7 @@ func callbackWithCleanPointer(ptr: UnsafeBufferPointer<String.Element>) throws -
607
620
}
608
621
609
622
func callbackWithTaintedPointer( ptr: UnsafeBufferPointer < String . Element > ) throws -> Int {
610
- sink ( arg: ptr [ 0 ] ) // $ tainted=617
623
+ sink ( arg: ptr [ 0 ] ) // $ tainted=630
611
624
612
625
return source ( )
613
626
}
@@ -626,7 +639,7 @@ func furtherTaintThroughCallbacks() {
626
639
ptr in
627
640
return source ( )
628
641
} )
629
- sink ( arg: result2!) // $ tainted=627
642
+ sink ( arg: result2!) // $ tainted=640
630
643
631
644
// return values from the closure (2)
632
645
if let result3 = clean. withContiguousStorageIfAvailable ( {
@@ -639,28 +652,28 @@ func furtherTaintThroughCallbacks() {
639
652
ptr in
640
653
return source ( )
641
654
} ) {
642
- sink ( arg: result4) // $ tainted=640
655
+ sink ( arg: result4) // $ tainted=653
643
656
}
644
657
645
658
// using a non-closure function
646
659
let result5 = try ? clean. withContiguousStorageIfAvailable ( callbackWithCleanPointer)
647
660
sink ( arg: result5!)
648
661
let result6 = try ? tainted. withContiguousStorageIfAvailable ( callbackWithTaintedPointer)
649
- sink ( arg: result6!) // $ tainted=612
662
+ sink ( arg: result6!) // $ tainted=625
650
663
}
651
664
652
665
func testAppendingFormat( ) {
653
666
var s1 = source2 ( )
654
- sink ( arg: s1. appendingFormat ( " %s %i " , " " , 0 ) ) // $ tainted=653
667
+ sink ( arg: s1. appendingFormat ( " %s %i " , " " , 0 ) ) // $ tainted=666
655
668
656
669
var s2 = " "
657
- sink ( arg: s2. appendingFormat ( source2 ( ) , " " , 0 ) ) // $ tainted=657
670
+ sink ( arg: s2. appendingFormat ( source2 ( ) , " " , 0 ) ) // $ tainted=670
658
671
659
672
var s3 = " "
660
- sink ( arg: s3. appendingFormat ( " %s %i " , source2 ( ) , 0 ) ) // $ tainted=660
673
+ sink ( arg: s3. appendingFormat ( " %s %i " , source2 ( ) , 0 ) ) // $ tainted=673
661
674
662
675
var s4 = " "
663
- sink ( arg: s4. appendingFormat ( " %s %i " , " " , source ( ) ) ) // $ tainted=663
676
+ sink ( arg: s4. appendingFormat ( " %s %i " , " " , source ( ) ) ) // $ tainted=676
664
677
}
665
678
666
679
func sourceUInt8( ) -> UInt8 { return 0 }
@@ -669,22 +682,22 @@ func testDecodeCString() {
669
682
var input : [ UInt8 ] = [ 1 , 2 , 3 , sourceUInt8 ( ) ]
670
683
671
684
let ( str1, repaired1) = String . decodeCString ( input, as: UTF8 . self) !
672
- sink ( arg: str1) // $ tainted=669
685
+ sink ( arg: str1) // $ tainted=682
673
686
sink ( arg: repaired1)
674
687
675
688
input. withUnsafeBufferPointer ( {
676
689
ptr in
677
690
let ( str2, repaired2) = String . decodeCString ( ptr. baseAddress, as: UTF8 . self) !
678
- sink ( arg: str2) // $ MISSING: tainted=669
691
+ sink ( arg: str2) // $ MISSING: tainted=682
679
692
sink ( arg: repaired2)
680
693
} )
681
694
682
695
let ( str3, repaired3) = String . decodeCString ( source2 ( ) , as: UTF8 . self) !
683
- sink ( arg: str3) // $ tainted=682
696
+ sink ( arg: str3) // $ tainted=695
684
697
sink ( arg: repaired3)
685
698
686
699
let ( str4, repaired4) = String . decodeCString ( & input, as: UTF8 . self) !
687
- sink ( arg: str4) // $ tainted=669
700
+ sink ( arg: str4) // $ tainted=682
688
701
sink ( arg: repaired4)
689
702
}
690
703
@@ -693,26 +706,43 @@ func testSubstringMembers() {
693
706
let tainted = source2 ( )
694
707
695
708
let sub1 = tainted [ ..< tainted. index ( tainted. endIndex, offsetBy: - 5 ) ]
696
- sink ( arg: sub1) // $ tainted=693
697
- sink ( arg: sub1. base) // $ tainted=693
698
- sink ( arg: sub1. utf8) // $ tainted=693
699
- sink ( arg: sub1. capitalized) // $ tainted=693
700
- sink ( arg: sub1. description) // $ tainted=693
709
+ sink ( arg: sub1) // $ tainted=706
710
+ sink ( arg: sub1. base) // $ tainted=706
711
+ sink ( arg: sub1. utf8) // $ tainted=706
712
+ sink ( arg: sub1. capitalized) // $ tainted=706
713
+ sink ( arg: sub1. description) // $ tainted=706
701
714
702
715
var sub2 = tainted [ tainted. index ( tainted. startIndex, offsetBy: 5 ) ... ]
703
- sink ( arg: sub2) // $ tainted=693
716
+ sink ( arg: sub2) // $ tainted=706
704
717
let result1 = sub2. withUTF8 ( {
705
718
buffer in
706
- sink ( arg: buffer [ 0 ] ) // $ tainted=693
719
+ sink ( arg: buffer [ 0 ] ) // $ tainted=706
707
720
return source ( )
708
721
} )
709
- sink ( arg: result1) // $ tainted=707
722
+ sink ( arg: result1) // $ tainted=720
710
723
711
724
let sub3 = Substring ( sub2. utf8)
712
- sink ( arg: sub3) // $ tainted=693
725
+ sink ( arg: sub3) // $ tainted=706
713
726
714
727
var sub4 = clean. prefix ( 10 )
715
728
sink ( arg: sub4)
716
729
sub4. replaceSubrange ( ..< clean. endIndex, with: sub1)
717
- sink ( arg: sub4) // $ tainted=693
730
+ sink ( arg: sub4) // $ tainted=706
731
+ }
732
+
733
+ // ---
734
+
735
+ func taintMutableCharacters( ) {
736
+ var str = " "
737
+
738
+ sink ( arg: str)
739
+ let rtn = str. withMutableCharacters ( {
740
+ chars in
741
+ sink ( arg: chars)
742
+ chars. append ( source2 ( ) )
743
+ sink ( arg: chars) // $ tainted=742
744
+ return source ( )
745
+ } )
746
+ sink ( arg: rtn) // $ tainted=744
747
+ sink ( arg: str) // $ tainted=742
718
748
}
0 commit comments