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

Issue:
App crashes in Release mode while logging App start session event
### Description

App works fine in `Debug` mode but crashes in `Release` mode upon App launch while logging App start session event. 
<img width="1155" alt="Screenshot 2023-06-06 at 4 56 23 PM" src="https://github.com/firebase/firebase-ios-sdk/assets/66404008/b5f754ff-ebfe-4966-9abf-5d0e7d3c7609">


### Reproducing the issue

We are observing this issue when using Bazel(https://bazel.build/) build system hence the Demo project is also built using Bazel.

To reproduce. 

Clone this repo - https://github.com/sanju-naik/bazel-demo-github , and checkout  `firebase-sessions-crash-in-opt` branch.
- Install bazelisk `brew install bazelisk`
- From the cloned repo, cd'into `BazelDemo` and run `bazel run //:BazelDemo_gen` to generate project. 
- open `BazelDemo.xcodeproj` and build `BazelDemo-Release` scheme you would notice crash as attached in above screenshot. 

### Firebase SDK Version

10.7.0

### Xcode Version

14.3

### Installation Method

CocoaPods

### Firebase Product(s)

Analytics, Crashlytics, Performance

### Targeted Platforms

iOS

### Relevant Log Output

_No response_

### 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

PODS:
  - Alamofire (5.6.4)
  - Firebase (10.7.0):
    - Firebase/Core (= 10.7.0)
  - Firebase/Core (10.7.0):
    - Firebase/CoreOnly
    - FirebaseAnalytics (~> 10.7.0)
  - Firebase/CoreOnly (10.7.0):
    - FirebaseCore (= 10.7.0)
  - FirebaseABTesting (10.10.0):
    - FirebaseCore (~> 10.0)
  - FirebaseAnalytics (10.7.0):
    - FirebaseAnalytics/AdIdSupport (= 10.7.0)
    - FirebaseCore (~> 10.0)
    - FirebaseInstallations (~> 10.0)
    - GoogleUtilities/AppDelegateSwizzler (~> 7.8)
    - GoogleUtilities/MethodSwizzler (~> 7.8)
    - GoogleUtilities/Network (~> 7.8)
    - "GoogleUtilities/NSData+zlib (~> 7.8)"
    - nanopb (< 2.30910.0, >= 2.30908.0)
  - FirebaseAnalytics/AdIdSupport (10.7.0):
    - FirebaseCore (~> 10.0)
    - FirebaseInstallations (~> 10.0)
    - GoogleAppMeasurement (= 10.7.0)
    - GoogleUtilities/AppDelegateSwizzler (~> 7.8)
    - GoogleUtilities/MethodSwizzler (~> 7.8)
    - GoogleUtilities/Network (~> 7.8)
    - "GoogleUtilities/NSData+zlib (~> 7.8)"
    - nanopb (< 2.30910.0, >= 2.30908.0)
  - FirebaseCore (10.7.0):
    - FirebaseCoreInternal (~> 10.0)
    - GoogleUtilities/Environment (~> 7.8)
    - GoogleUtilities/Logger (~> 7.8)
  - FirebaseCoreExtension (10.10.0):
    - FirebaseCore (~> 10.0)
  - FirebaseCoreInternal (10.10.0):
    - "GoogleUtilities/NSData+zlib (~> 7.8)"
  - FirebaseCrashlytics (10.7.0):
    - FirebaseCore (~> 10.5)
    - FirebaseInstallations (~> 10.0)
    - FirebaseSessions (~> 10.5)
    - GoogleDataTransport (~> 9.2)
    - GoogleUtilities/Environment (~> 7.8)
    - nanopb (< 2.30910.0, >= 2.30908.0)
    - PromisesObjC (~> 2.1)
  - FirebaseDynamicLinks (10.7.0):
    - FirebaseCore (~> 10.0)
  - FirebaseInstallations (10.10.0):
    - FirebaseCore (~> 10.0)
    - GoogleUtilities/Environment (~> 7.8)
    - GoogleUtilities/UserDefaults (~> 7.8)
    - PromisesObjC (~> 2.1)
  - FirebasePerformance (10.7.0):
    - FirebaseCore (~> 10.5)
    - FirebaseInstallations (~> 10.0)
    - FirebaseRemoteConfig (~> 10.0)
    - FirebaseSessions (~> 10.5)
    - GoogleDataTransport (~> 9.2)
    - GoogleUtilities/Environment (~> 7.8)
    - GoogleUtilities/ISASwizzler (~> 7.8)
    - GoogleUtilities/MethodSwizzler (~> 7.8)
    - nanopb (< 2.30910.0, >= 2.30908.0)
  - FirebaseRemoteConfig (10.7.0):
    - FirebaseABTesting (~> 10.0)
    - FirebaseCore (~> 10.0)
    - FirebaseInstallations (~> 10.0)
    - GoogleUtilities/Environment (~> 7.8)
    - "GoogleUtilities/NSData+zlib (~> 7.8)"
  - FirebaseSessions (10.10.0):
    - FirebaseCore (~> 10.5)
    - FirebaseCoreExtension (~> 10.0)
    - FirebaseInstallations (~> 10.0)
    - GoogleDataTransport (~> 9.2)
    - GoogleUtilities/Environment (~> 7.10)
    - nanopb (< 2.30910.0, >= 2.30908.0)
    - PromisesSwift (~> 2.1)
  - GoogleAppMeasurement (10.7.0):
    - GoogleAppMeasurement/AdIdSupport (= 10.7.0)
    - GoogleUtilities/AppDelegateSwizzler (~> 7.8)
    - GoogleUtilities/MethodSwizzler (~> 7.8)
    - GoogleUtilities/Network (~> 7.8)
    - "GoogleUtilities/NSData+zlib (~> 7.8)"
    - nanopb (< 2.30910.0, >= 2.30908.0)
  - GoogleAppMeasurement/AdIdSupport (10.7.0):
    - GoogleAppMeasurement/WithoutAdIdSupport (= 10.7.0)
    - GoogleUtilities/AppDelegateSwizzler (~> 7.8)
    - GoogleUtilities/MethodSwizzler (~> 7.8)
    - GoogleUtilities/Network (~> 7.8)
    - "GoogleUtilities/NSData+zlib (~> 7.8)"
    - nanopb (< 2.30910.0, >= 2.30908.0)
  - GoogleAppMeasurement/WithoutAdIdSupport (10.7.0):
    - GoogleUtilities/AppDelegateSwizzler (~> 7.8)
    - GoogleUtilities/MethodSwizzler (~> 7.8)
    - GoogleUtilities/Network (~> 7.8)
    - "GoogleUtilities/NSData+zlib (~> 7.8)"
    - nanopb (< 2.30910.0, >= 2.30908.0)
  - GoogleDataTransport (9.2.3):
    - GoogleUtilities/Environment (~> 7.7)
    - nanopb (< 2.30910.0, >= 2.30908.0)
    - PromisesObjC (< 3.0, >= 1.2)
  - GoogleUtilities/AppDelegateSwizzler (7.11.1):
    - GoogleUtilities/Environment
    - GoogleUtilities/Logger
    - GoogleUtilities/Network
  - GoogleUtilities/Environment (7.11.1):
    - PromisesObjC (< 3.0, >= 1.2)
  - GoogleUtilities/ISASwizzler (7.11.1)
  - GoogleUtilities/Logger (7.11.1):
    - GoogleUtilities/Environment
  - GoogleUtilities/MethodSwizzler (7.11.1):
    - GoogleUtilities/Logger
  - GoogleUtilities/Network (7.11.1):
    - GoogleUtilities/Logger
    - "GoogleUtilities/NSData+zlib"
    - GoogleUtilities/Reachability
  - "GoogleUtilities/NSData+zlib (7.11.1)"
  - GoogleUtilities/Reachability (7.11.1):
    - GoogleUtilities/Logger
  - GoogleUtilities/UserDefaults (7.11.1):
    - GoogleUtilities/Logger
  - nanopb (2.30909.0):
    - nanopb/decode (= 2.30909.0)
    - nanopb/encode (= 2.30909.0)
  - nanopb/decode (2.30909.0)
  - nanopb/encode (2.30909.0)
  - PromisesObjC (2.2.0)
  - PromisesSwift (2.2.0):
    - PromisesObjC (= 2.2.0)

DEPENDENCIES:
  - Alamofire
  - Firebase (= 10.7.0)
  - FirebaseCrashlytics (= 10.7.0)
  - FirebaseDynamicLinks (= 10.7.0)
  - FirebasePerformance (= 10.7.0)
  - FirebaseRemoteConfig (= 10.7.0)

SPEC REPOS:
  trunk:
    - Alamofire
    - Firebase
    - FirebaseABTesting
    - FirebaseAnalytics
    - FirebaseCore
    - FirebaseCoreExtension
    - FirebaseCoreInternal
    - FirebaseCrashlytics
    - FirebaseDynamicLinks
    - FirebaseInstallations
    - FirebasePerformance
    - FirebaseRemoteConfig
    - FirebaseSessions
    - GoogleAppMeasurement
    - GoogleDataTransport
    - GoogleUtilities
    - nanopb
    - PromisesObjC
    - PromisesSwift

SPEC CHECKSUMS:
  Alamofire: 4e95d97098eacb88856099c4fc79b526a299e48c
  Firebase: 0219acf760880eeec8ce479895bd7767466d9f81
  FirebaseABTesting: b2a87808d90f02766fcffb3957d3e397e7accc15
  FirebaseAnalytics: f8133442ee6f8512e28ff19e62ce15398bfaeace
  FirebaseCore: e317665b9d744727a97e623edbbed009320afdd7
  FirebaseCoreExtension: 8d93ebbf6838a874b4ed82a564c9d6705f8365dd
  FirebaseCoreInternal: 971029061d326000d65bfdc21f5502c75c8b0893
  FirebaseCrashlytics: 35fdd1a433b31e28adcf5c8933f4c526691a1e0b
  FirebaseDynamicLinks: 16a8fae3697fba66fed7a1d646fe59f30d42aa31
  FirebaseInstallations: 52153982b057d3afcb4e1fbb3eb0b6d00611e681
  FirebasePerformance: 8281bbaf08aad194001018b932115b7d58a6f00b
  FirebaseRemoteConfig: d5de62211e2eaa2152d8ee85a23c301b70887a74
  FirebaseSessions: 5f9e62cd4096e24d2011cbd845b0efceffaee1ec
  GoogleAppMeasurement: fe17c92a32207dd5cdd4e8d742767f2da74857f6
  GoogleDataTransport: f0308f5905a745f94fb91fea9c6cbaf3831cb1bd
  GoogleUtilities: 9aa0ad5a7bc171f8bae016300bfcfa3fb8425749
  nanopb: b552cce312b6c8484180ef47159bc0f65a1f0431
  PromisesObjC: 09985d6d70fbe7878040aa746d78236e6946d2ef
  PromisesSwift: cf9eb58666a43bbe007302226e510b16c1e10959

PODFILE CHECKSUM: be1abb165a8c7f88af2b139d4ea107cea4f424ac

COCOAPODS: 1.12.1


```

</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.
This may be the result of building the nanopb library without specifying the right options. For example see https://github.com/firebase/firebase-ios-sdk/blob/master/FirebaseCrashlytics.podspec#L101

` 'PB_FIELD_32BIT=1 PB_NO_PACKED_STRUCTS=1 PB_ENABLE_MALLOC=1'`
Above mentioned flags are being passed, From the example I shared, I am passing the flags here - https://github.com/sanju-naik/bazel-demo-github/blob/firebase-sessions-crash-in-opt/BazelDemo/Pods/nanopb/BUILD.bazel#L24 . But still the app crashes. 
Those flags also need to be passed to the clients of nanopb since the clients need to have the right `-D` options when they use the nanopb headers.
Ok, let me examine the `swiftc` invocations and check if these flags are present. 

> Those flags also need to be passed to the clients of nanopb 

By Clients here you mean Targets that depend on nanopb? i.e the Firebase Pods or Is it the iOS Application Targer?

Also in the same setup, it runs fine in `Debug` mode so just curious if those options are passed by default in Debug mode? 
 
Any Firebase product that sets the options in the podspec like https://github.com/firebase/firebase-ios-sdk/blob/master/FirebaseCrashlytics.podspec#L101 needs to be built with those options.

Crashes from alignment issues can be randomish since they depend on how linking occurs and whether or not data happens to fall on a required alignment boundary or not.
All the flags mentioned in the Podspec file are passed in all of the Firebase Pods as well as nanopb pod but it still crashes in `Release` mode. 
Also I tried comparing different compiler options between `debug` & `release` mode and add the `debug` mode ones to `Release` to get it working but still no luck 😞 .

Would it be possible to Debug this using the example I provided above and provide more insights onto which flag is causing this issue? 🙏 
@sanju-naik I don't seem to have access to the repository anymore. Were you able to get this working?
<!-- event: mark-stale -->
Hey @sanju-naik. We need more information to resolve this issue but there hasn't been an update in 5 weekdays. I'm marking the issue as stale and if there are no new updates in the next 5 days I will close it automatically.

If you have more information that will help us get to the bottom of this, just add a comment!
We solved this issue by issue by using `xcframework` of nanopb. But the issue still exists on source code based Cocoapod. If you can take a look at that, it would be great 🙏 Let me update and share the correct url for the Sample project. 
I'm seeing this issue as well on Firebase 10.21.0 from cocoapods. It happens on startup everytime
As discussed above, nanopb crashes are almost always related to a problem with option setting/propagation in the build system. 

We'll need a reproducible example to help here.
I was able to reproduce with the following project https://github.com/sergiocampama/SessionsTestApp on Xcode 15.3 beta 3, wasn't able to repro on 15.2, both attempts on a 17.2 iPhone simulator. It looks to be related to Xcode beta then. The project is configured to run on the simulator using the Release configuration. It does not reproduce on the Debug configuration. I believe you should be able to just download that project, pod install and then run on a simulator using xcode 15.3 beta 3 to reproduce.

<img width="740" alt="Screenshot 2024-02-24 at 7 23 07 PM" src="https://github.com/firebase/firebase-ios-sdk/assets/689198/f66d7b12-f6af-4b47-bd2e-7277dad96b55">

<img width="926" alt="Screenshot 2024-02-24 at 7 23 16 PM" src="https://github.com/firebase/firebase-ios-sdk/assets/689198/097ae5f6-7fcc-4cb7-9a86-1c9ccda85793">



> We solved this issue by issue by using `xcframework` of nanopb. But the issue still exists on source code based Cocoapod. If you can take a look at that, it would be great 🙏 Let me update and share the correct url for the Sample project.

@sanju-naik did you replace nanopb with an xcframework on a cocoapods project? could you share how you did it?


@sergiocampama Thanks for the repro, but I'm not able to reproduce the crash on Xcode 15.3 beta 3.  Maybe the crash is specific to Arm Macs, and I have an Intel Mac?
You should be able to connect an iPhone as well, a bit more cumbersome since you'll need to add your account to Xcode, change the bundle ID of the app and set your development team on the signing settings, but it should also reproduce there
Could also reproduce on a different Apple Silicon machine, same config as the above, could be that x86 simulators are unaffected.
Thanks. On an iPhone 13, I don't see a crash, but I see several log messages like:
```
10.21.0 - [FirebaseSessions][I-SES000000] Session Event failed to encode as proto with error: Optional(Error Domain=FIRSESEncodeError Code=-1 "(null)" UserInfo={NSLocalizedDescriptionKey=Error in nanopb encoding to get size: invalid data_size})
10.21.0 - [FirebaseSessions][I-SES000000] Session Event generated nil transportBytes. Returning empty data.
```
that doesn't occur when built in Debug mode.

And on closer inspection, the log failure DOES reproduce on the simulator when built in Release mode.
Looks like the issue could be related to type conversions between Swift UnsafeMutablePointers and C types. Note the difference between fields[1] and its corresponding entry in the original array.

The random? memory values in the entries after array element 0 would also explain sometimes crashing and sometimes logging an error message.

![Screenshot 2024-02-25 at 10 12 29 AM](https://github.com/firebase/firebase-ios-sdk/assets/73870/d90b545d-7ca6-447e-81a4-f2e309f04753)


Fix patch:
diff --git a/Crashlytics/CHANGELOG.md b/Crashlytics/CHANGELOG.md
index f040eecef96..52d43c7359d 100644
--- a/Crashlytics/CHANGELOG.md
+++ b/Crashlytics/CHANGELOG.md
@@ -1,5 +1,6 @@
-# Unreleased
+# 10.22.0
 - [changed] Removed calls to statfs in the Crashlytics SDK to comply with Apple Privacy Manifests. This change removes support for collecting Disk Space Free in Crashlytics reports.
+- [fixed] Fixed FirebaseSessions crash on startup that occurs in release mode in Xcode 15.3 and other build configurations. (#11403)
 
 # 10.16.0
 - [fixed] Fixed a memory leak regression when generating session events (#11725).
diff --git a/FirebaseSessions/Sources/SessionStartEvent.swift b/FirebaseSessions/Sources/SessionStartEvent.swift
index c107849a662..5a8d0d0148d 100644
--- a/FirebaseSessions/Sources/SessionStartEvent.swift
+++ b/FirebaseSessions/Sources/SessionStartEvent.swift
@@ -150,18 +150,7 @@ class SessionStartEvent: NSObject, GDTCOREventDataObject {
   // MARK: - GDTCOREventDataObject
 
   func transportBytes() -> Data {
-    var fields = firebase_appquality_sessions_SessionEvent_fields
-    var error: NSError?
-    let data = FIRSESEncodeProto(&fields.0, &proto, &error)
-    if error != nil {
-      Logger
-        .logError("Session Event failed to encode as proto with error: \(error.debugDescription)")
-    }
-    guard let data = data else {
-      Logger.logError("Session Event generated nil transportBytes. Returning empty data.")
-      return Data()
-    }
-    return data
+    return FIRSESTransportBytes(&proto)
   }
 
   // MARK: - Data Conversion
diff --git a/FirebaseSessions/SourcesObjC/NanoPB/FIRSESNanoPBHelpers.h b/FirebaseSessions/SourcesObjC/NanoPB/FIRSESNanoPBHelpers.h
index 8956ff022a6..e07f0e344ed 100644
--- a/FirebaseSessions/SourcesObjC/NanoPB/FIRSESNanoPBHelpers.h
+++ b/FirebaseSessions/SourcesObjC/NanoPB/FIRSESNanoPBHelpers.h
@@ -91,6 +91,9 @@ pb_size_t FIRSESGetAppleApplicationInfoTag(void);
 /// private method in GULAppEnvironmentUtil.
 NSString* _Nullable FIRSESGetSysctlEntry(const char* sysctlKey);
 
+/// C function to bridge from Swift to do nanopb bytes transfer.
+NSData* FIRSESTransportBytes(const void* _Nonnull proto);
+
 NS_ASSUME_NONNULL_END
 
 #endif /* FIRSESNanoPBHelpers_h */
diff --git a/FirebaseSessions/SourcesObjC/NanoPB/FIRSESNanoPBHelpers.m b/FirebaseSessions/SourcesObjC/NanoPB/FIRSESNanoPBHelpers.m
index 22cb8a61b2f..6440ec4d886 100644
--- a/FirebaseSessions/SourcesObjC/NanoPB/FIRSESNanoPBHelpers.m
+++ b/FirebaseSessions/SourcesObjC/NanoPB/FIRSESNanoPBHelpers.m
@@ -21,6 +21,8 @@
 
 #import "FirebaseSessions/SourcesObjC/Protogen/nanopb/sessions.nanopb.h"
 
+@import FirebaseCoreExtension;
+
 #import <nanopb/pb.h>
 #import <nanopb/pb_decode.h>
 #import <nanopb/pb_encode.h>
@@ -182,4 +184,22 @@ pb_size_t FIRSESGetAppleApplicationInfoTag(void) {
   }
 }
 
+NSData *FIRSESTransportBytes(const void *_Nonnull proto) {
+  const pb_field_t *fields = firebase_appquality_sessions_SessionEvent_fields;
+  NSError *error;
+  NSData *data = FIRSESEncodeProto(fields, proto, &error);
+  if (error != nil) {
+    FIRLogError(
+        @"FirebaseSessions", @"I-SES000001", @"%@",
+        [NSString stringWithFormat:@"Session Event failed to encode as proto with error: %@",
+                                   error.debugDescription]);
+  }
+  if (data == nil) {
+    data = [NSData data];
+    FIRLogError(@"FirebaseSessions", @"I-SES000002",
+                @"Session Event generated nil transportBytes. Returning empty data.");
+  }
+  return data;
+}
+
 NS_ASSUME_NONNULL_END
diff --git a/Package.swift b/Package.swift
index 5309b8ddbfd..9670eff963b 100644
--- a/Package.swift
+++ b/Package.swift
@@ -1076,6 +1076,8 @@ let package = Package(
     .target(
       name: "FirebaseSessionsObjC",
       dependencies: [
+        "FirebaseCore",
+        "FirebaseCoreExtension",
         .product(name: "GULEnvironment", package: "GoogleUtilities"),
         .product(name: "nanopb", package: "nanopb"),
       ],


Test patch: