Skip to content

Commit b19c01d

Browse files
committed
Ensure that hashing data with zero bytes avoids empty allocations and fix bridged empty data hashes from de-referencing null values
1 parent ed43bef commit b19c01d

File tree

2 files changed

+20
-3
lines changed

2 files changed

+20
-3
lines changed

stdlib/public/SDK/Foundation/Data.swift

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1626,9 +1626,11 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
16261626
public var hashValue: Int {
16271627
var hashValue = 0
16281628
let hashRange: Range<Int> = _sliceRange.lowerBound..<Swift.min(_sliceRange.lowerBound + 80, _sliceRange.upperBound)
1629-
_withStackOrHeapBuffer(hashRange.count) { buffer in
1630-
_backing.withUnsafeBytes(in: hashRange) {
1631-
memcpy(buffer.pointee.memory, $0.baseAddress!, hashRange.count)
1629+
_withStackOrHeapBuffer(hashRange.count + 1) { buffer in
1630+
if hashRange.count > 0 {
1631+
_backing.withUnsafeBytes(in: hashRange) {
1632+
memcpy(buffer.pointee.memory, $0.baseAddress!, hashRange.count)
1633+
}
16321634
}
16331635
hashValue = Int(bitPattern: CFHashBytes(buffer.pointee.memory.assumingMemoryBound(to: UInt8.self), hashRange.count))
16341636
}

test/stdlib/TestData.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3663,6 +3663,20 @@ class TestData : TestDataSuper {
36633663
expectEqual(Data(bytes: [0, 1, 2, 3, 4]), regionData[1]) //passes
36643664
expectEqual(Data(bytes: [0]), regionData[2]) //fails
36653665
}
3666+
3667+
func test_hashEmptyData() {
3668+
let d1 = Data()
3669+
let h1 = d1.hashValue
3670+
3671+
let d2 = NSData() as Data
3672+
let h2 = d2.hashValue
3673+
expectEqual(h1, h2)
3674+
3675+
let data = Data(bytes: [0, 1, 2, 3, 4, 5, 6])
3676+
let d3 = data[4..<4]
3677+
let h3 = d3.hashValue
3678+
expectEqual(h1, h3)
3679+
}
36663680
}
36673681

36683682
#if !FOUNDATION_XCTEST
@@ -3973,6 +3987,7 @@ DataTests.test("test_validateMutation_slice_cow_customMutableBacking_replaceSubr
39733987
DataTests.test("test_sliceHash") { TestData().test_sliceHash() }
39743988
DataTests.test("test_slice_resize_growth") { TestData().test_slice_resize_growth() }
39753989
DataTests.test("test_sliceEnumeration") { TestData().test_sliceEnumeration() }
3990+
DataTests.test("test_hashEmptyData") { TestData().test_hashEmptyData() }
39763991

39773992
// XCTest does not have a crash detection, whereas lit does
39783993
DataTests.test("bounding failure subdata") {

0 commit comments

Comments
 (0)