Skip to content

Commit a33dfb5

Browse files
phauslerparkera
authored andcommitted
Synchronize Data.swift from the overlay (#1282)
This pulls in the fixes for: Guard Data access to NSData._isCompact under availability guards Ensure that hashing data with zero bytes avoids empty allocations and fix bridged empty data hashes from de-referencing null values (#12509)
1 parent 1b4bb4e commit a33dfb5

File tree

1 file changed

+25
-7
lines changed

1 file changed

+25
-7
lines changed

Foundation/Data.swift

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,22 @@ internal func __NSDataIsCompact(_ data: NSData) -> Bool {
3838
import _SwiftFoundationOverlayShims
3939
import _SwiftCoreFoundationOverlayShims
4040

41+
internal func __NSDataIsCompact(_ data: NSData) -> Bool {
42+
if #available(OSX 10.10, iOS 9.0, tvOS 9.0, watchOS 2.0, *) {
43+
return data._isCompact()
44+
} else {
45+
var compact = true
46+
let len = data.length
47+
data.enumerateBytes { (_, byteRange, stop) in
48+
if byteRange.length != len {
49+
compact = false
50+
}
51+
stop.pointee = true
52+
}
53+
return compact
54+
}
55+
}
56+
4157
@_silgen_name("__NSDataWriteToURL")
4258
internal func __NSDataWriteToURL(_ data: NSData, _ url: NSURL, _ options: UInt, _ error: NSErrorPointer) -> Bool
4359

@@ -130,7 +146,7 @@ public final class _DataStorage {
130146
case .mutable:
131147
return try apply(UnsafeRawBufferPointer(start: _bytes?.advanced(by: range.lowerBound - _offset), count: Swift.min(range.count, _length)))
132148
case .customReference(let d):
133-
if d._isCompact() {
149+
if __NSDataIsCompact(d) {
134150
let len = d.length
135151
guard len > 0 else {
136152
return try apply(UnsafeRawBufferPointer(start: nil, count: 0))
@@ -161,7 +177,7 @@ public final class _DataStorage {
161177
return try apply(UnsafeRawBufferPointer(buffer))
162178
}
163179
case .customMutableReference(let d):
164-
if d._isCompact() {
180+
if __NSDataIsCompact(d) {
165181
let len = d.length
166182
guard len > 0 else {
167183
return try apply(UnsafeRawBufferPointer(start: nil, count: 0))
@@ -505,7 +521,7 @@ public final class _DataStorage {
505521
case .mutable:
506522
return _bytes!.advanced(by: index - _offset).assumingMemoryBound(to: UInt8.self).pointee
507523
case .customReference(let d):
508-
if d._isCompact() {
524+
if __NSDataIsCompact(d) {
509525
return d.bytes.advanced(by: index - _offset).assumingMemoryBound(to: UInt8.self).pointee
510526
} else {
511527
var byte: UInt8 = 0
@@ -519,7 +535,7 @@ public final class _DataStorage {
519535
return byte
520536
}
521537
case .customMutableReference(let d):
522-
if d._isCompact() {
538+
if __NSDataIsCompact(d) {
523539
return d.bytes.advanced(by: index - _offset).assumingMemoryBound(to: UInt8.self).pointee
524540
} else {
525541
var byte: UInt8 = 0
@@ -1626,9 +1642,11 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
16261642
public var hashValue: Int {
16271643
var hashValue = 0
16281644
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)
1645+
_withStackOrHeapBuffer(hashRange.count + 1) { buffer in
1646+
if hashRange.count > 0 {
1647+
_backing.withUnsafeBytes(in: hashRange) {
1648+
memcpy(buffer.pointee.memory, $0.baseAddress!, hashRange.count)
1649+
}
16321650
}
16331651
hashValue = Int(bitPattern: CFHashBytes(buffer.pointee.memory.assumingMemoryBound(to: UInt8.self), hashRange.count))
16341652
}

0 commit comments

Comments
 (0)