Skip to content

Commit 79b80a8

Browse files
sashabelonogovphausler
authored andcommitted
[SR-6361] Fix Data.withUnsafeMutableBytes() for slices with length < range.lowerBound (swiftlang#1314)
1 parent 58f7912 commit 79b80a8

File tree

2 files changed

+54
-4
lines changed

2 files changed

+54
-4
lines changed

Foundation/Data.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -214,20 +214,20 @@ public final class _DataStorage {
214214
switch _backing {
215215
case .swift: fallthrough
216216
case .mutable:
217-
return try apply(UnsafeMutableRawBufferPointer(start: _bytes!.advanced(by:range.lowerBound - _offset), count: Swift.min(range.count, _length - range.lowerBound)))
217+
return try apply(UnsafeMutableRawBufferPointer(start: _bytes!.advanced(by:range.lowerBound - _offset), count: Swift.min(range.count, _length)))
218218
case .customMutableReference(let d):
219219
let len = d.length
220-
return try apply(UnsafeMutableRawBufferPointer(start: d.mutableBytes.advanced(by:range.lowerBound - _offset), count: Swift.min(range.count, len - range.lowerBound)))
220+
return try apply(UnsafeMutableRawBufferPointer(start: d.mutableBytes.advanced(by:range.lowerBound - _offset), count: Swift.min(range.count, len)))
221221
case .immutable(let d):
222222
let data = d.mutableCopy() as! NSMutableData
223223
_backing = .mutable(data)
224224
_bytes = data.mutableBytes
225-
return try apply(UnsafeMutableRawBufferPointer(start: _bytes!.advanced(by:range.lowerBound - _offset), count: Swift.min(range.count, _length - range.lowerBound)))
225+
return try apply(UnsafeMutableRawBufferPointer(start: _bytes!.advanced(by:range.lowerBound - _offset), count: Swift.min(range.count, _length)))
226226
case .customReference(let d):
227227
let data = d.mutableCopy() as! NSMutableData
228228
_backing = .customMutableReference(data)
229229
let len = data.length
230-
return try apply(UnsafeMutableRawBufferPointer(start: data.mutableBytes.advanced(by:range.lowerBound - _offset), count: Swift.min(range.count, len - range.lowerBound)))
230+
return try apply(UnsafeMutableRawBufferPointer(start: data.mutableBytes.advanced(by:range.lowerBound - _offset), count: Swift.min(range.count, len)))
231231
}
232232
}
233233

TestFoundation/TestNSData.swift

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -509,6 +509,12 @@ class TestNSData: XCTestCase {
509509
// ("test_sliceEnumeration", test_sliceEnumeration),
510510
("test_sliceInsertion", test_sliceInsertion),
511511
("test_sliceDeletion", test_sliceDeletion),
512+
("test_validateMutation_slice_withUnsafeMutableBytes_lengthLessThanLowerBound", test_validateMutation_slice_withUnsafeMutableBytes_lengthLessThanLowerBound),
513+
("test_validateMutation_slice_immutableBacking_withUnsafeMutableBytes_lengthLessThanLowerBound", test_validateMutation_slice_immutableBacking_withUnsafeMutableBytes_lengthLessThanLowerBound),
514+
("test_validateMutation_slice_mutableBacking_withUnsafeMutableBytes_lengthLessThanLowerBound", test_validateMutation_slice_mutableBacking_withUnsafeMutableBytes_lengthLessThanLowerBound),
515+
("test_validateMutation_slice_customBacking_withUnsafeMutableBytes_lengthLessThanLowerBound", test_validateMutation_slice_customBacking_withUnsafeMutableBytes_lengthLessThanLowerBound),
516+
("test_validateMutation_slice_customMutableBacking_withUnsafeMutableBytes_lengthLessThanLowerBound",
517+
test_validateMutation_slice_customMutableBacking_withUnsafeMutableBytes_lengthLessThanLowerBound),
512518
]
513519
}
514520

@@ -3979,5 +3985,49 @@ extension TestNSData {
39793985
XCTAssertEqual(mutableSliceData.startIndex, 2)
39803986
XCTAssertEqual(mutableSliceData.endIndex, sliceData.endIndex - numberOfElementsToDelete)
39813987
}
3988+
3989+
func test_validateMutation_slice_withUnsafeMutableBytes_lengthLessThanLowerBound() {
3990+
var data = Data(bytes: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])[4..<6]
3991+
data.withUnsafeMutableBytes { (ptr: UnsafeMutablePointer<UInt8>) in
3992+
ptr.advanced(by: 1).pointee = 0xFF
3993+
}
3994+
XCTAssertEqual(data, Data(bytes: [4, 0xFF]))
3995+
}
3996+
3997+
func test_validateMutation_slice_immutableBacking_withUnsafeMutableBytes_lengthLessThanLowerBound() {
3998+
var data = Data(referencing: NSData(bytes: "hello world", length: 11))[4..<6]
3999+
data.withUnsafeMutableBytes { (ptr: UnsafeMutablePointer<UInt8>) in
4000+
ptr.advanced(by: 1).pointee = 0xFF
4001+
}
4002+
XCTAssertEqual(data[data.startIndex.advanced(by: 1)], 0xFF)
4003+
}
4004+
4005+
func test_validateMutation_slice_mutableBacking_withUnsafeMutableBytes_lengthLessThanLowerBound() {
4006+
var base = Data(referencing: NSData(bytes: "hello world", length: 11))
4007+
base.append(contentsOf: [1, 2, 3, 4, 5, 6])
4008+
var data = base[4..<6]
4009+
data.withUnsafeMutableBytes { (ptr: UnsafeMutablePointer<UInt8>) in
4010+
ptr.advanced(by: 1).pointee = 0xFF
4011+
}
4012+
XCTAssertEqual(data[data.startIndex.advanced(by: 1)], 0xFF)
4013+
}
4014+
4015+
func test_validateMutation_slice_customBacking_withUnsafeMutableBytes_lengthLessThanLowerBound() {
4016+
var data = Data(referencing: AllOnesImmutableData(length: 10))[4..<6]
4017+
data.withUnsafeMutableBytes { (ptr: UnsafeMutablePointer<UInt8>) in
4018+
ptr.advanced(by: 1).pointee = 0xFF
4019+
}
4020+
XCTAssertEqual(data[data.startIndex.advanced(by: 1)], 0xFF)
4021+
}
4022+
4023+
func test_validateMutation_slice_customMutableBacking_withUnsafeMutableBytes_lengthLessThanLowerBound() {
4024+
var base = Data(referencing: AllOnesData(length: 1))
4025+
base.count = 10
4026+
var data = base[4..<6]
4027+
data.withUnsafeMutableBytes { (ptr: UnsafeMutablePointer<UInt8>) in
4028+
ptr.advanced(by: 1).pointee = 0xFF
4029+
}
4030+
XCTAssertEqual(data[data.startIndex.advanced(by: 1)], 0xFF)
4031+
}
39824032
}
39834033

0 commit comments

Comments
 (0)