From 46ef1adf4bce960fc4b5e00263453f4b8458d331 Mon Sep 17 00:00:00 2001 From: Philipp Hofmann Date: Thu, 18 Sep 2025 13:42:30 +0200 Subject: [PATCH 01/13] fix: Crash in native bridge add breadcrumb --- package-dev/Plugins/iOS/SentryNativeBridge.m | 46 +++++++++++++++----- 1 file changed, 34 insertions(+), 12 deletions(-) diff --git a/package-dev/Plugins/iOS/SentryNativeBridge.m b/package-dev/Plugins/iOS/SentryNativeBridge.m index e1e204285..0e2f2e41b 100644 --- a/package-dev/Plugins/iOS/SentryNativeBridge.m +++ b/package-dev/Plugins/iOS/SentryNativeBridge.m @@ -64,24 +64,46 @@ void SentryNativeBridgeAddBreadcrumb( return; } + // Convert all C strings to NSStrings before entering the scope block to reduce the risk + // of the const char * being freed before the scope block is executed. + NSString *timestampString = nil; + if (timestamp != NULL) { + timestampString = [NSString stringWithUTF8String:timestamp]; + } + + NSString *messageString = nil; + if (message != NULL) { + messageString = [NSString stringWithUTF8String:message]; + } + + NSString *typeString = nil; + if (type != NULL) { + typeString = [NSString stringWithUTF8String:type]; + } + + NSString *categoryString = nil; + if (category != NULL) { + categoryString = [NSString stringWithUTF8String:category]; + } + [SentrySDK configureScope:^(SentryScope *scope) { + SentryBreadcrumb *breadcrumb = [[SentryBreadcrumb alloc] initWithLevel:level - category:(category ? [NSString stringWithUTF8String:category] : nil)]; + category:categoryString]; - if (timestamp != NULL) { + if (timestampString != nil && timestampString.length > 0) { NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; [dateFormatter setDateFormat:NSCalendarIdentifierISO8601]; - breadcrumb.timestamp = - [dateFormatter dateFromString:[NSString stringWithUTF8String:timestamp]]; + breadcrumb.timestamp = [dateFormatter dateFromString:timestampString]; } - if (message != NULL) { - breadcrumb.message = [NSString stringWithUTF8String:message]; + if (messageString != nil) { + breadcrumb.message = messageString; } - if (type != NULL) { - breadcrumb.type = [NSString stringWithUTF8String:type]; + if (typeString != nil) { + breadcrumb.type = typeString; } [scope addBreadcrumb:breadcrumb]; @@ -184,15 +206,15 @@ void SentryNativeBridgeSetTrace(const char *traceId, const char *spanId) NSString *traceIdStr = [NSString stringWithUTF8String:traceId]; NSString *spanIdStr = [NSString stringWithUTF8String:spanId]; - + // This is a workaround to deal with SentryId living inside the Swift header Class sentryIdClass = NSClassFromString(@"_TtC6Sentry8SentryId"); Class sentrySpanIdClass = NSClassFromString(@"SentrySpanId"); - + if (sentryIdClass && sentrySpanIdClass) { id sentryTraceId = [[sentryIdClass alloc] initWithUUIDString:traceIdStr]; id sentrySpanId = [[sentrySpanIdClass alloc] initWithValue:spanIdStr]; - + if (sentryTraceId && sentrySpanId) { [PrivateSentrySDKOnly setTrace:sentryTraceId spanId:sentrySpanId]; } @@ -288,4 +310,4 @@ void SentryNativeBridgeWriteScope( // clang-format off }]; } -NS_ASSUME_NONNULL_END \ No newline at end of file +NS_ASSUME_NONNULL_END From b22ef270bd205fe69bc93e0b678ae635f2ce1c64 Mon Sep 17 00:00:00 2001 From: bitsandfoxes Date: Mon, 22 Sep 2025 12:23:48 +0200 Subject: [PATCH 02/13] Preallocate all instances --- package-dev/Plugins/iOS/SentryNativeBridge.m | 73 ++++++++--- .../Plugins/macOS/SentryNativeBridge.m | 113 +++++++++++++----- 2 files changed, 140 insertions(+), 46 deletions(-) diff --git a/package-dev/Plugins/iOS/SentryNativeBridge.m b/package-dev/Plugins/iOS/SentryNativeBridge.m index 0e2f2e41b..65f1f6aaf 100644 --- a/package-dev/Plugins/iOS/SentryNativeBridge.m +++ b/package-dev/Plugins/iOS/SentryNativeBridge.m @@ -116,12 +116,18 @@ void SentryNativeBridgeSetExtra(const char *key, const char *value) return; } + // Convert C strings to NSStrings before entering the scope block + NSString *keyString = [NSString stringWithUTF8String:key]; + NSString *valueString = nil; + if (value != NULL) { + valueString = [NSString stringWithUTF8String:value]; + } + [SentrySDK configureScope:^(SentryScope *scope) { - if (value != NULL) { - [scope setExtraValue:[NSString stringWithUTF8String:value] - forKey:[NSString stringWithUTF8String:key]]; + if (valueString != nil) { + [scope setExtraValue:valueString forKey:keyString]; } else { - [scope removeExtraForKey:[NSString stringWithUTF8String:key]]; + [scope removeExtraForKey:keyString]; } }]; } @@ -132,12 +138,18 @@ void SentryNativeBridgeSetTag(const char *key, const char *value) return; } + // Convert C strings to NSStrings before entering the scope block + NSString *keyString = [NSString stringWithUTF8String:key]; + NSString *valueString = nil; + if (value != NULL) { + valueString = [NSString stringWithUTF8String:value]; + } + [SentrySDK configureScope:^(SentryScope *scope) { - if (value != NULL) { - [scope setTagValue:[NSString stringWithUTF8String:value] - forKey:[NSString stringWithUTF8String:key]]; + if (valueString != nil) { + [scope setTagValue:valueString forKey:keyString]; } else { - [scope removeTagForKey:[NSString stringWithUTF8String:key]]; + [scope removeTagForKey:keyString]; } }]; } @@ -148,8 +160,12 @@ void SentryNativeBridgeUnsetTag(const char *key) return; } - [SentrySDK configureScope:^( - SentryScope *scope) { [scope removeTagForKey:[NSString stringWithUTF8String:key]]; }]; + // Convert C string to NSString before entering the scope block + NSString *keyString = [NSString stringWithUTF8String:key]; + + [SentrySDK configureScope:^(SentryScope *scope) { + [scope removeTagForKey:keyString]; + }]; } void SentryNativeBridgeSetUser( @@ -159,23 +175,44 @@ void SentryNativeBridgeSetUser( return; } + // Convert C strings to NSStrings before entering the scope block + NSString *emailString = nil; + if (email != NULL) { + emailString = [NSString stringWithUTF8String:email]; + } + + NSString *userIdString = nil; + if (userId != NULL) { + userIdString = [NSString stringWithUTF8String:userId]; + } + + NSString *ipAddressString = nil; + if (ipAddress != NULL) { + ipAddressString = [NSString stringWithUTF8String:ipAddress]; + } + + NSString *usernameString = nil; + if (username != NULL) { + usernameString = [NSString stringWithUTF8String:username]; + } + [SentrySDK configureScope:^(SentryScope *scope) { SentryUser *user = [[SentryUser alloc] init]; - if (email != NULL) { - user.email = [NSString stringWithUTF8String:email]; + if (emailString != nil) { + user.email = emailString; } - if (userId != NULL) { - user.userId = [NSString stringWithUTF8String:userId]; + if (userIdString != nil) { + user.userId = userIdString; } - if (ipAddress != NULL) { - user.ipAddress = [NSString stringWithUTF8String:ipAddress]; + if (ipAddressString != nil) { + user.ipAddress = ipAddressString; } - if (username != NULL) { - user.username = [NSString stringWithUTF8String:username]; + if (usernameString != nil) { + user.username = usernameString; } [scope setUser:user]; diff --git a/package-dev/Plugins/macOS/SentryNativeBridge.m b/package-dev/Plugins/macOS/SentryNativeBridge.m index 8156671aa..c0e42ce86 100644 --- a/package-dev/Plugins/macOS/SentryNativeBridge.m +++ b/package-dev/Plugins/macOS/SentryNativeBridge.m @@ -156,27 +156,47 @@ void SentryNativeBridgeAddBreadcrumb( return; } + // Convert all C strings to NSStrings before entering the scope block to reduce the risk + // of the const char * being freed before the scope block is executed. + NSString *timestampString = nil; + if (timestamp != NULL) { + timestampString = [NSString stringWithUTF8String:timestamp]; + } + + NSString *messageString = nil; + if (message != NULL) { + messageString = [NSString stringWithUTF8String:message]; + } + + NSString *typeString = nil; + if (type != NULL) { + typeString = [NSString stringWithUTF8String:type]; + } + + NSString *categoryString = nil; + if (category != NULL) { + categoryString = [NSString stringWithUTF8String:category]; + } + SentryConfigureScope(^(id scope) { id breadcrumb = [[SentryBreadcrumb alloc] init]; - if (timestamp != NULL) { + if (timestampString != nil && timestampString.length > 0) { NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; [dateFormatter setDateFormat:NSCalendarIdentifierISO8601]; - [breadcrumb - setValue:[dateFormatter dateFromString:[NSString stringWithUTF8String:timestamp]] - forKey:@"timestamp"]; + [breadcrumb setValue:[dateFormatter dateFromString:timestampString] forKey:@"timestamp"]; } - if (message != NULL) { - [breadcrumb setValue:[NSString stringWithUTF8String:message] forKey:@"message"]; + if (messageString != nil) { + [breadcrumb setValue:messageString forKey:@"message"]; } - if (type != NULL) { - [breadcrumb setValue:[NSString stringWithUTF8String:type] forKey:@"type"]; + if (typeString != nil) { + [breadcrumb setValue:typeString forKey:@"type"]; } - if (category != NULL) { - [breadcrumb setValue:[NSString stringWithUTF8String:category] forKey:@"category"]; + if (categoryString != nil) { + [breadcrumb setValue:categoryString forKey:@"category"]; } [breadcrumb setValue:[NSNumber numberWithInt:level] forKey:@"level"]; @@ -191,14 +211,21 @@ void SentryNativeBridgeSetExtra(const char *key, const char *value) return; } + // Convert C strings to NSStrings before entering the scope block + NSString *keyString = [NSString stringWithUTF8String:key]; + NSString *valueString = nil; + if (value != NULL) { + valueString = [NSString stringWithUTF8String:value]; + } + SentryConfigureScope(^(id scope) { - if (value != NULL) { + if (valueString != nil) { [scope performSelector:@selector(setExtraValue:forKey:) - withObject:[NSString stringWithUTF8String:value] - withObject:[NSString stringWithUTF8String:key]]; + withObject:valueString + withObject:keyString]; } else { [scope performSelector:@selector(removeExtraForKey:) - withObject:[NSString stringWithUTF8String:key]]; + withObject:keyString]; } }); } @@ -209,14 +236,21 @@ void SentryNativeBridgeSetTag(const char *key, const char *value) return; } + // Convert C strings to NSStrings before entering the scope block + NSString *keyString = [NSString stringWithUTF8String:key]; + NSString *valueString = nil; + if (value != NULL) { + valueString = [NSString stringWithUTF8String:value]; + } + SentryConfigureScope(^(id scope) { - if (value != NULL) { + if (valueString != nil) { [scope performSelector:@selector(setTagValue:forKey:) - withObject:[NSString stringWithUTF8String:value] - withObject:[NSString stringWithUTF8String:key]]; + withObject:valueString + withObject:keyString]; } else { [scope performSelector:@selector(removeTagForKey:) - withObject:[NSString stringWithUTF8String:key]]; + withObject:keyString]; } }); } @@ -227,9 +261,11 @@ void SentryNativeBridgeUnsetTag(const char *key) return; } + // Convert C string to NSString before entering the scope block + NSString *keyString = [NSString stringWithUTF8String:key]; + SentryConfigureScope(^(id scope) { - [scope performSelector:@selector(removeTagForKey:) - withObject:[NSString stringWithUTF8String:key]]; + [scope performSelector:@selector(removeTagForKey:) withObject:keyString]; }); } @@ -240,23 +276,44 @@ void SentryNativeBridgeSetUser( return; } + // Convert C strings to NSStrings before entering the scope block + NSString *emailString = nil; + if (email != NULL) { + emailString = [NSString stringWithUTF8String:email]; + } + + NSString *userIdString = nil; + if (userId != NULL) { + userIdString = [NSString stringWithUTF8String:userId]; + } + + NSString *ipAddressString = nil; + if (ipAddress != NULL) { + ipAddressString = [NSString stringWithUTF8String:ipAddress]; + } + + NSString *usernameString = nil; + if (username != NULL) { + usernameString = [NSString stringWithUTF8String:username]; + } + SentryConfigureScope(^(id scope) { id user = [[SentryUser alloc] init]; - if (email != NULL) { - [user setValue:[NSString stringWithUTF8String:email] forKey:@"email"]; + if (emailString != nil) { + [user setValue:emailString forKey:@"email"]; } - if (userId != NULL) { - [user setValue:[NSString stringWithUTF8String:userId] forKey:@"userId"]; + if (userIdString != nil) { + [user setValue:userIdString forKey:@"userId"]; } - if (ipAddress != NULL) { - [user setValue:[NSString stringWithUTF8String:ipAddress] forKey:@"ipAddress"]; + if (ipAddressString != nil) { + [user setValue:ipAddressString forKey:@"ipAddress"]; } - if (username != NULL) { - [user setValue:[NSString stringWithUTF8String:username] forKey:@"username"]; + if (usernameString != nil) { + [user setValue:usernameString forKey:@"username"]; } [scope performSelector:@selector(setUser:) withObject:user]; From f7806eb6d0dffd92b2d02d1b81585ab9acb7e64f Mon Sep 17 00:00:00 2001 From: bitsandfoxes Date: Mon, 22 Sep 2025 14:30:54 +0200 Subject: [PATCH 03/13] Cleanup --- package-dev/Plugins/iOS/SentryNativeBridge.m | 6 ------ package-dev/Plugins/macOS/SentryNativeBridge.m | 6 ------ 2 files changed, 12 deletions(-) diff --git a/package-dev/Plugins/iOS/SentryNativeBridge.m b/package-dev/Plugins/iOS/SentryNativeBridge.m index 65f1f6aaf..40c5950c6 100644 --- a/package-dev/Plugins/iOS/SentryNativeBridge.m +++ b/package-dev/Plugins/iOS/SentryNativeBridge.m @@ -64,8 +64,6 @@ void SentryNativeBridgeAddBreadcrumb( return; } - // Convert all C strings to NSStrings before entering the scope block to reduce the risk - // of the const char * being freed before the scope block is executed. NSString *timestampString = nil; if (timestamp != NULL) { timestampString = [NSString stringWithUTF8String:timestamp]; @@ -116,7 +114,6 @@ void SentryNativeBridgeSetExtra(const char *key, const char *value) return; } - // Convert C strings to NSStrings before entering the scope block NSString *keyString = [NSString stringWithUTF8String:key]; NSString *valueString = nil; if (value != NULL) { @@ -138,7 +135,6 @@ void SentryNativeBridgeSetTag(const char *key, const char *value) return; } - // Convert C strings to NSStrings before entering the scope block NSString *keyString = [NSString stringWithUTF8String:key]; NSString *valueString = nil; if (value != NULL) { @@ -160,7 +156,6 @@ void SentryNativeBridgeUnsetTag(const char *key) return; } - // Convert C string to NSString before entering the scope block NSString *keyString = [NSString stringWithUTF8String:key]; [SentrySDK configureScope:^(SentryScope *scope) { @@ -175,7 +170,6 @@ void SentryNativeBridgeSetUser( return; } - // Convert C strings to NSStrings before entering the scope block NSString *emailString = nil; if (email != NULL) { emailString = [NSString stringWithUTF8String:email]; diff --git a/package-dev/Plugins/macOS/SentryNativeBridge.m b/package-dev/Plugins/macOS/SentryNativeBridge.m index c0e42ce86..a9ba54978 100644 --- a/package-dev/Plugins/macOS/SentryNativeBridge.m +++ b/package-dev/Plugins/macOS/SentryNativeBridge.m @@ -156,8 +156,6 @@ void SentryNativeBridgeAddBreadcrumb( return; } - // Convert all C strings to NSStrings before entering the scope block to reduce the risk - // of the const char * being freed before the scope block is executed. NSString *timestampString = nil; if (timestamp != NULL) { timestampString = [NSString stringWithUTF8String:timestamp]; @@ -211,7 +209,6 @@ void SentryNativeBridgeSetExtra(const char *key, const char *value) return; } - // Convert C strings to NSStrings before entering the scope block NSString *keyString = [NSString stringWithUTF8String:key]; NSString *valueString = nil; if (value != NULL) { @@ -236,7 +233,6 @@ void SentryNativeBridgeSetTag(const char *key, const char *value) return; } - // Convert C strings to NSStrings before entering the scope block NSString *keyString = [NSString stringWithUTF8String:key]; NSString *valueString = nil; if (value != NULL) { @@ -261,7 +257,6 @@ void SentryNativeBridgeUnsetTag(const char *key) return; } - // Convert C string to NSString before entering the scope block NSString *keyString = [NSString stringWithUTF8String:key]; SentryConfigureScope(^(id scope) { @@ -276,7 +271,6 @@ void SentryNativeBridgeSetUser( return; } - // Convert C strings to NSStrings before entering the scope block NSString *emailString = nil; if (email != NULL) { emailString = [NSString stringWithUTF8String:email]; From adf2f0fa159067a5ee64fadc7a0e76a73fb2a023 Mon Sep 17 00:00:00 2001 From: bitsandfoxes Date: Mon, 22 Sep 2025 15:51:04 +0200 Subject: [PATCH 04/13] Handle utf8 string gracefully, fix timestamp --- package-dev/Plugins/iOS/SentryNativeBridge.m | 30 +++++------------ .../Plugins/macOS/SentryNativeBridge.m | 33 +++++++------------ 2 files changed, 19 insertions(+), 44 deletions(-) diff --git a/package-dev/Plugins/iOS/SentryNativeBridge.m b/package-dev/Plugins/iOS/SentryNativeBridge.m index 40c5950c6..626bf86ff 100644 --- a/package-dev/Plugins/iOS/SentryNativeBridge.m +++ b/package-dev/Plugins/iOS/SentryNativeBridge.m @@ -64,25 +64,11 @@ void SentryNativeBridgeAddBreadcrumb( return; } - NSString *timestampString = nil; - if (timestamp != NULL) { - timestampString = [NSString stringWithUTF8String:timestamp]; - } - - NSString *messageString = nil; - if (message != NULL) { - messageString = [NSString stringWithUTF8String:message]; - } - - NSString *typeString = nil; - if (type != NULL) { - typeString = [NSString stringWithUTF8String:type]; - } - - NSString *categoryString = nil; - if (category != NULL) { - categoryString = [NSString stringWithUTF8String:category]; - } + // Convert C strings to NSStrings, handling invalid UTF-8 gracefully + NSString *timestampString = (timestamp != NULL) ? [NSString stringWithUTF8String:timestamp] : nil; + NSString *messageString = (message != NULL) ? [NSString stringWithUTF8String:message] : nil; + NSString *typeString = (type != NULL) ? [NSString stringWithUTF8String:type] : nil; + NSString *categoryString = (category != NULL) ? [NSString stringWithUTF8String:category] : nil; [SentrySDK configureScope:^(SentryScope *scope) { @@ -91,9 +77,9 @@ void SentryNativeBridgeAddBreadcrumb( category:categoryString]; if (timestampString != nil && timestampString.length > 0) { - NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; - [dateFormatter setDateFormat:NSCalendarIdentifierISO8601]; - breadcrumb.timestamp = [dateFormatter dateFromString:timestampString]; + NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; + formatter.dateFormat = @"yyyy-MM-dd'T'HH:mm:ss'Z'"; + breadcrumb.timestamp = [formatter dateFromString:timestampString]; } if (messageString != nil) { diff --git a/package-dev/Plugins/macOS/SentryNativeBridge.m b/package-dev/Plugins/macOS/SentryNativeBridge.m index a9ba54978..e6387a8de 100644 --- a/package-dev/Plugins/macOS/SentryNativeBridge.m +++ b/package-dev/Plugins/macOS/SentryNativeBridge.m @@ -156,33 +156,22 @@ void SentryNativeBridgeAddBreadcrumb( return; } - NSString *timestampString = nil; - if (timestamp != NULL) { - timestampString = [NSString stringWithUTF8String:timestamp]; - } - - NSString *messageString = nil; - if (message != NULL) { - messageString = [NSString stringWithUTF8String:message]; - } - - NSString *typeString = nil; - if (type != NULL) { - typeString = [NSString stringWithUTF8String:type]; - } - - NSString *categoryString = nil; - if (category != NULL) { - categoryString = [NSString stringWithUTF8String:category]; - } + // Convert C strings to NSStrings, handling invalid UTF-8 gracefully + NSString *timestampString = (timestamp != NULL) ? [NSString stringWithUTF8String:timestamp] : nil; + NSString *messageString = (message != NULL) ? [NSString stringWithUTF8String:message] : nil; + NSString *typeString = (type != NULL) ? [NSString stringWithUTF8String:type] : nil; + NSString *categoryString = (category != NULL) ? [NSString stringWithUTF8String:category] : nil; SentryConfigureScope(^(id scope) { id breadcrumb = [[SentryBreadcrumb alloc] init]; if (timestampString != nil && timestampString.length > 0) { - NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; - [dateFormatter setDateFormat:NSCalendarIdentifierISO8601]; - [breadcrumb setValue:[dateFormatter dateFromString:timestampString] forKey:@"timestamp"]; + NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; + [formatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss'Z'"]; + NSDate *date = [formatter dateFromString:timestampString]; + if (date != nil) { + [breadcrumb setValue:date forKey:@"timestamp"]; + } } if (messageString != nil) { From 42b5fe8e51ab3d288fc26268751867b8a2c28ee9 Mon Sep 17 00:00:00 2001 From: bitsandfoxes Date: Mon, 22 Sep 2025 16:13:15 +0200 Subject: [PATCH 05/13] Updated CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e1370b61d..483ec78c1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ ### Fixes +- Fixed crashes when adding breadcrumbs on iOS/macOS. This was caused by invalid date parsing and corrupted string data in the native bridge responsible for scope sync ([#2327](https://github.com/getsentry/sentry-unity/pull/2327)) - Fixed input handling in samples to work with old and new input system ([#2319](https://github.com/getsentry/sentry-unity/pull/2319)) ### Dependencies From d595a5ae0dee409becb58924c8f5afb9ed0d5a9a Mon Sep 17 00:00:00 2001 From: bitsandfoxes Date: Tue, 23 Sep 2025 11:31:13 +0200 Subject: [PATCH 06/13] Check date format --- package-dev/Plugins/iOS/SentryNativeBridge.m | 2 -- package-dev/Plugins/macOS/SentryNativeBridge.m | 1 - 2 files changed, 3 deletions(-) diff --git a/package-dev/Plugins/iOS/SentryNativeBridge.m b/package-dev/Plugins/iOS/SentryNativeBridge.m index 626bf86ff..ec3afa1af 100644 --- a/package-dev/Plugins/iOS/SentryNativeBridge.m +++ b/package-dev/Plugins/iOS/SentryNativeBridge.m @@ -64,14 +64,12 @@ void SentryNativeBridgeAddBreadcrumb( return; } - // Convert C strings to NSStrings, handling invalid UTF-8 gracefully NSString *timestampString = (timestamp != NULL) ? [NSString stringWithUTF8String:timestamp] : nil; NSString *messageString = (message != NULL) ? [NSString stringWithUTF8String:message] : nil; NSString *typeString = (type != NULL) ? [NSString stringWithUTF8String:type] : nil; NSString *categoryString = (category != NULL) ? [NSString stringWithUTF8String:category] : nil; [SentrySDK configureScope:^(SentryScope *scope) { - SentryBreadcrumb *breadcrumb = [[SentryBreadcrumb alloc] initWithLevel:level category:categoryString]; diff --git a/package-dev/Plugins/macOS/SentryNativeBridge.m b/package-dev/Plugins/macOS/SentryNativeBridge.m index e6387a8de..7c1c10260 100644 --- a/package-dev/Plugins/macOS/SentryNativeBridge.m +++ b/package-dev/Plugins/macOS/SentryNativeBridge.m @@ -156,7 +156,6 @@ void SentryNativeBridgeAddBreadcrumb( return; } - // Convert C strings to NSStrings, handling invalid UTF-8 gracefully NSString *timestampString = (timestamp != NULL) ? [NSString stringWithUTF8String:timestamp] : nil; NSString *messageString = (message != NULL) ? [NSString stringWithUTF8String:message] : nil; NSString *typeString = (type != NULL) ? [NSString stringWithUTF8String:type] : nil; From e8e291200cbcd3a1ef52a2be38054db6a9594b8a Mon Sep 17 00:00:00 2001 From: bitsandfoxes Date: Tue, 23 Sep 2025 12:49:10 +0200 Subject: [PATCH 07/13] Review --- package-dev/Plugins/iOS/SentryNativeBridge.m | 49 +++++++--------- .../Plugins/macOS/SentryNativeBridge.m | 57 ++++++++----------- 2 files changed, 45 insertions(+), 61 deletions(-) diff --git a/package-dev/Plugins/iOS/SentryNativeBridge.m b/package-dev/Plugins/iOS/SentryNativeBridge.m index ec3afa1af..ed97534fe 100644 --- a/package-dev/Plugins/iOS/SentryNativeBridge.m +++ b/package-dev/Plugins/iOS/SentryNativeBridge.m @@ -6,6 +6,18 @@ NS_ASSUME_NONNULL_BEGIN +static NSDateFormatter *_Nullable cachedISO8601Formatter(void) { + static NSDateFormatter *formatter = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + formatter = [[NSDateFormatter alloc] init]; + formatter.dateFormat = @"yyyy-MM-dd'T'HH:mm:ss'Z'"; + formatter.timeZone = [NSTimeZone timeZoneWithAbbreviation:@"UTC"]; + formatter.locale = [NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"]; + }); + return formatter; +} + // macOS only // On iOS, the SDK is linked statically so we don't need to dlopen() it. int SentryNativeBridgeLoadLibrary() { return 1; } @@ -64,10 +76,10 @@ void SentryNativeBridgeAddBreadcrumb( return; } - NSString *timestampString = (timestamp != NULL) ? [NSString stringWithUTF8String:timestamp] : nil; - NSString *messageString = (message != NULL) ? [NSString stringWithUTF8String:message] : nil; - NSString *typeString = (type != NULL) ? [NSString stringWithUTF8String:type] : nil; - NSString *categoryString = (category != NULL) ? [NSString stringWithUTF8String:category] : nil; + NSString *timestampString = _NSStringOrNil(timestamp); + NSString *messageString = _NSStringOrNil(message); + NSString *typeString = _NSStringOrNil(type); + NSString *categoryString = _NSStringOrNil(category) ?: @"default"; // Category cannot be nil [SentrySDK configureScope:^(SentryScope *scope) { SentryBreadcrumb *breadcrumb = [[SentryBreadcrumb alloc] @@ -75,9 +87,7 @@ void SentryNativeBridgeAddBreadcrumb( category:categoryString]; if (timestampString != nil && timestampString.length > 0) { - NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; - formatter.dateFormat = @"yyyy-MM-dd'T'HH:mm:ss'Z'"; - breadcrumb.timestamp = [formatter dateFromString:timestampString]; + breadcrumb.timestamp = [cachedISO8601Formatter() dateFromString:timestampString]; } if (messageString != nil) { @@ -154,26 +164,11 @@ void SentryNativeBridgeSetUser( return; } - NSString *emailString = nil; - if (email != NULL) { - emailString = [NSString stringWithUTF8String:email]; - } - - NSString *userIdString = nil; - if (userId != NULL) { - userIdString = [NSString stringWithUTF8String:userId]; - } - - NSString *ipAddressString = nil; - if (ipAddress != NULL) { - ipAddressString = [NSString stringWithUTF8String:ipAddress]; - } - - NSString *usernameString = nil; - if (username != NULL) { - usernameString = [NSString stringWithUTF8String:username]; - } - + NSString *emailString = (email != NULL) ? [NSString stringWithUTF8String:email] : nil; + NSString *userIdString = (userId != NULL) ? [NSString stringWithUTF8String:userId] : nil; + NSString *ipAddressString = (ipAddress != NULL) ? [NSString stringWithUTF8String:ipAddress] : nil; + NSString *usernameString = (username != NULL) ? [NSString stringWithUTF8String:username] : nil; + [SentrySDK configureScope:^(SentryScope *scope) { SentryUser *user = [[SentryUser alloc] init]; diff --git a/package-dev/Plugins/macOS/SentryNativeBridge.m b/package-dev/Plugins/macOS/SentryNativeBridge.m index 7c1c10260..5d7ddd94e 100644 --- a/package-dev/Plugins/macOS/SentryNativeBridge.m +++ b/package-dev/Plugins/macOS/SentryNativeBridge.m @@ -1,6 +1,18 @@ #import #include +static NSDateFormatter *_Nullable cachedISO8601Formatter(void) { + static NSDateFormatter *formatter = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + formatter = [[NSDateFormatter alloc] init]; + [formatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss'Z'"]; + formatter.timeZone = [NSTimeZone timeZoneWithAbbreviation:@"UTC"]; + formatter.locale = [NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"]; + }); + return formatter; +} + static int loadStatus = -1; // unitialized static Class SentrySDK; @@ -156,18 +168,16 @@ void SentryNativeBridgeAddBreadcrumb( return; } - NSString *timestampString = (timestamp != NULL) ? [NSString stringWithUTF8String:timestamp] : nil; - NSString *messageString = (message != NULL) ? [NSString stringWithUTF8String:message] : nil; - NSString *typeString = (type != NULL) ? [NSString stringWithUTF8String:type] : nil; - NSString *categoryString = (category != NULL) ? [NSString stringWithUTF8String:category] : nil; + NSString *timestampString = _NSStringOrNil(timestamp): + NSString *messageString = _NSStringOrNil(message): + NSString *typeString = _NSStringOrNil(type); + NSString *categoryString = _NSStringOrNil(category) ?: @"default"; // Category cannot be nil SentryConfigureScope(^(id scope) { id breadcrumb = [[SentryBreadcrumb alloc] init]; if (timestampString != nil && timestampString.length > 0) { - NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; - [formatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss'Z'"]; - NSDate *date = [formatter dateFromString:timestampString]; + NSDate *date = [cachedISO8601Formatter() dateFromString:timestampString]; if (date != nil) { [breadcrumb setValue:date forKey:@"timestamp"]; } @@ -198,10 +208,7 @@ void SentryNativeBridgeSetExtra(const char *key, const char *value) } NSString *keyString = [NSString stringWithUTF8String:key]; - NSString *valueString = nil; - if (value != NULL) { - valueString = [NSString stringWithUTF8String:value]; - } + NSString *valueString = _NSStringOrNil(value); SentryConfigureScope(^(id scope) { if (valueString != nil) { @@ -222,10 +229,7 @@ void SentryNativeBridgeSetTag(const char *key, const char *value) } NSString *keyString = [NSString stringWithUTF8String:key]; - NSString *valueString = nil; - if (value != NULL) { - valueString = [NSString stringWithUTF8String:value]; - } + NSString *valueString = _NSStringOrNil(value); SentryConfigureScope(^(id scope) { if (valueString != nil) { @@ -259,25 +263,10 @@ void SentryNativeBridgeSetUser( return; } - NSString *emailString = nil; - if (email != NULL) { - emailString = [NSString stringWithUTF8String:email]; - } - - NSString *userIdString = nil; - if (userId != NULL) { - userIdString = [NSString stringWithUTF8String:userId]; - } - - NSString *ipAddressString = nil; - if (ipAddress != NULL) { - ipAddressString = [NSString stringWithUTF8String:ipAddress]; - } - - NSString *usernameString = nil; - if (username != NULL) { - usernameString = [NSString stringWithUTF8String:username]; - } + NSString *emailString _NSStringOrNil(email); + NSString *userIdString = _NSStringOrNil(userId); + NSString *ipAddressString = _NSStringOrNil(ipAddress); + NSString *usernameString = _NSStringOrNil(username); SentryConfigureScope(^(id scope) { id user = [[SentryUser alloc] init]; From d4fec6a855ee82d8d94b42b9a7ea3b6ead096bc5 Mon Sep 17 00:00:00 2001 From: bitsandfoxes Date: Tue, 23 Sep 2025 14:21:02 +0200 Subject: [PATCH 08/13] Stuff needs to go on top --- package-dev/Plugins/iOS/SentryNativeBridge.m | 42 +++++++++---------- .../Plugins/macOS/SentryNativeBridge.m | 42 +++++++++---------- 2 files changed, 42 insertions(+), 42 deletions(-) diff --git a/package-dev/Plugins/iOS/SentryNativeBridge.m b/package-dev/Plugins/iOS/SentryNativeBridge.m index ed97534fe..68f424b25 100644 --- a/package-dev/Plugins/iOS/SentryNativeBridge.m +++ b/package-dev/Plugins/iOS/SentryNativeBridge.m @@ -18,6 +18,27 @@ return formatter; } +static inline NSString *_NSStringOrNil(const char *value) +{ + return value ? [NSString stringWithUTF8String:value] : nil; +} + +static inline NSNumber *_NSNumberOrNil(int32_t value) +{ + return value == 0 ? nil : @(value); +} + +static inline NSNumber *_NSBoolOrNil(int8_t value) +{ + if (value == 0) { + return @NO; + } + if (value == 1) { + return @YES; + } + return nil; +} + // macOS only // On iOS, the SDK is linked statically so we don't need to dlopen() it. int SentryNativeBridgeLoadLibrary() { return 1; } @@ -231,27 +252,6 @@ void SentryNativeBridgeSetTrace(const char *traceId, const char *spanId) } } -static inline NSString *_NSStringOrNil(const char *value) -{ - return value ? [NSString stringWithUTF8String:value] : nil; -} - -static inline NSNumber *_NSNumberOrNil(int32_t value) -{ - return value == 0 ? nil : @(value); -} - -static inline NSNumber *_NSBoolOrNil(int8_t value) -{ - if (value == 0) { - return @NO; - } - if (value == 1) { - return @YES; - } - return nil; -} - void SentryNativeBridgeWriteScope( // clang-format off // // const char *AppStartTime, // const char *AppBuildType, diff --git a/package-dev/Plugins/macOS/SentryNativeBridge.m b/package-dev/Plugins/macOS/SentryNativeBridge.m index 5d7ddd94e..9527418cd 100644 --- a/package-dev/Plugins/macOS/SentryNativeBridge.m +++ b/package-dev/Plugins/macOS/SentryNativeBridge.m @@ -13,6 +13,27 @@ return formatter; } +static inline NSString *_NSStringOrNil(const char *value) +{ + return value ? [NSString stringWithUTF8String:value] : nil; +} + +static inline NSString *_NSNumberOrNil(int32_t value) +{ + return value == 0 ? nil : @(value); +} + +static inline NSNumber *_NSBoolOrNil(int8_t value) +{ + if (value == 0) { + return @NO; + } + if (value == 1) { + return @YES; + } + return nil; +} + static int loadStatus = -1; // unitialized static Class SentrySDK; @@ -329,27 +350,6 @@ void SentryNativeBridgeSetTrace(const char *traceId, const char *spanId) withObject:sentrySpanId]; } -static inline NSString *_NSStringOrNil(const char *value) -{ - return value ? [NSString stringWithUTF8String:value] : nil; -} - -static inline NSString *_NSNumberOrNil(int32_t value) -{ - return value == 0 ? nil : @(value); -} - -static inline NSNumber *_NSBoolOrNil(int8_t value) -{ - if (value == 0) { - return @NO; - } - if (value == 1) { - return @YES; - } - return nil; -} - void SentryNativeBridgeWriteScope( // clang-format off // // const char *AppStartTime, // const char *AppBuildType, From 9530584b38b325b698f2892c0c3bc5b021d135b8 Mon Sep 17 00:00:00 2001 From: bitsandfoxes Date: Tue, 23 Sep 2025 16:45:47 +0200 Subject: [PATCH 09/13] Review, extensive cleanup --- package-dev/Plugins/iOS/SentryNativeBridge.m | 57 +++++-------------- .../Plugins/macOS/SentryNativeBridge.m | 43 +++----------- 2 files changed, 23 insertions(+), 77 deletions(-) diff --git a/package-dev/Plugins/iOS/SentryNativeBridge.m b/package-dev/Plugins/iOS/SentryNativeBridge.m index 68f424b25..be28d5a6d 100644 --- a/package-dev/Plugins/iOS/SentryNativeBridge.m +++ b/package-dev/Plugins/iOS/SentryNativeBridge.m @@ -6,7 +6,7 @@ NS_ASSUME_NONNULL_BEGIN -static NSDateFormatter *_Nullable cachedISO8601Formatter(void) { +static NSDateFormatter *_Nullable sentry_cachedISO8601Formatter(void) { static NSDateFormatter *formatter = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ @@ -108,7 +108,7 @@ void SentryNativeBridgeAddBreadcrumb( category:categoryString]; if (timestampString != nil && timestampString.length > 0) { - breadcrumb.timestamp = [cachedISO8601Formatter() dateFromString:timestampString]; + breadcrumb.timestamp = [sentry_cachedISO8601Formatter() dateFromString:timestampString]; } if (messageString != nil) { @@ -130,17 +130,10 @@ void SentryNativeBridgeSetExtra(const char *key, const char *value) } NSString *keyString = [NSString stringWithUTF8String:key]; - NSString *valueString = nil; - if (value != NULL) { - valueString = [NSString stringWithUTF8String:value]; - } + NSString *valueString = _NSStringOrNil(value); [SentrySDK configureScope:^(SentryScope *scope) { - if (valueString != nil) { - [scope setExtraValue:valueString forKey:keyString]; - } else { - [scope removeExtraForKey:keyString]; - } + [scope setExtraValue:valueString forKey:keyString]; }]; } @@ -151,17 +144,10 @@ void SentryNativeBridgeSetTag(const char *key, const char *value) } NSString *keyString = [NSString stringWithUTF8String:key]; - NSString *valueString = nil; - if (value != NULL) { - valueString = [NSString stringWithUTF8String:value]; - } + NSString *valueString = _NSStringOrNil(value); [SentrySDK configureScope:^(SentryScope *scope) { - if (valueString != nil) { - [scope setTagValue:valueString forKey:keyString]; - } else { - [scope removeTagForKey:keyString]; - } + [scope setTagValue:valueString forKey:keyString]; }]; } @@ -181,33 +167,18 @@ void SentryNativeBridgeUnsetTag(const char *key) void SentryNativeBridgeSetUser( const char *email, const char *userId, const char *ipAddress, const char *username) { - if (email == NULL && userId == NULL && ipAddress == NULL && username == NULL) { - return; - } - - NSString *emailString = (email != NULL) ? [NSString stringWithUTF8String:email] : nil; - NSString *userIdString = (userId != NULL) ? [NSString stringWithUTF8String:userId] : nil; - NSString *ipAddressString = (ipAddress != NULL) ? [NSString stringWithUTF8String:ipAddress] : nil; - NSString *usernameString = (username != NULL) ? [NSString stringWithUTF8String:username] : nil; + NSString *emailString = _NSStringOrNil(email); + NSString *userIdString = _NSStringOrNil(userId); + NSString *ipAddressString = _NSStringOrNil(ipAddress); + NSString *usernameString = _NSStringOrNil(username); [SentrySDK configureScope:^(SentryScope *scope) { SentryUser *user = [[SentryUser alloc] init]; - if (emailString != nil) { - user.email = emailString; - } - - if (userIdString != nil) { - user.userId = userIdString; - } - - if (ipAddressString != nil) { - user.ipAddress = ipAddressString; - } - - if (usernameString != nil) { - user.username = usernameString; - } + user.email = emailString; + user.userId = userIdString; + user.ipAddress = ipAddressString; + user.username = usernameString; [scope setUser:user]; }]; diff --git a/package-dev/Plugins/macOS/SentryNativeBridge.m b/package-dev/Plugins/macOS/SentryNativeBridge.m index 9527418cd..1deab6a2b 100644 --- a/package-dev/Plugins/macOS/SentryNativeBridge.m +++ b/package-dev/Plugins/macOS/SentryNativeBridge.m @@ -1,7 +1,7 @@ #import #include -static NSDateFormatter *_Nullable cachedISO8601Formatter(void) { +static NSDateFormatter *_Nullable sentry_cachedISO8601Formatter(void) { static NSDateFormatter *formatter = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ @@ -198,7 +198,7 @@ void SentryNativeBridgeAddBreadcrumb( id breadcrumb = [[SentryBreadcrumb alloc] init]; if (timestampString != nil && timestampString.length > 0) { - NSDate *date = [cachedISO8601Formatter() dateFromString:timestampString]; + NSDate *date = [sentry_cachedISO8601Formatter() dateFromString:timestampString]; if (date != nil) { [breadcrumb setValue:date forKey:@"timestamp"]; } @@ -232,14 +232,9 @@ void SentryNativeBridgeSetExtra(const char *key, const char *value) NSString *valueString = _NSStringOrNil(value); SentryConfigureScope(^(id scope) { - if (valueString != nil) { - [scope performSelector:@selector(setExtraValue:forKey:) + [scope performSelector:@selector(setExtraValue:forKey:) withObject:valueString withObject:keyString]; - } else { - [scope performSelector:@selector(removeExtraForKey:) - withObject:keyString]; - } }); } @@ -253,14 +248,9 @@ void SentryNativeBridgeSetTag(const char *key, const char *value) NSString *valueString = _NSStringOrNil(value); SentryConfigureScope(^(id scope) { - if (valueString != nil) { - [scope performSelector:@selector(setTagValue:forKey:) + [scope performSelector:@selector(setTagValue:forKey:) withObject:valueString withObject:keyString]; - } else { - [scope performSelector:@selector(removeTagForKey:) - withObject:keyString]; - } }); } @@ -280,10 +270,6 @@ void SentryNativeBridgeUnsetTag(const char *key) void SentryNativeBridgeSetUser( const char *email, const char *userId, const char *ipAddress, const char *username) { - if (email == NULL && userId == NULL && ipAddress == NULL && username == NULL) { - return; - } - NSString *emailString _NSStringOrNil(email); NSString *userIdString = _NSStringOrNil(userId); NSString *ipAddressString = _NSStringOrNil(ipAddress); @@ -292,22 +278,11 @@ void SentryNativeBridgeSetUser( SentryConfigureScope(^(id scope) { id user = [[SentryUser alloc] init]; - if (emailString != nil) { - [user setValue:emailString forKey:@"email"]; - } - - if (userIdString != nil) { - [user setValue:userIdString forKey:@"userId"]; - } - - if (ipAddressString != nil) { - [user setValue:ipAddressString forKey:@"ipAddress"]; - } - - if (usernameString != nil) { - [user setValue:usernameString forKey:@"username"]; - } - + [user setValue:emailString forKey:@"email"]; + [user setValue:userIdString forKey:@"userId"]; + [user setValue:ipAddressString forKey:@"ipAddress"]; + [user setValue:usernameString forKey:@"username"]; + [scope performSelector:@selector(setUser:) withObject:user]; }); } From b380c68b9163646a2adedf9becb837e0f18b21ef Mon Sep 17 00:00:00 2001 From: bitsandfoxes Date: Wed, 24 Sep 2025 10:14:17 +0200 Subject: [PATCH 10/13] Added context removal to the smoke test --- .../Scripts/SmokeTester.cs | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/test/Scripts.Integration.Test/Scripts/SmokeTester.cs b/test/Scripts.Integration.Test/Scripts/SmokeTester.cs index 8879f4fed..d7474886a 100644 --- a/test/Scripts.Integration.Test/Scripts/SmokeTester.cs +++ b/test/Scripts.Integration.Test/Scripts/SmokeTester.cs @@ -189,6 +189,26 @@ private IEnumerator SmokeTestCoroutine() t.ExpectMessage(currentMessage, "'filename':'screenshot.jpg','attachment_type':'event.attachment'"); t.ExpectMessageNot(currentMessage, "'length':0"); + var ex = new Exception("Exception & removed context test"); + RemoveContext(); + SentrySdk.CaptureException(ex); + + // Wait for screenshot capture to complete + yield return null; + + currentMessage++; // The exception event + + t.ExpectMessage(currentMessage, "'type':'event'"); + t.ExpectMessageNot(currentMessage, "'extra':{'extra-key':42}"); + t.ExpectMessageNot(currentMessage, "'tag-key':'tag-value'"); + t.ExpectMessageNot(currentMessage, "'user':{"); + t.ExpectMessageNot(currentMessage, "'length':0"); + + currentMessage++; // The screenshot envelope + + t.ExpectMessage(currentMessage, "'filename':'screenshot.jpg','attachment_type':'event.attachment'"); + t.ExpectMessageNot(currentMessage, "'length':0"); + Debug.Log("Finished checking messages."); t.Pass(); @@ -251,6 +271,22 @@ private static void AddContext() }); } + private static void RemoveContext() + { + SentrySdk.ConfigureScope((Scope scope) => + { + scope.SetExtra("extra-key", null); + scope.UnsetTag("tag-key"); + scope.User = new SentryUser + { + Username = null, + Email = null, + IpAddress = null, + Id = null, + }; + }); + } + // CppPlugin.cpp [DllImport("__Internal")] private static extern void throw_cpp(); From 60a2036c6e0ee076e0a3fdb32be6587f07c1a8fc Mon Sep 17 00:00:00 2001 From: bitsandfoxes Date: Wed, 24 Sep 2025 10:30:35 +0200 Subject: [PATCH 11/13] Fixed variable error --- test/Scripts.Integration.Test/Scripts/SmokeTester.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Scripts.Integration.Test/Scripts/SmokeTester.cs b/test/Scripts.Integration.Test/Scripts/SmokeTester.cs index d7474886a..85e5e4055 100644 --- a/test/Scripts.Integration.Test/Scripts/SmokeTester.cs +++ b/test/Scripts.Integration.Test/Scripts/SmokeTester.cs @@ -189,7 +189,7 @@ private IEnumerator SmokeTestCoroutine() t.ExpectMessage(currentMessage, "'filename':'screenshot.jpg','attachment_type':'event.attachment'"); t.ExpectMessageNot(currentMessage, "'length':0"); - var ex = new Exception("Exception & removed context test"); + ex = new Exception("Exception & removed context test"); RemoveContext(); SentrySdk.CaptureException(ex); From 8d5269a4e90ff1475ba23d6bc3a361fdf6763b26 Mon Sep 17 00:00:00 2001 From: bitsandfoxes Date: Wed, 24 Sep 2025 11:47:04 +0200 Subject: [PATCH 12/13] Fixed compiler issues --- package-dev/Plugins/macOS/SentryNativeBridge.m | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package-dev/Plugins/macOS/SentryNativeBridge.m b/package-dev/Plugins/macOS/SentryNativeBridge.m index 1deab6a2b..f8845abef 100644 --- a/package-dev/Plugins/macOS/SentryNativeBridge.m +++ b/package-dev/Plugins/macOS/SentryNativeBridge.m @@ -189,8 +189,8 @@ void SentryNativeBridgeAddBreadcrumb( return; } - NSString *timestampString = _NSStringOrNil(timestamp): - NSString *messageString = _NSStringOrNil(message): + NSString *timestampString = _NSStringOrNil(timestamp); + NSString *messageString = _NSStringOrNil(message); NSString *typeString = _NSStringOrNil(type); NSString *categoryString = _NSStringOrNil(category) ?: @"default"; // Category cannot be nil @@ -270,7 +270,7 @@ void SentryNativeBridgeUnsetTag(const char *key) void SentryNativeBridgeSetUser( const char *email, const char *userId, const char *ipAddress, const char *username) { - NSString *emailString _NSStringOrNil(email); + NSString *emailString = _NSStringOrNil(email); NSString *userIdString = _NSStringOrNil(userId); NSString *ipAddressString = _NSStringOrNil(ipAddress); NSString *usernameString = _NSStringOrNil(username); From d2ec80781d59e7ebcdd5d753e6213392a320a0e4 Mon Sep 17 00:00:00 2001 From: bitsandfoxes Date: Wed, 24 Sep 2025 12:56:32 +0200 Subject: [PATCH 13/13] Fixed expected user in SmokeTester --- test/Scripts.Integration.Test/Scripts/SmokeTester.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Scripts.Integration.Test/Scripts/SmokeTester.cs b/test/Scripts.Integration.Test/Scripts/SmokeTester.cs index b1ac2cbc5..1cbf56009 100644 --- a/test/Scripts.Integration.Test/Scripts/SmokeTester.cs +++ b/test/Scripts.Integration.Test/Scripts/SmokeTester.cs @@ -207,7 +207,7 @@ private IEnumerator SmokeTestCoroutine() t.ExpectMessage(currentMessage, "'type':'event'"); t.ExpectMessageNot(currentMessage, "'extra':{'extra-key':42}"); t.ExpectMessageNot(currentMessage, "'tag-key':'tag-value'"); - t.ExpectMessageNot(currentMessage, "'user':{"); + t.ExpectMessageNot(currentMessage, "user-id"); t.ExpectMessageNot(currentMessage, "'length':0"); currentMessage++; // The screenshot envelope