@@ -319,6 +319,7 @@ public final class _DataStorage {
319
319
320
320
@inline ( __always)
321
321
public func append( _ bytes: UnsafeRawPointer , length: Int ) {
322
+ precondition ( length >= 0 , " Length of appending bytes must be positive " )
322
323
switch _backing {
323
324
case . swift:
324
325
let origLength = _length
@@ -1087,6 +1088,18 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
1087
1088
_sliceRange = range
1088
1089
}
1089
1090
1091
+ @_versioned
1092
+ internal func _validateIndex( _ index: Int , message: String ? = nil ) {
1093
+ precondition ( _sliceRange. contains ( index) , message ?? " Index \( index) is out of bounds of range \( _sliceRange) " )
1094
+ }
1095
+
1096
+ @_versioned
1097
+ internal func _validateRange< R: RangeExpression > ( _ range: R ) where R. Bound == Int {
1098
+ let r = range. relative ( to: 0 ..< R . Bound. max)
1099
+ precondition ( r. lowerBound >= _sliceRange. lowerBound && r. lowerBound <= _sliceRange. upperBound, " Range \( r) is out of bounds of range \( _sliceRange) " )
1100
+ precondition ( r. upperBound >= _sliceRange. lowerBound && r. upperBound <= _sliceRange. upperBound, " Range \( r) is out of bounds of range \( _sliceRange) " )
1101
+ }
1102
+
1090
1103
// -----------------------------------
1091
1104
// MARK: - Properties and Functions
1092
1105
@@ -1099,6 +1112,7 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
1099
1112
}
1100
1113
@inline ( __always)
1101
1114
set {
1115
+ precondition ( count >= 0 , " count must be positive " )
1102
1116
if !isKnownUniquelyReferenced( & _backing) {
1103
1117
_backing = _backing. mutableCopy ( _sliceRange)
1104
1118
}
@@ -1142,14 +1156,15 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
1142
1156
/// - warning: This method does not verify that the contents at pointer have enough space to hold `count` bytes.
1143
1157
@inline ( __always)
1144
1158
public func copyBytes( to pointer: UnsafeMutablePointer < UInt8 > , count: Int ) {
1159
+ precondition ( count >= 0 , " count of bytes to copy must be positive " )
1145
1160
if count == 0 { return }
1146
- memcpy ( UnsafeMutableRawPointer ( pointer) , _backing. bytes!. advanced ( by: _sliceRange. lowerBound) , count)
1161
+ memcpy ( UnsafeMutableRawPointer ( pointer) , _backing. bytes!. advanced ( by: _sliceRange. lowerBound) , Swift . min ( count, _sliceRange . count ) )
1147
1162
}
1148
1163
1149
1164
@inline ( __always)
1150
1165
private func _copyBytesHelper( to pointer: UnsafeMutableRawPointer , from range: NSRange ) {
1151
1166
if range. length == 0 { return }
1152
- memcpy ( UnsafeMutableRawPointer ( pointer) , _backing. bytes!. advanced ( by: range. location) , range. length)
1167
+ memcpy ( UnsafeMutableRawPointer ( pointer) , _backing. bytes!. advanced ( by: range. location) , Swift . min ( range. length, _sliceRange . count ) )
1153
1168
}
1154
1169
1155
1170
/// Copy a subset of the contents of the data to a pointer.
@@ -1174,18 +1189,13 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
1174
1189
1175
1190
let copyRange : Range < Index >
1176
1191
if let r = range {
1177
- guard !r. isEmpty else { return 0 }
1178
- precondition ( r. lowerBound >= 0 )
1179
- precondition ( r. lowerBound < cnt, " The range is outside the bounds of the data " )
1180
-
1181
- precondition ( r. upperBound >= 0 )
1182
- precondition ( r. upperBound <= cnt, " The range is outside the bounds of the data " )
1183
-
1192
+ guard !r. isEmpty else { return 0 }
1184
1193
copyRange = r. lowerBound..< ( r. lowerBound + Swift. min ( buffer. count * MemoryLayout< DestinationType> . stride, r. count) )
1185
1194
} else {
1186
1195
copyRange = 0 ..< Swift . min ( buffer. count * MemoryLayout< DestinationType> . stride, cnt)
1187
1196
}
1188
-
1197
+ _validateRange ( copyRange)
1198
+
1189
1199
guard !copyRange. isEmpty else { return 0 }
1190
1200
1191
1201
let nsRange = NSMakeRange ( copyRange. lowerBound, copyRange. upperBound - copyRange. lowerBound)
@@ -1243,6 +1253,7 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
1243
1253
public func range( of dataToFind: Data , options: Data . SearchOptions = [ ] , in range: Range < Index > ? = nil ) -> Range < Index > ? {
1244
1254
let nsRange : NSRange
1245
1255
if let r = range {
1256
+ _validateRange ( r)
1246
1257
nsRange = NSMakeRange ( r. lowerBound, r. upperBound - r. lowerBound)
1247
1258
} else {
1248
1259
nsRange = NSMakeRange ( 0 , _backing. length)
@@ -1266,6 +1277,7 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
1266
1277
1267
1278
@inline ( __always)
1268
1279
public mutating func append( _ bytes: UnsafePointer < UInt8 > , count: Int ) {
1280
+ precondition ( count >= 0 , " count must be positive " )
1269
1281
if count == 0 { return }
1270
1282
if !isKnownUniquelyReferenced( & _backing) {
1271
1283
_backing = _backing. mutableCopy ( _sliceRange)
@@ -1326,6 +1338,9 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
1326
1338
/// - parameter range: The range in the data to set to `0`.
1327
1339
@inline ( __always)
1328
1340
public mutating func resetBytes( in range: Range < Index > ) {
1341
+ // it is worth noting that the range here may be out of bounds of the Data itself (which triggers a growth)
1342
+ precondition ( range. lowerBound >= 0 , " Ranges must be positive bounds " )
1343
+ precondition ( range. upperBound >= 0 , " Ranges must be positive bounds " )
1329
1344
let range = NSMakeRange ( range. lowerBound, range. upperBound - range. lowerBound)
1330
1345
if !isKnownUniquelyReferenced( & _backing) {
1331
1346
_backing = _backing. mutableCopy ( _sliceRange)
@@ -1346,6 +1361,7 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
1346
1361
/// - parameter data: The replacement data.
1347
1362
@inline ( __always)
1348
1363
public mutating func replaceSubrange( _ subrange: Range < Index > , with data: Data ) {
1364
+ _validateRange ( subrange)
1349
1365
let nsRange = NSMakeRange ( subrange. lowerBound, subrange. upperBound - subrange. lowerBound)
1350
1366
let cnt = data. count
1351
1367
if !isKnownUniquelyReferenced( & _backing) {
@@ -1361,6 +1377,7 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
1361
1377
1362
1378
@inline ( __always)
1363
1379
public mutating func replaceSubrange( _ subrange: CountableRange < Index > , with data: Data ) {
1380
+ _validateRange ( subrange)
1364
1381
let nsRange = NSMakeRange ( subrange. lowerBound, subrange. upperBound - subrange. lowerBound)
1365
1382
let cnt = data. count
1366
1383
if !isKnownUniquelyReferenced( & _backing) {
@@ -1383,6 +1400,7 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
1383
1400
/// - parameter buffer: The replacement bytes.
1384
1401
@inline ( __always)
1385
1402
public mutating func replaceSubrange< SourceType> ( _ subrange: Range < Index > , with buffer: UnsafeBufferPointer < SourceType > ) {
1403
+ _validateRange ( subrange)
1386
1404
let nsRange = NSMakeRange ( subrange. lowerBound, subrange. upperBound - subrange. lowerBound)
1387
1405
let bufferCount = buffer. count * MemoryLayout< SourceType> . stride
1388
1406
@@ -1405,19 +1423,13 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
1405
1423
@inline ( __always)
1406
1424
public mutating func replaceSubrange< ByteCollection : Collection > ( _ subrange: Range < Index > , with newElements: ByteCollection )
1407
1425
where ByteCollection. Iterator. Element == Data . Iterator . Element {
1408
-
1426
+ _validateRange ( subrange )
1409
1427
// Calculate this once, it may not be O(1)
1410
1428
let replacementCount : Int = numericCast ( newElements. count)
1411
1429
let currentCount = self . count
1412
1430
let subrangeCount = subrange. count
1413
1431
1414
- if currentCount < subrange. lowerBound + subrangeCount {
1415
- if subrangeCount == 0 {
1416
- preconditionFailure ( " location \( subrange. lowerBound) exceeds data count \( currentCount) " )
1417
- } else {
1418
- preconditionFailure ( " range \( subrange) exceeds data count \( currentCount) " )
1419
- }
1420
- }
1432
+ _validateRange ( subrange)
1421
1433
1422
1434
let resultCount = currentCount - subrangeCount + replacementCount
1423
1435
if resultCount != currentCount {
@@ -1446,6 +1458,7 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
1446
1458
1447
1459
@inline ( __always)
1448
1460
public mutating func replaceSubrange( _ subrange: Range < Index > , with bytes: UnsafeRawPointer , count cnt: Int ) {
1461
+ _validateRange ( subrange)
1449
1462
let nsRange = NSMakeRange ( subrange. lowerBound, subrange. upperBound - subrange. lowerBound)
1450
1463
if !isKnownUniquelyReferenced( & _backing) {
1451
1464
_backing = _backing. mutableCopy ( _sliceRange)
@@ -1461,11 +1474,11 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
1461
1474
/// - parameter range: The range to copy.
1462
1475
@inline ( __always)
1463
1476
public func subdata( in range: Range < Index > ) -> Data {
1477
+ _validateRange ( range)
1464
1478
let length = count
1465
1479
if count == 0 {
1466
1480
return Data ( )
1467
1481
}
1468
- precondition ( length >= range. upperBound)
1469
1482
return _backing. subdata ( in: range)
1470
1483
}
1471
1484
@@ -1502,6 +1515,7 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
1502
1515
1503
1516
@inline ( __always)
1504
1517
public func advanced( by amount: Int ) -> Data {
1518
+ _validateIndex ( startIndex + amount)
1505
1519
let length = count - amount
1506
1520
precondition ( length > 0 )
1507
1521
return withUnsafeBytes { ( ptr: UnsafePointer < UInt8 > ) -> Data in
@@ -1518,10 +1532,12 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
1518
1532
public subscript( index: Index ) -> UInt8 {
1519
1533
@inline ( __always)
1520
1534
get {
1535
+ _validateIndex ( index)
1521
1536
return _backing. bytes!. advanced ( by: index) . assumingMemoryBound ( to: UInt8 . self) . pointee
1522
1537
}
1523
1538
@inline ( __always)
1524
1539
set {
1540
+ _validateIndex ( index)
1525
1541
if !isKnownUniquelyReferenced( & _backing) {
1526
1542
_backing = _backing. mutableCopy ( _sliceRange)
1527
1543
}
@@ -1532,6 +1548,7 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
1532
1548
public subscript( bounds: Range < Index > ) -> Data {
1533
1549
@inline ( __always)
1534
1550
get {
1551
+ _validateRange ( bounds)
1535
1552
return Data ( backing: _backing, range: bounds)
1536
1553
}
1537
1554
@inline ( __always)
@@ -1547,16 +1564,20 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
1547
1564
let range = rangeExpression. relative ( to: 0 ..< R . Bound. max)
1548
1565
let start : Int = numericCast ( range. lowerBound)
1549
1566
let end : Int = numericCast ( range. upperBound)
1550
- return Data ( backing: _backing, range: start..< end)
1567
+ let r : Range < Int > = start..< end
1568
+ _validateRange ( r)
1569
+ return Data ( backing: _backing, range: r)
1551
1570
}
1552
1571
@inline ( __always)
1553
1572
set {
1554
1573
let range = rangeExpression. relative ( to: 0 ..< R . Bound. max)
1555
1574
let start : Int = numericCast ( range. lowerBound)
1556
1575
let end : Int = numericCast ( range. upperBound)
1557
- replaceSubrange ( start..< end, with: newValue)
1576
+ let r : Range < Int > = start..< end
1577
+ _validateRange ( r)
1578
+ replaceSubrange ( r, with: newValue)
1558
1579
}
1559
-
1580
+
1560
1581
}
1561
1582
1562
1583
/// The start `Index` in the data.
0 commit comments