Skip to content

Commit 2eac2cf

Browse files
committed
Fix CFInfo on 64-bit big endian platforms.
Prior to this change 64-bit platforms treated _cfinfoa as both a 64-bit and 32-bit variable. When accessing _cfinfoa as a 32-bit variable the code makes the assumption that it is accessing the lowest (or rightmost) bits of _cfinfoa. Unfortunately on big-endian platforms it is actually accessing the high (or leftmost) bits. Fix this issue by unconditionally treating _cfinfoa as a 64-bit value when targeting a 64-bit platform.
1 parent 59df77d commit 2eac2cf

File tree

4 files changed

+32
-14
lines changed

4 files changed

+32
-14
lines changed

CoreFoundation/Base.subproj/CFRuntime.c

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -388,12 +388,15 @@ CFTypeRef _CFRuntimeCreateInstance(CFAllocatorRef allocator, CFTypeID typeID, CF
388388

389389
// Zero the rest of the memory, starting at cfinfo
390390
memset(&memory->_cfinfoa, 0, size - (sizeof(memory->_cfisa) + sizeof(memory->_swift_rc)));
391-
391+
392392
// Set up the cfinfo struct
393-
uint32_t *cfinfop = (uint32_t *)&(memory->_cfinfoa);
394-
// The 0x80 means we use the default allocator
395-
*cfinfop = (uint32_t)(((uint32_t)typeID << 8) | (0x80));
396-
393+
uint32_t cfinfo = ((uint32_t)(typeID) << 8) | 0x80; // 0x80 means we use the default allocator
394+
#if __LP64__
395+
*(uint64_t *)&(memory->_cfinfoa) = (uint64_t)cfinfo;
396+
#else
397+
*(uint32_t *)&(memory->_cfinfoa) = cfinfo;
398+
#endif
399+
397400
return memory;
398401
#else
399402
if (__CFRuntimeClassTableSize <= typeID) HALT;

CoreFoundation/String.subproj/CFString.h

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -176,17 +176,10 @@ struct __CFConstStr {
176176
#define CONST_STRING_LITERAL_SECTION
177177
#endif
178178

179-
#if __BIG_ENDIAN__
180-
#define CFSTR(cStr) ({ \
181-
static struct __CFConstStr str CONST_STRING_LITERAL_SECTION = {{(uintptr_t)&__CFConstantStringClassReference, _CF_CONSTANT_OBJECT_STRONG_RC, 0x00000000C8070000}, (uint8_t *)(cStr), sizeof(cStr) - 1}; \
182-
(CFStringRef)&str; \
183-
})
184-
#else
185179
#define CFSTR(cStr) ({ \
186180
static struct __CFConstStr str CONST_STRING_LITERAL_SECTION = {{(uintptr_t)&__CFConstantStringClassReference, _CF_CONSTANT_OBJECT_STRONG_RC, 0x07C8}, (uint8_t *)(cStr), sizeof(cStr) - 1}; \
187181
(CFStringRef)&str; \
188182
})
189-
#endif
190183

191184
#else
192185

Foundation/NSObjCRuntime.swift

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -215,17 +215,33 @@ internal func NSInvalidArgument(_ message: String, method: String = #function, f
215215

216216
internal struct _CFInfo {
217217
// This must match _CFRuntimeBase
218+
#if arch(x86_64) || arch(arm64) || arch(s390x) || arch(powerpc64) || arch(powerpc64le)
219+
// 64-bit
220+
var info: UInt64
221+
init(typeID: CFTypeID) {
222+
// This matches what _CFRuntimeCreateInstance does to initialize the info value
223+
info = UInt64((UInt32(typeID) << 8) | 0x80)
224+
}
225+
init(typeID: CFTypeID, extra: UInt32) {
226+
info = UInt64((UInt32(typeID) << 8) | 0x80)
227+
info |= UInt64(extra) << 32
228+
}
229+
#elseif arch(arm) || arch(i386)
230+
// 32-bit
218231
var info: UInt32
219232
var pad : UInt32
220233
init(typeID: CFTypeID) {
221234
// This matches what _CFRuntimeCreateInstance does to initialize the info value
222-
info = UInt32((UInt32(typeID) << 8) | (UInt32(0x80)))
235+
info = (UInt32(typeID) << 8) | 0x80
223236
pad = 0
224237
}
225238
init(typeID: CFTypeID, extra: UInt32) {
226-
info = UInt32((UInt32(typeID) << 8) | (UInt32(0x80)))
239+
info = (UInt32(typeID) << 8) | 0x80
227240
pad = extra
228241
}
242+
#else
243+
#error("unknown architecture")
244+
#endif
229245
}
230246

231247
#if os(macOS) || os(iOS)

Foundation/NSSwiftRuntime.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,13 @@ extension ObjCBool : CustomStringConvertible {
8787
#endif
8888

8989
internal class __NSCFType : NSObject {
90+
#if arch(x86_64) || arch(arm64) || arch(s390x) || arch(powerpc64) || arch(powerpc64le)
91+
private var _cfinfo : Int64
92+
#elseif arch(arm) || arch(i386)
9093
private var _cfinfo : Int32
94+
#else
95+
#error("unknown architecture")
96+
#endif
9197

9298
override init() {
9399
// This is not actually called; _CFRuntimeCreateInstance will initialize _cfinfo

0 commit comments

Comments
 (0)