Skip to content

Commit 2f61737

Browse files
committed
Fix Data.count’s setter
Data provides a settable `count` property. Its expected behavior is undocumented, but based on the implementation, it is intended to zero-extend (or truncate) the collection to the specified length. This does not work correctly if we start with an empty Data and we try to increase the count by a small integer: ``` import Foundation var d = Data() d.count = 2 print(d.count) // ⟹ 0 ⁉️ d.count = 100 print(d.count) // ⟹ 100 ✓ ``` It looks like this bug was introduced with the Data overhaul that shipped in Swift 5. (This issue was uncovered by swiftlang/swift#28918.) rdar://58134026
1 parent b280852 commit 2f61737

File tree

2 files changed

+50
-1
lines changed

2 files changed

+50
-1
lines changed

Foundation/Data.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1440,7 +1440,7 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
14401440
if newValue == 0 {
14411441
return nil
14421442
} else if InlineData.canStore(count: newValue) {
1443-
return .inline(InlineData())
1443+
return .inline(InlineData(count: newValue))
14441444
} else if InlineSlice.canStore(count: newValue) {
14451445
return .slice(InlineSlice(count: newValue))
14461446
} else {

TestFoundation/TestNSData.swift

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -528,6 +528,8 @@ class TestNSData: LoopbackServerTest {
528528
("test_replaceSubrangeReferencingMutable", test_replaceSubrangeReferencingMutable),
529529
("test_replaceSubrangeReferencingImmutable", test_replaceSubrangeReferencingImmutable),
530530
("test_rangeOfSlice", test_rangeOfSlice),
531+
("test_Data_increaseCount", test_Data_increaseCount),
532+
("test_Data_decreaseCount", test_Data_decreaseCount),
531533
]
532534
}
533535

@@ -4528,5 +4530,52 @@ extension TestNSData {
45284530
let decodedData = NSData(coder: unarchiver)
45294531
XCTAssertEqual(data, decodedData)
45304532
}
4533+
4534+
func test_Data_increaseCount() {
4535+
guard #available(macOS 9999, iOS 9999, watchOS 9999, tvOS 9999, *) else { return }
4536+
let initials: [Range<UInt8>] = [
4537+
0..<0,
4538+
0..<2,
4539+
0..<4,
4540+
0..<8,
4541+
0..<16,
4542+
0..<32,
4543+
0..<64
4544+
]
4545+
let diffs = [0, 1, 2, 4, 8, 16, 32]
4546+
for initial in initials {
4547+
for diff in diffs {
4548+
var data = Data(initial)
4549+
data.count += diff
4550+
expectEqualSequence(
4551+
Array(initial) + Array(repeating: 0, count: diff),
4552+
data)
4553+
}
4554+
}
4555+
}
4556+
4557+
func test_Data_decreaseCount() {
4558+
guard #available(macOS 9999, iOS 9999, watchOS 9999, tvOS 9999, *) else { return }
4559+
let initials: [Range<UInt8>] = [
4560+
0..<0,
4561+
0..<2,
4562+
0..<4,
4563+
0..<8,
4564+
0..<16,
4565+
0..<32,
4566+
0..<64
4567+
]
4568+
let diffs = [0, 1, 2, 4, 8, 16, 32]
4569+
for initial in initials {
4570+
for diff in diffs {
4571+
guard initial.count >= diff else { continue }
4572+
var data = Data(initial)
4573+
data.count -= diff
4574+
expectEqualSequence(
4575+
initial.dropLast(diff),
4576+
data)
4577+
}
4578+
}
4579+
}
45314580
}
45324581

0 commit comments

Comments
 (0)