Repository: firebase/firebase-ios-sdk (language: cpp)

Issue:
Deadlock caused by call to objc_copyImageNames in FIRPopulateProtoWithNumberOfLinkedFrameworks
### Environment

  * Xcode version: 12.1
  * Firebase SDK version: 6.34.0
  * Installation method: `CocoaPods` (select one)
  * Firebase Component: Crashlytics

### Problem

Firebase's call to `objc_copyImageNames` within `FIRPopulateProtoWithNumberOfLinkedFrameworks` can sometimes trigger a deadlock on launch (if another thread is performing a `dlopen`, e.g. CFNetwork) resulting in the app being terminated by the system watchdog. This has been filed as a bug report with Apple (FB8971497) and discussed on the developer forums [here ](https://developer.apple.com/forums/thread/671497?answerId=657367022&page=1#657354022) however it's worth raising here as well to see if there's any workarounds.

Is it possible to disable diagnostics including the number of linked frameworks to remove the call to `objc_copyImageNames`? 

#### Steps to reproduce:

In an app that makes a network request at launch, with a reasonable number of dynamic libraries linked (~5+), it may trigger a deadlock (timing dependant) resulting in the app being terminated by the system watchdog. Crash report can be found [here](https://gist.github.com/SquaredTiki/11a58e6837029e44da6098b34486658d).



Discussion / hints:
Thanks for the report and sorry for the issue. It looks like the right approach here is to just remove this as it's not needed anymore. I'll put a PR shortly for it.

Fix patch:
diff --git a/Example/CoreDiagnostics/Tests/FIRCoreDiagnosticsTest.m b/Example/CoreDiagnostics/Tests/FIRCoreDiagnosticsTest.m
index daff05ae5d0..a7240a45f2e 100644
--- a/Example/CoreDiagnostics/Tests/FIRCoreDiagnosticsTest.m
+++ b/Example/CoreDiagnostics/Tests/FIRCoreDiagnosticsTest.m
@@ -160,7 +160,6 @@ - (void)testProtoPopulation {
   });
   icoreConfiguration.using_gdt = 1;
   icoreConfiguration.has_using_gdt = 1;
-  FIRPopulateProtoWithNumberOfLinkedFrameworks(&icoreConfiguration);
   FIRPopulateProtoWithInfoPlistValues(&icoreConfiguration);
   icoreConfiguration.configuration_type =
       logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_CORE;
@@ -198,22 +197,7 @@ - (void)populateProto:(logs_proto_mobilesdk_ios_ICoreConfiguration *)config {
   config->has_app_count = 1;
   config->use_default_app = 1;
   config->has_use_default_app = 1;
-
-  int numFrameworks = -1;  // Subtract the app binary itself.
-  unsigned int numImages;
-  const char **imageNames = objc_copyImageNames(&numImages);
-  for (unsigned int i = 0; i < numImages; i++) {
-    NSString *imageName = [NSString stringWithUTF8String:imageNames[i]];
-    if ([imageName rangeOfString:@"System/Library"].length != 0        // Apple .frameworks
-        || [imageName rangeOfString:@"Developer/Library"].length != 0  // Xcode debug .frameworks
-        || [imageName rangeOfString:@"usr/lib"].length != 0) {         // Public .dylibs
-      continue;
-    }
-    numFrameworks++;
-  }
-  free(imageNames);
-  config->dynamic_framework_count = numFrameworks;
-  config->has_dynamic_framework_count = 1;
+  config->has_dynamic_framework_count = 0;  // Removed from payload.
   config->apple_framework_version = FIREncodeString(combinedVersions);
   NSString *minVersion = [[NSBundle mainBundle] infoDictionary][@"MinimumOSVersion"];
   if (minVersion) {
diff --git a/Firebase/CoreDiagnostics/FIRCDLibrary/FIRCoreDiagnostics.m b/Firebase/CoreDiagnostics/FIRCDLibrary/FIRCoreDiagnostics.m
index 32eda1b257d..8ad55e5cf45 100644
--- a/Firebase/CoreDiagnostics/FIRCDLibrary/FIRCoreDiagnostics.m
+++ b/Firebase/CoreDiagnostics/FIRCDLibrary/FIRCoreDiagnostics.m
@@ -37,7 +37,7 @@
 
 #ifdef FIREBASE_BUILD_ZIP_FILE
 static BOOL kUsingZipFile = YES;
-#else  // FIREBASE_BUILD_ZIP_FILE
+#else   // FIREBASE_BUILD_ZIP_FILE
 static BOOL kUsingZipFile = NO;
 #endif  // FIREBASE_BUILD_ZIP_FILE
 
@@ -454,29 +454,6 @@ void FIRPopulateProtoWithInstalledServices(logs_proto_mobilesdk_ios_ICoreConfigu
   config->sdk_service_installed_count = (int32_t)sdkServiceInstalledArray.count;
 }
 
-/** Populates the proto with the number of linked frameworks.
- *
- * @param config The proto to populate.
- */
-void FIRPopulateProtoWithNumberOfLinkedFrameworks(
-    logs_proto_mobilesdk_ios_ICoreConfiguration *config) {
-  int numFrameworks = -1;  // Subtract the app binary itself.
-  unsigned int numImages;
-  const char **imageNames = objc_copyImageNames(&numImages);
-  for (unsigned int i = 0; i < numImages; i++) {
-    NSString *imageName = [NSString stringWithUTF8String:imageNames[i]];
-    if ([imageName rangeOfString:@"System/Library"].length != 0        // Apple .frameworks
-        || [imageName rangeOfString:@"Developer/Library"].length != 0  // Xcode debug .frameworks
-        || [imageName rangeOfString:@"usr/lib"].length != 0) {         // Public .dylibs
-      continue;
-    }
-    numFrameworks++;
-  }
-  free(imageNames);
-  config->dynamic_framework_count = numFrameworks;
-  config->has_dynamic_framework_count = 1;
-}
-
 /** Populates the proto with Info.plist values.
  *
  * @param config The proto to populate.
@@ -532,7 +509,6 @@ - (void)sendDiagnosticsData:(nonnull id<FIRCoreDiagnosticsData>)diagnosticsData
     FIRPopulateProtoWithInfoFromUserInfoParams(&icore_config, diagnosticObjects);
     FIRPopulateProtoWithCommonInfoFromApp(&icore_config, diagnosticObjects);
     FIRPopulateProtoWithInstalledServices(&icore_config);
-    FIRPopulateProtoWithNumberOfLinkedFrameworks(&icore_config);
     FIRPopulateProtoWithInfoPlistValues(&icore_config);
     [self setHeartbeatFlagIfNeededToConfig:&icore_config];
 
diff --git a/FirebaseCore/CHANGELOG.md b/FirebaseCore/CHANGELOG.md
index 96824d42630..c143af5c43d 100644
--- a/FirebaseCore/CHANGELOG.md
+++ b/FirebaseCore/CHANGELOG.md
@@ -1,3 +1,5 @@
+# Unreleased
+- [fixed] Fixed potential deadlock with objc_copyImageNames call. (#7310)
 # Firebase 7.4.0
 - [changed] Patch update to nanopb 0.3.9.7 that fixes a memory leak and other issues. (#7090)
 - [added] Zip distribution now includes community supported macOS and tvOS libraries. Product


Test patch: