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

Issue:
FirebaseMessaging calls length on NSNull when no image given
### Description

In the case where populateNotificationContent is used from an iOS notification service extension but the notification has `content.userInfo[kPayloadOptionsName][kPayloadOptionsImageURLName]` not set, a `-[NSNull length]: unrecognized selector sent to instance` exception is raised and the thread is terminated.

The issue is an incorrect nil check in populateNotificationContent.

### Reproducing the issue

1. Create an iOS notification service extension following the guide at https://firebase.google.com/docs/cloud-messaging/ios/send-image
2. Using XCode, run the app to deploy it onto a physical device, then stop the app so the NSE will run
3. Use XCode to open the device console, and start recording
4. Send a notification that does *not* set image in the fcm_options for APNS
5. Observe the error in the console output for the notification service you created in step 1


### Firebase SDK Version

10.9

### Xcode Version

14.3

### Installation Method

CocoaPods

### Firebase Product(s)

Messaging

### Targeted Platforms

iOS

### Relevant Log Output

```shell
default	17:14:29.354397+1200	NotificationExt	[4BB0A9E6-86B7-4AEE-9DF8-99B6F5BBC764] Request replacement content for notification request B795-D9CB
default	17:14:29.355974+1200	NotificationExt	-[NSNull length]: unrecognized selector sent to instance 0x212e62c48
fault	17:14:29.357412+1200	NotificationExt	<NSXPCConnection: 0x10310b870> connection to service with pid 41336 created from an endpoint: Warning: Exception caught during invocation of selector didReceiveNotificationRequest:withCompletionHandler:, dropping incoming message and invalidating the connection.
Exception: -[NSNull length]: unrecognized selector sent to instance 0x212e62c48
-[NSNull length]: unrecognized selector sent to instance 0x212e62c48
(
	0   CoreFoundation                      0x00000001bae30cc0 4230C122-42E8-383B-BEEC-EE7B61F8BB61 + 40128
	1   libobjc.A.dylib                     0x00000001b3ed83d0 objc_exception_throw + 60
	2   CoreFoundation                      0x00000001bafa5ab8 4230C122-42E8-383B-BEEC-EE7B61F8BB61 + 1567416
	3   CoreFoundation                      0x00000001bae470e8 4230C122-42E8-383B-BEEC-EE7B61F8BB61 + 131304
	4   CoreFoundation                      0x00000001baead900 _CF_forwarding_prep_0 + 96
	5   CoreFoundation                      0x00000001bae8fb0c 4230C122-42E8-383B-BEEC-EE7B61F8BB61 + 428812
	6   Foundation                          0x00000001b510fb30 6E76DC96-11AF-3B2E-B71E-215F9CC6E822 + 142128
	7   FirebaseMessaging                   0x0000000102f0f8b8 -[FIRMessagingExtensionHelper populateNotificationContent:withContentHandler:] + 200
	8   NotificationExt                     0x0000000102cca5c0 $s15NotificationExt0A7ServiceC10didReceive_18withContentHandlerySo21UNNotificationRequestC_ySo0iG0CctF + 664
	9   NotificationExt                     0x0000000102cca6b8 $s15NotificationExt0A7ServiceC10didReceive_18withContentHandlerySo21UNNotificationRequestC_ySo0iG0CctFTo + 112
	10  UserNotifications                   0x00000001ddec21cc EC182B78-B223-39C0-B028-CAA3A948913A + 53708
	11  Foundation                          0x00000001b51908e8 6E76DC96-11AF-3B2E-B71E-215F9CC6E822 + 669928
	12  Foundation                          0x00000001b56ce8d8 6E76DC96-11AF-3B2E-B71E-215F9CC6E822 + 6166744
	13  Foundation                          0x00000001b56d00c4 6E76DC96-11AF-3B2E-B71E-215F9CC6E822 + 6172868
	14  Foundation                          0x00000001b56cfb30 6E76DC96-11AF-3B2E-B71E-215F9CC6E822 + 6171440
	15  libxpc.dylib                        0x000000021ac30af0 9EBB5610-EEE0-3407-A3C2-49279EEBCB59 + 72432
	16  libxpc.dylib                        0x000000021ac30f20 9EBB5610-EEE0-3407-A3C2-49279EEBCB59 + 73504
	17  libdispatch.dylib                   0x00000001c22f6f6c BB347F0E-F21C-3607-82E6-C8D750FDBF8C + 16236
	18  libdispatch.dylib                   0x00000001c23136ec BB347F0E-F21C-3607-82E6-C8D750FDBF8C + 132844
	19  libdispatch.dylib                   0x00000001c22fe40c BB347F0E-F21C-3607-82E6-C8D750FDBF8C + 46092
	20  libdispatch.dylib                   0x00000001c2314438 BB347F0E-F21C-3607-82E6-C8D750FDBF8C + 136248
	21  libdispatch.dylib                   0x00000001c22fe40c BB347F0E-F21C-3607-82E6-C8D750FDBF8C + 46092
	22  libdispatch.dylib                   0x00000001c22ff0d8 BB347F0E-F21C-3607-82E6-C8D750FDBF8C + 49368
	23  libdispatch.dylib                   0x00000001c2309cdc BB347F0E-F21C-3607-82E6-C8D750FDBF8C + 93404
	24  libsystem_pthread.dylib             0x000000021abdcddc _pthread_wqthread + 288
	25  libsystem_pthread.dylib             0x000000021abdcb7c start_wqthread + 8
)
default	17:14:29.357609+1200	NotificationExt	*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSNull length]: unrecognized selector sent to instance 0x212e62c48'
*** First throw call stack:
(0x1bae30cb4 0x1b3ed83d0 0x1bafa5ab8 0x1bae470e8 0x1baead900 0x1bae8fb0c 0x1b510fb30 0x102f0f8b8 0x102cca5c0 0x102cca6b8 0x1ddec21cc 0x1b51908e8 0x1b56ce8d8 0x1b56d00c4 0x1b56cfb30 0x21ac30af0 0x21ac30f20 0x1c22f6f6c 0x1c23136ec 0x1c22fe40c 0x1c2314438 0x1c22fe40c 0x1c22ff0d8 0x1c2309cdc 0x21abdcddc 0x21abdcb7c)
```
```


### If using Swift Package Manager, the project's Package.resolved

<!--- Look below for instructions on how to share your Package.resolved. --->

<details>
<summary>Expand <code>Package.resolved</code> snippet</summary>
<br>

```json

Replace this line with the contents of your Package.resolved.

```

</details>


### If using CocoaPods, the project's Podfile.lock

<!--- Look below for instructions on how to share your Podfile.lock. --->

<details>
<summary>Expand <code>Podfile.lock</code> snippet</summary>
<br>

```yml

Replace this line with the contents of your Podfile.lock!

```

</details>



Discussion / hints:
I couldn't figure out how to label this issue, so I've labeled it for a human to triage. Hang tight.
The problem is here:

```
- (void)populateNotificationContent:(UNMutableNotificationContent *)content
                 withContentHandler:(void (^)(UNNotificationContent *_Nonnull))contentHandler {
  self.contentHandler = [contentHandler copy];
  self.bestAttemptContent = content;

  // The `userInfo` property isn't available on newer versions of tvOS.
#if TARGET_OS_IOS || TARGET_OS_OSX || TARGET_OS_WATCH
  NSString *currentImageURL = content.userInfo[kPayloadOptionsName][kPayloadOptionsImageURLName];
  if (!currentImageURL) {
    [self deliverNotification];
    return;
  }
```

This tries to handle the nil case, but you don't get `nil` from the hash - you get `NSNull`.

Fix patch:
diff --git a/FirebaseMessaging/Sources/FIRMessagingExtensionHelper.m b/FirebaseMessaging/Sources/FIRMessagingExtensionHelper.m
index 30c150baefb..79b9e4adf5b 100644
--- a/FirebaseMessaging/Sources/FIRMessagingExtensionHelper.m
+++ b/FirebaseMessaging/Sources/FIRMessagingExtensionHelper.m
@@ -112,12 +112,12 @@ - (void)populateNotificationContent:(UNMutableNotificationContent *)content
 
   // The `userInfo` property isn't available on newer versions of tvOS.
 #if TARGET_OS_IOS || TARGET_OS_OSX || TARGET_OS_WATCH
-  NSString *currentImageURL = content.userInfo[kPayloadOptionsName][kPayloadOptionsImageURLName];
-  if (!currentImageURL) {
+  NSObject *currentImageURL = content.userInfo[kPayloadOptionsName][kPayloadOptionsImageURLName];
+  if (!currentImageURL || currentImageURL == [NSNull null]) {
     [self deliverNotification];
     return;
   }
-  NSURL *attachmentURL = [NSURL URLWithString:currentImageURL];
+  NSURL *attachmentURL = [NSURL URLWithString:(NSString *)currentImageURL];
   if (attachmentURL) {
     [self loadAttachmentForURL:attachmentURL
              completionHandler:^(UNNotificationAttachment *attachment) {


Test patch: