Skip to content

Commit

Permalink
[SR-439] Cached floating-point CF values do not bridge
Browse files Browse the repository at this point in the history
If a bridged CF type is instantiated before __CFInitializeSwift() is called,
then those types will not be bridged. This created unusual and unexpected
results when initializing floating point numbers containing cached values
such as 0.0, 1.0 and NaN: decoding a property list containing these would
assert fail but other numbers would be fine.

This patch fixes this bug by moving the initialization of CFNumber constants
to a new function, __CFNumberInitialize(), which is called after the Swift
bridge is initialized. This patch is enabled but should not regress non-Swift
builds.

CFNull and CFBooleans are instantiated before __CFInitializeSwift() is called;
if these types are ever bridged then a similar fix must be made.
  • Loading branch information
lhoward committed Jan 2, 2016
1 parent de8559c commit c9e528a
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 26 deletions.
3 changes: 3 additions & 0 deletions CoreFoundation/Base.subproj/CFInternal.h
Expand Up @@ -662,6 +662,9 @@ CF_INLINE uintptr_t __CFISAForTypeID(CFTypeID typeID) {
return (typeID < __CFRuntimeClassTableSize) ? __CFRuntimeObjCClassTable[typeID] : 0;
}

/* For Swift, which can't allocate any CF objects until after the bridge is initialized */
CF_PRIVATE void __CFNumberInitialize(void);

/* See comments in CFBase.c
*/
#define FAULT_CALLBACK(V)
Expand Down
1 change: 1 addition & 0 deletions CoreFoundation/Base.subproj/CFRuntime.c
Expand Up @@ -1169,6 +1169,7 @@ void __CFInitialize(void) {
extern void __CFInitializeSwift();
__CFInitializeSwift();
#endif
__CFNumberInitialize(); /* needs to happen after Swift bridge is initialized */
{
CFIndex idx, cnt = 0;
char **args = NULL;
Expand Down
53 changes: 27 additions & 26 deletions CoreFoundation/NumberDate.subproj/CFNumber.c
Expand Up @@ -1045,39 +1045,40 @@ CFTypeID CFNumberGetTypeID(void) {
dispatch_once(&initOnce, ^{
__kCFNumberTypeID = _CFRuntimeRegisterClass(&__CFNumberClass); // initOnce covered

_CFRuntimeSetInstanceTypeIDAndIsa(&__kCFNumberNaN, __kCFNumberTypeID);
__CFBitfieldSetValue(__kCFNumberNaN._base._cfinfo[CF_INFO_BITS], 4, 0, kCFNumberFloat64Type);
__kCFNumberNaN._pad = BITSFORDOUBLENAN;

_CFRuntimeSetInstanceTypeIDAndIsa(& __kCFNumberNegativeInfinity, __kCFNumberTypeID);
__CFBitfieldSetValue(__kCFNumberNegativeInfinity._base._cfinfo[CF_INFO_BITS], 4, 0, kCFNumberFloat64Type);
__kCFNumberNegativeInfinity._pad = BITSFORDOUBLENEGINF;
const char *caching = __CFgetenv("CFNumberDisableCache"); // "all" to disable caching and tagging; anything else to disable caching; nothing to leave both enabled
if (caching) __CFNumberCaching = (!strcmp(caching, "all")) ? kCFNumberCachingFullyDisabled : kCFNumberCachingDisabled; // initial state above is kCFNumberCachingEnabled
});
return __kCFNumberTypeID;
}

_CFRuntimeSetInstanceTypeIDAndIsa(& __kCFNumberPositiveInfinity, __kCFNumberTypeID);
__CFBitfieldSetValue(__kCFNumberPositiveInfinity._base._cfinfo[CF_INFO_BITS], 4, 0, kCFNumberFloat64Type);
__kCFNumberPositiveInfinity._pad = BITSFORDOUBLEPOSINF;
CF_PRIVATE void __CFNumberInitialize(void) {
_CFRuntimeSetInstanceTypeIDAndIsa(&__kCFNumberNaN, __kCFNumberTypeID);
__CFBitfieldSetValue(__kCFNumberNaN._base._cfinfo[CF_INFO_BITS], 4, 0, kCFNumberFloat64Type);
__kCFNumberNaN._pad = BITSFORDOUBLENAN;

_CFRuntimeSetInstanceTypeIDAndIsa(& __kCFNumberFloat32Zero, __kCFNumberTypeID);
__CFBitfieldSetValue(__kCFNumberFloat32Zero._base._cfinfo[CF_INFO_BITS], 4, 0, kCFNumberFloat32Type);
__kCFNumberFloat32Zero._pad = BITSFORFLOATZERO;
_CFRuntimeSetInstanceTypeIDAndIsa(& __kCFNumberNegativeInfinity, __kCFNumberTypeID);
__CFBitfieldSetValue(__kCFNumberNegativeInfinity._base._cfinfo[CF_INFO_BITS], 4, 0, kCFNumberFloat64Type);
__kCFNumberNegativeInfinity._pad = BITSFORDOUBLENEGINF;

_CFRuntimeSetInstanceTypeIDAndIsa(& __kCFNumberFloat32One, __kCFNumberTypeID);
__CFBitfieldSetValue(__kCFNumberFloat32One._base._cfinfo[CF_INFO_BITS], 4, 0, kCFNumberFloat32Type);
__kCFNumberFloat32One._pad = BITSFORFLOATONE;
_CFRuntimeSetInstanceTypeIDAndIsa(& __kCFNumberPositiveInfinity, __kCFNumberTypeID);
__CFBitfieldSetValue(__kCFNumberPositiveInfinity._base._cfinfo[CF_INFO_BITS], 4, 0, kCFNumberFloat64Type);
__kCFNumberPositiveInfinity._pad = BITSFORDOUBLEPOSINF;

_CFRuntimeSetInstanceTypeIDAndIsa(& __kCFNumberFloat64Zero, __kCFNumberTypeID);
__CFBitfieldSetValue(__kCFNumberFloat64Zero._base._cfinfo[CF_INFO_BITS], 4, 0, kCFNumberFloat64Type);
__kCFNumberFloat64Zero._pad = BITSFORDOUBLEZERO;
_CFRuntimeSetInstanceTypeIDAndIsa(& __kCFNumberFloat32Zero, __kCFNumberTypeID);
__CFBitfieldSetValue(__kCFNumberFloat32Zero._base._cfinfo[CF_INFO_BITS], 4, 0, kCFNumberFloat32Type);
__kCFNumberFloat32Zero._pad = BITSFORFLOATZERO;

_CFRuntimeSetInstanceTypeIDAndIsa(& __kCFNumberFloat64One, __kCFNumberTypeID);
__CFBitfieldSetValue(__kCFNumberFloat64One._base._cfinfo[CF_INFO_BITS], 4, 0, kCFNumberFloat64Type);
__kCFNumberFloat64One._pad = BITSFORDOUBLEONE;
_CFRuntimeSetInstanceTypeIDAndIsa(& __kCFNumberFloat32One, __kCFNumberTypeID);
__CFBitfieldSetValue(__kCFNumberFloat32One._base._cfinfo[CF_INFO_BITS], 4, 0, kCFNumberFloat32Type);
__kCFNumberFloat32One._pad = BITSFORFLOATONE;

_CFRuntimeSetInstanceTypeIDAndIsa(& __kCFNumberFloat64Zero, __kCFNumberTypeID);
__CFBitfieldSetValue(__kCFNumberFloat64Zero._base._cfinfo[CF_INFO_BITS], 4, 0, kCFNumberFloat64Type);
__kCFNumberFloat64Zero._pad = BITSFORDOUBLEZERO;

const char *caching = __CFgetenv("CFNumberDisableCache"); // "all" to disable caching and tagging; anything else to disable caching; nothing to leave both enabled
if (caching) __CFNumberCaching = (!strcmp(caching, "all")) ? kCFNumberCachingFullyDisabled : kCFNumberCachingDisabled; // initial state above is kCFNumberCachingEnabled
});
return __kCFNumberTypeID;
_CFRuntimeSetInstanceTypeIDAndIsa(& __kCFNumberFloat64One, __kCFNumberTypeID);
__CFBitfieldSetValue(__kCFNumberFloat64One._base._cfinfo[CF_INFO_BITS], 4, 0, kCFNumberFloat64Type);
__kCFNumberFloat64One._pad = BITSFORDOUBLEONE;
}

#define MinCachedInt (-1)
Expand Down

0 comments on commit c9e528a

Please sign in to comment.