From de749526db62a315afd1ffe4cc066a65ccdf2519 Mon Sep 17 00:00:00 2001 From: Philipp Hofmann Date: Mon, 5 Aug 2024 09:36:43 +0200 Subject: [PATCH 1/4] fix: Missing mach info for crash reports The SentryInternalCDefines didn't define the SENTRY_HOST_APPLE, which led to missing mach info for crash reports, as the SentryCrashReport relies on the SENTRY_HOST_APPLE to write that info. For reference, the SentryCrashCRASH_HOST_APPLE was changed to SENTRY_HOST_APPLE in GH-4101. The problem is fixed now by defining SENTRY_HOST_APPLE in SentryInternalCDefines. Fixes GH-4227 --- CHANGELOG.md | 2 + .../Sentry/include/SentryInternalCDefines.h | 4 ++ .../SentryCrash/SentryCrashReportTests.swift | 52 +++++++++++++++++-- .../SentryKSCrashReportConverterTests.m | 3 ++ 4 files changed, 57 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 974dd6ff7fc..2529df68c2c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,8 @@ - Skip UI crumbs when target or sender is nil (#4211) - Guard FramesTracker start and stop (#4224) - Long-lasting TTID/TTFD spans (#4225). Avoid long TTID spans when the FrameTracker isn't running, which is the case when the app is in the background. +- Missing mach info for crash reports (#4230) + ### Improvements diff --git a/Sources/Sentry/include/SentryInternalCDefines.h b/Sources/Sentry/include/SentryInternalCDefines.h index 4b6144c6b76..c62290443d3 100644 --- a/Sources/Sentry/include/SentryInternalCDefines.h +++ b/Sources/Sentry/include/SentryInternalCDefines.h @@ -40,6 +40,10 @@ typedef unsigned long long bytes; #include +#ifdef __APPLE__ +# define SENTRY_HOST_APPLE 1 +#endif + #ifndef TARGET_OS_VISION # define TARGET_OS_VISION 0 #endif diff --git a/Tests/SentryTests/Integrations/SentryCrash/SentryCrashReportTests.swift b/Tests/SentryTests/Integrations/SentryCrash/SentryCrashReportTests.swift index fc8cd009605..4a363faabee 100644 --- a/Tests/SentryTests/Integrations/SentryCrash/SentryCrashReportTests.swift +++ b/Tests/SentryTests/Integrations/SentryCrash/SentryCrashReportTests.swift @@ -117,13 +117,48 @@ class SentryCrashReportTests: XCTestCase { XCTAssertFalse(crashReportContentsAsString.contains("boot_time"), "The crash report must not contain boot_time because Apple forbids sending this information off device see: https://developer.apple.com/documentation/bundleresources/privacy_manifest_files/describing_use_of_required_reason_api#4278394.") } - private func writeCrashReport() { + func testCrashReportContainsMachInfo() throws { + var monitorContext = SentryCrash_MonitorContext() + monitorContext.mach.type = EXC_BAD_ACCESS + monitorContext.mach.code = 1 + monitorContext.mach.subcode = 12 - let api = sentrycrashcm_system_getAPI() - api?.pointee.addContextualInfoToEvent(&monitorContext) + writeCrashReport(monitorContext: monitorContext) - sentrycrashreport_writeStandardReport(&monitorContext, fixture.reportPath) + let crashReportContents = try XCTUnwrap( FileManager.default.contents(atPath: fixture.reportPath)) + + let crashReport: CrashReport = try JSONDecoder().decode(CrashReport.self, from: crashReportContents) + + let mach = try XCTUnwrap(crashReport.crash.error.mach) + XCTAssertEqual(1, mach.exception) + XCTAssertEqual("EXC_BAD_ACCESS", mach.exception_name) + XCTAssertEqual(1, mach.code) + XCTAssertEqual("KERN_INVALID_ADDRESS", mach.code_name) + XCTAssertEqual(12, mach.subcode) + } + + func testCrashReportContainsStandardMachInfo_WhenMachInfoIsEmpty() throws { + writeCrashReport() + + let crashReportContents = try XCTUnwrap( FileManager.default.contents(atPath: fixture.reportPath)) + + let crashReport: CrashReport = try JSONDecoder().decode(CrashReport.self, from: crashReportContents) + + let mach = try XCTUnwrap(crashReport.crash.error.mach) + XCTAssertEqual(0, mach.exception) + XCTAssertNil(mach.exception_name) + XCTAssertEqual(0, mach.code) + XCTAssertNil(mach.code_name) + XCTAssertEqual(0, mach.subcode) + } + + private func writeCrashReport(monitorContext: SentryCrash_MonitorContext? = nil) { + var localMonitorContext = monitorContext ?? SentryCrash_MonitorContext() + + let api = sentrycrashcm_system_getAPI() + api?.pointee.addContextualInfoToEvent(&localMonitorContext) + sentrycrashreport_writeStandardReport(&localMonitorContext, fixture.reportPath) } /** @@ -167,6 +202,7 @@ class SentryCrashReportTests: XCTestCase { let type: String? let reason: String? let nsexception: NSException? + let mach: Mach? } struct NSException: Decodable, Equatable { @@ -174,6 +210,14 @@ class SentryCrashReportTests: XCTestCase { let userInfo: String? let reason: String? } + + struct Mach: Decodable, Equatable { + let exception: Int? + let exception_name: String? + let code: Int? + let code_name: String? + let subcode: Int? + } struct CrashReportUserInfo: Decodable, Equatable { let user: CrashReportUser? diff --git a/Tests/SentryTests/SentryKSCrashReportConverterTests.m b/Tests/SentryTests/SentryKSCrashReportConverterTests.m index b8d7dcb253a..57fd2164201 100644 --- a/Tests/SentryTests/SentryKSCrashReportConverterTests.m +++ b/Tests/SentryTests/SentryKSCrashReportConverterTests.m @@ -75,11 +75,14 @@ - (void)testConvertReport stringWithFormat:@"%@", [exception.mechanism.meta.signal valueForKeyPath:@"number"]]; NSString *exc = [NSString stringWithFormat:@"%@", [exception.mechanism.meta.machException valueForKeyPath:@"name"]]; + XCTAssertEqualObjects(code, @"0"); XCTAssertEqualObjects(number, @"10"); XCTAssertEqualObjects(exc, @"EXC_BAD_ACCESS"); XCTAssertEqualObjects( [exception.mechanism.data valueForKeyPath:@"relevant_address"], @"0x0000000102468000"); + XCTAssertNotNil(exception.mechanism.handled); + XCTAssertFalse(exception.mechanism.handled.boolValue); XCTAssertTrue([NSJSONSerialization isValidJSONObject:[event serialize]]); XCTAssertNotNil([[event serialize] valueForKeyPath:@"exception.values"]); From f67e61a8fbb6a1942635fc877212c1d042336403 Mon Sep 17 00:00:00 2001 From: Philipp Hofmann Date: Mon, 5 Aug 2024 10:07:04 +0200 Subject: [PATCH 2/4] fix tests --- .../SentryCrash/SentryCrashReportTests.swift | 9 --------- 1 file changed, 9 deletions(-) diff --git a/Tests/SentryTests/Integrations/SentryCrash/SentryCrashReportTests.swift b/Tests/SentryTests/Integrations/SentryCrash/SentryCrashReportTests.swift index 4a363faabee..a308f00c2a0 100644 --- a/Tests/SentryTests/Integrations/SentryCrash/SentryCrashReportTests.swift +++ b/Tests/SentryTests/Integrations/SentryCrash/SentryCrashReportTests.swift @@ -220,7 +220,6 @@ class SentryCrashReportTests: XCTestCase { } struct CrashReportUserInfo: Decodable, Equatable { - let user: CrashReportUser? let dist: String? let context: [String: [String: String]]? let environment: String? @@ -231,14 +230,6 @@ class SentryCrashReportTests: XCTestCase { let breadcrumbs: [CrashReportCrumb]? } - struct CrashReportUser: Decodable, Equatable { - let id: String - let email: String - let username: String - let ip_address: String - let data: [String: [String: String]] - } - struct CrashReportCrumb: Decodable, Equatable { let category: String let data: [String: [String: String]] From f8a43bd8a6f30f019dbb86d43cd3374066082864 Mon Sep 17 00:00:00 2001 From: Philipp Hofmann Date: Mon, 5 Aug 2024 10:20:35 +0200 Subject: [PATCH 3/4] again fix --- .../Integrations/SentryCrash/SentryCrashReportTests.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Tests/SentryTests/Integrations/SentryCrash/SentryCrashReportTests.swift b/Tests/SentryTests/Integrations/SentryCrash/SentryCrashReportTests.swift index a308f00c2a0..c4c1fe7a2d7 100644 --- a/Tests/SentryTests/Integrations/SentryCrash/SentryCrashReportTests.swift +++ b/Tests/SentryTests/Integrations/SentryCrash/SentryCrashReportTests.swift @@ -189,8 +189,8 @@ class SentryCrashReportTests: XCTestCase { // We parse JSON so it's fine to disable identifier_name // swiftlint:disable identifier_name struct CrashReport: Decodable { - let user: CrashReportUserInfo - let sentry_sdk_scope: CrashReportUserInfo + let user: CrashReportUserInfo? + let sentry_sdk_scope: CrashReportUserInfo? let crash: Crash } From 861f7a8f05f9bac44e4ac9b9a684e14141926b1d Mon Sep 17 00:00:00 2001 From: Philipp Hofmann Date: Mon, 5 Aug 2024 10:44:43 +0200 Subject: [PATCH 4/4] try again --- .../SentryCrash/SentryCrashReportTests.swift | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Tests/SentryTests/Integrations/SentryCrash/SentryCrashReportTests.swift b/Tests/SentryTests/Integrations/SentryCrash/SentryCrashReportTests.swift index c4c1fe7a2d7..e1d6e8c56b6 100644 --- a/Tests/SentryTests/Integrations/SentryCrash/SentryCrashReportTests.swift +++ b/Tests/SentryTests/Integrations/SentryCrash/SentryCrashReportTests.swift @@ -118,6 +118,7 @@ class SentryCrashReportTests: XCTestCase { } func testCrashReportContainsMachInfo() throws { + serializeToCrashReport(scope: fixture.scope) var monitorContext = SentryCrash_MonitorContext() monitorContext.mach.type = EXC_BAD_ACCESS @@ -139,6 +140,7 @@ class SentryCrashReportTests: XCTestCase { } func testCrashReportContainsStandardMachInfo_WhenMachInfoIsEmpty() throws { + serializeToCrashReport(scope: fixture.scope) writeCrashReport() let crashReportContents = try XCTUnwrap( FileManager.default.contents(atPath: fixture.reportPath)) @@ -220,6 +222,7 @@ class SentryCrashReportTests: XCTestCase { } struct CrashReportUserInfo: Decodable, Equatable { + let user: CrashReportUser? let dist: String? let context: [String: [String: String]]? let environment: String? @@ -229,6 +232,14 @@ class SentryCrashReportTests: XCTestCase { let level: String? let breadcrumbs: [CrashReportCrumb]? } + + struct CrashReportUser: Decodable, Equatable { + let id: String + let email: String + let username: String + let ip_address: String + let data: [String: [String: String]] + } struct CrashReportCrumb: Decodable, Equatable { let category: String