Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit d99723b

Browse files
committed
Avoid corrupting NSData -> CFDataRef due to invalid storage size layout of dealloc handler versus CFAllocatorRef, sizeof(swift closure) != sizeof(void *)
1 parent 26b4b96 commit d99723b

File tree

1 file changed

+9
-6
lines changed

1 file changed

+9
-6
lines changed

Foundation/NSData.swift

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -58,14 +58,17 @@ public struct NSDataBase64DecodingOptions : OptionSetType {
5858
public static let Anchored = NSDataSearchOptions(rawValue: UInt(1 << 1))
5959
}
6060

61+
class _NSDataDeallocator {
62+
var handler: (UnsafeMutablePointer<Void>, Int) -> Void = {_,_ in }
63+
}
64+
6165
public class NSData : NSObject, NSCopying, NSMutableCopying, NSSecureCoding {
6266
private static let DeallocationSentry = UInt32(0xB5A5A5AB) // this is a slightly sub-par solution, however we cannot caputre self in the block for deallocation but we need a way of passing the bytes (in case of realloc) to the block and a way of then disambiguating between CFAllocators and dealloc handlers
6367
typealias CFType = CFDataRef
6468
private var _base = _CFInfo(typeID: CFDataGetTypeID(), extra: NSData.DeallocationSentry)
6569
private var _length: CFIndex = 0
6670
private var _capacity: CFIndex = 0
67-
private typealias _NSDataDeallocator = (UnsafeMutablePointer<Void>, Int) -> Void
68-
private var _deallocHandler: _NSDataDeallocator?
71+
private var _deallocHandler = _NSDataDeallocator()
6972
private var _bytes: UnsafeMutablePointer<UInt8> = nil
7073

7174
internal var _cfObject: CFType {
@@ -84,15 +87,15 @@ public class NSData : NSObject, NSCopying, NSMutableCopying, NSSecureCoding {
8487

8588
deinit {
8689
if _base.pad == NSData.DeallocationSentry && _bytes != nil {
87-
if let handler = _deallocHandler {
88-
handler(_bytes, _length)
89-
}
90+
_deallocHandler.handler(_bytes, _length)
9091
}
9192
_CFDeinit(self)
9293
}
9394

9495
internal init(bytes: UnsafeMutablePointer<Void>, length: Int, copy: Bool, deallocator: ((UnsafeMutablePointer<Void>, Int) -> Void)?) {
95-
_deallocHandler = deallocator
96+
if let handler = deallocator {
97+
_deallocHandler.handler = handler
98+
}
9699

97100
super.init()
98101
let options : CFOptionFlags = (self.dynamicType == NSMutableData.self) ? 0x1 | 0x2 : 0x0

0 commit comments

Comments
 (0)