Skip to content

Ensure that hashing data with zero bytes avoids empty allocations and fix bridged empty data hashes from de-referencing null values #12511

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions stdlib/public/SDK/Foundation/Data.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1627,9 +1627,11 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
public var hashValue: Int {
var hashValue = 0
let hashRange: Range<Int> = _sliceRange.lowerBound..<Swift.min(_sliceRange.lowerBound + 80, _sliceRange.upperBound)
_withStackOrHeapBuffer(hashRange.count) { buffer in
_backing.withUnsafeBytes(in: hashRange) {
memcpy(buffer.pointee.memory, $0.baseAddress!, hashRange.count)
_withStackOrHeapBuffer(hashRange.count + 1) { buffer in
if hashRange.count > 0 {
_backing.withUnsafeBytes(in: hashRange) {
memcpy(buffer.pointee.memory, $0.baseAddress!, hashRange.count)
}
}
hashValue = Int(bitPattern: CFHashBytes(buffer.pointee.memory.assumingMemoryBound(to: UInt8.self), hashRange.count))
}
Expand Down
15 changes: 15 additions & 0 deletions test/stdlib/TestData.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3656,6 +3656,20 @@ class TestData : TestDataSuper {
expectEqual(Data(bytes: [0, 1, 2, 3, 4]), regionData[1]) //passes
expectEqual(Data(bytes: [0]), regionData[2]) //fails
}

func test_hashEmptyData() {
let d1 = Data()
let h1 = d1.hashValue

let d2 = NSData() as Data
let h2 = d2.hashValue
expectEqual(h1, h2)

let data = Data(bytes: [0, 1, 2, 3, 4, 5, 6])
let d3 = data[4..<4]
let h3 = d3.hashValue
expectEqual(h1, h3)
}
}

#if !FOUNDATION_XCTEST
Expand Down Expand Up @@ -3966,6 +3980,7 @@ DataTests.test("test_validateMutation_slice_cow_customMutableBacking_replaceSubr
DataTests.test("test_sliceHash") { TestData().test_sliceHash() }
DataTests.test("test_slice_resize_growth") { TestData().test_slice_resize_growth() }
DataTests.test("test_sliceEnumeration") { TestData().test_sliceEnumeration() }
DataTests.test("test_hashEmptyData") { TestData().test_hashEmptyData() }


// XCTest does not have a crash detection, whereas lit does
Expand Down