Skip to content

Commit fd8b266

Browse files
authored
Merge pull request #5269 from iCharlesHu/charles/cf-is-swift-nil-deref
Initialize _allBundles in _CFBundleCopyAllBundles before trying to copy it.
2 parents cfc5a16 + 0bb3920 commit fd8b266

File tree

1 file changed

+20
-11
lines changed

1 file changed

+20
-11
lines changed

Sources/CoreFoundation/CFBundle.c

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -255,22 +255,26 @@ CF_PRIVATE CFURLRef _CFURLCreateResolvedDirectoryWithString(CFAllocatorRef alloc
255255
#pragma mark -
256256
#pragma mark Bundle Tables
257257

258+
static void __CFBundleCreateAllBundlesArrayLocked() {
259+
CFArrayCallBacks callbacks = kCFTypeArrayCallBacks;
260+
#if TARGET_OS_OSX
261+
if (_useUnsafeUnretainedTables()) {
262+
callbacks.retain = NULL;
263+
callbacks.release = NULL;
264+
}
265+
#endif
266+
// The _allBundles array holds a strong reference on the bundle.
267+
// It does this to prevent a race on bundle deallocation / creation. See: <rdar://problem/6606482> CFBundle isn't thread-safe in RR mode
268+
// Also, the existence of the CFBundleGetBundleWithIdentifier / CFBundleGetAllBundles API means that any bundle we hand out from there must be permanently retained, or callers will potentially have an object that can be deallocated out from underneath them.
269+
_allBundles = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &callbacks);
270+
}
271+
258272
static void _CFBundleAddToTablesLocked(CFBundleRef bundle, CFStringRef bundleID) {
259273
if (bundle->_isUnique) return;
260274

261275
// Add to the _allBundles list
262276
if (!_allBundles) {
263-
CFArrayCallBacks callbacks = kCFTypeArrayCallBacks;
264-
#if TARGET_OS_OSX
265-
if (_useUnsafeUnretainedTables()) {
266-
callbacks.retain = NULL;
267-
callbacks.release = NULL;
268-
}
269-
#endif
270-
// The _allBundles array holds a strong reference on the bundle.
271-
// It does this to prevent a race on bundle deallocation / creation. See: <rdar://problem/6606482> CFBundle isn't thread-safe in RR mode
272-
// Also, the existence of the CFBundleGetBundleWithIdentifier / CFBundleGetAllBundles API means that any bundle we hand out from there must be permanently retained, or callers will potentially have an object that can be deallocated out from underneath them.
273-
_allBundles = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &callbacks);
277+
__CFBundleCreateAllBundlesArrayLocked();
274278
}
275279
CFArrayAppendValue(_allBundles, bundle);
276280

@@ -1795,6 +1799,11 @@ CF_EXPORT CFArrayRef _CFBundleCopyAllBundles(void) {
17951799
_CFBundleEnsureAllBundlesUpToDate();
17961800
CFBundleRef main = CFBundleGetMainBundle();
17971801
_CFMutexLock(&CFBundleGlobalDataLock);
1802+
// There is a chance that `_allBundles` haven't been initiated
1803+
// if no one called `CFBundleCreate()` yet
1804+
if (!_allBundles) {
1805+
__CFBundleCreateAllBundlesArrayLocked();
1806+
}
17981807
// _allBundles does not include the main bundle, so insert it here.
17991808
CFMutableArrayRef bundles = CFArrayCreateMutableCopy(kCFAllocatorSystemDefault, CFArrayGetCount(_allBundles) + 1, _allBundles);
18001809
_CFMutexUnlock(&CFBundleGlobalDataLock);

0 commit comments

Comments
 (0)