diff --git a/.jazzy.yaml b/.jazzy.yaml index 07ab0cea5..846ce00c0 100644 --- a/.jazzy.yaml +++ b/.jazzy.yaml @@ -2,11 +2,11 @@ author_url: "https://www.bugsnag.com" author: "Bugsnag Inc" clean: false # avoid deleting docs/.git framework_root: "Bugsnag" -github_file_prefix: "https://github.com/bugsnag/bugsnag-cocoa/tree/v6.24.0/Bugsnag" +github_file_prefix: "https://github.com/bugsnag/bugsnag-cocoa/tree/v6.25.0/Bugsnag" github_url: "https://github.com/bugsnag/bugsnag-cocoa" hide_documentation_coverage: true module: "Bugsnag" -module_version: "6.24.0" +module_version: "6.25.0" objc: true output: "docs" readme: "README.md" diff --git a/Bugsnag.podspec.json b/Bugsnag.podspec.json index dbbfd435c..1150f13b1 100644 --- a/Bugsnag.podspec.json +++ b/Bugsnag.podspec.json @@ -1,6 +1,6 @@ { "name": "Bugsnag", - "version": "6.24.0", + "version": "6.25.0", "summary": "The Bugsnag crash reporting framework for Apple platforms.", "homepage": "https://bugsnag.com", "license": "MIT", @@ -9,7 +9,7 @@ }, "source": { "git": "https://github.com/bugsnag/bugsnag-cocoa.git", - "tag": "v6.24.0" + "tag": "v6.25.0" }, "ios": { "frameworks": [ diff --git a/Bugsnag.xcconfig b/Bugsnag.xcconfig index 97d351c86..986dd44c0 100644 --- a/Bugsnag.xcconfig +++ b/Bugsnag.xcconfig @@ -89,6 +89,17 @@ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES // -Wimplicit-retai CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES // -Warc-repeated-use-of-weak -Wno-arc-maybe-repeated-use-of-weak CLANG_WARN__ARC_BRIDGE_CAST_NONARC = YES // -Warc-bridge-casts-disallowed-in-nonarc +// Static Analysis - Issues - Security + +CLANG_ANALYZER_SECURITY_FLOATLOOPCOUNTER = YES +CLANG_ANALYZER_SECURITY_INSECUREAPI_RAND = YES +CLANG_ANALYZER_SECURITY_INSECUREAPI_STRCPY = YES + +// Static Analysis - Issues - Unused Code + +CLANG_TIDY_BUGPRONE_REDUNDANT_BRANCH_CONDITION = YES +CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES + // Warning flags that have no dedicated Xcode build settings WARNING_CFLAGS = -Wcast-qual -Wconditional-uninitialized -Wcustom-atomic-properties -Wdirect-ivar-access -Wdocumentation-unknown-command -Wformat-nonliteral -Widiomatic-parentheses -Wimplicit-int-float-conversion -Wimport-preprocessor-directive-pedantic -Wincomplete-implementation -Wmissing-variable-declarations -Wno-unknown-warning-option -Wnonportable-include-path -Wnullable-to-nonnull-conversion -Woverriding-method-mismatch -Wpointer-sign -Wswitch-enum -Wundef -Wunused-macros diff --git a/Bugsnag/Client/BugsnagClient.m b/Bugsnag/Client/BugsnagClient.m index d78931ad8..9c3297dfc 100644 --- a/Bugsnag/Client/BugsnagClient.m +++ b/Bugsnag/Client/BugsnagClient.m @@ -150,7 +150,7 @@ static void BSSerializeDataCrashHandler(const BSG_KSCrashReportWriter *writer) { // MARK: - BSG_OBJC_DIRECT_MEMBERS -@interface BugsnagClient () +@interface BugsnagClient () @property (nonatomic) BSGNotificationBreadcrumbs *notificationBreadcrumbs; @@ -246,7 +246,9 @@ - (void)start { [self computeDidCrashLastLaunch]; if (self.configuration.telemetry & BSGTelemetryInternalErrors) { - BSGInternalErrorReporter.sharedInstance = [[BSGInternalErrorReporter alloc] initWithDataSource:self]; + BSGInternalErrorReporter.sharedInstance = + [[BSGInternalErrorReporter alloc] initWithApiKey:self.configuration.apiKey + endpoint:(NSURL *_Nonnull)self.configuration.notifyURL]; } else { bsg_log_debug(@"Internal error reporting was disabled in config"); } diff --git a/Bugsnag/Helpers/BSGInternalErrorReporter.h b/Bugsnag/Helpers/BSGInternalErrorReporter.h index 9613c31f8..eab37a9d0 100644 --- a/Bugsnag/Helpers/BSGInternalErrorReporter.h +++ b/Bugsnag/Helpers/BSGInternalErrorReporter.h @@ -10,11 +10,7 @@ #import "BSGDefines.h" -@class BugsnagAppWithState; -@class BugsnagConfiguration; -@class BugsnagDeviceWithState; @class BugsnagEvent; -@class BugsnagNotifier; NS_ASSUME_NONNULL_BEGIN @@ -23,18 +19,6 @@ NSString *_Nullable BSGErrorDescription(NSError *_Nullable error); // MARK: - -@protocol BSGInternalErrorReporterDataSource - -@property (readonly, nonatomic) BugsnagConfiguration *configuration; - -- (BugsnagAppWithState *)generateAppWithState:(NSDictionary *)systemInfo; - -- (BugsnagDeviceWithState *)generateDeviceWithState:(NSDictionary *)systemInfo; - -@end - -// MARK: - - BSG_OBJC_DIRECT_MEMBERS @interface BSGInternalErrorReporter : NSObject @@ -43,7 +27,7 @@ BSG_OBJC_DIRECT_MEMBERS /// Runs the block immediately if sharedInstance exists, otherwise runs the block once sharedInstance has been created. + (void)performBlock:(void (^)(BSGInternalErrorReporter *))block; -- (instancetype)initWithDataSource:(id)dataSource NS_DESIGNATED_INITIALIZER; +- (instancetype)initWithApiKey:(NSString *)apiKey endpoint:(NSURL *)endpoint NS_DESIGNATED_INITIALIZER; - (instancetype)init UNAVAILABLE_ATTRIBUTE; diff --git a/Bugsnag/Helpers/BSGInternalErrorReporter.m b/Bugsnag/Helpers/BSGInternalErrorReporter.m index df1bb6dc7..73ee47346 100644 --- a/Bugsnag/Helpers/BSGInternalErrorReporter.m +++ b/Bugsnag/Helpers/BSGInternalErrorReporter.m @@ -11,13 +11,9 @@ #import "BSGKeys.h" #import "BSG_KSCrashReportFields.h" #import "BSG_KSSysCtl.h" -#import "BSG_KSSystemInfo.h" #import "BSG_RFC3339DateTool.h" #import "BugsnagApiClient.h" -#import "BugsnagAppWithState+Private.h" #import "BugsnagCollections.h" -#import "BugsnagConfiguration+Private.h" -#import "BugsnagDeviceWithState+Private.h" #import "BugsnagError+Private.h" #import "BugsnagEvent+Private.h" #import "BugsnagHandledState.h" @@ -50,13 +46,16 @@ static NSString * DeviceId(void); +static NSString * Sysctl(const char *name); + // MARK: - BSG_OBJC_DIRECT_MEMBERS @interface BSGInternalErrorReporter () -@property (weak, nullable, nonatomic) id dataSource; +@property (nonatomic) NSString *apiKey; +@property (nonatomic) NSURL *endpoint; @property (nonatomic) NSURLSession *session; @end @@ -88,9 +87,10 @@ + (void)performBlock:(void (^)(BSGInternalErrorReporter *))block { } } -- (instancetype)initWithDataSource:(id)dataSource { +- (instancetype)initWithApiKey:(NSString *)apiKey endpoint:(NSURL *)endpoint { if ((self = [super init])) { - _dataSource = dataSource; + _apiKey = apiKey; + _endpoint = endpoint; _session = [NSURLSession sessionWithConfiguration:NSURLSessionConfiguration.ephemeralSessionConfiguration]; } return self; @@ -199,24 +199,30 @@ - (nullable BugsnagEvent *)eventWithError:(BugsnagError *)error diagnostics:(nullable NSDictionary *)diagnostics groupingHash:(nullable NSString *)groupingHash { - id dataSource = self.dataSource; - if (!dataSource) { - return nil; - } - BugsnagMetadata *metadata = [[BugsnagMetadata alloc] init]; if (diagnostics) { [metadata addMetadata:(NSDictionary * _Nonnull)diagnostics toSection:BugsnagDiagnosticsKey]; } - [metadata addMetadata:dataSource.configuration.apiKey withKey:BSGKeyApiKey toSection:BugsnagDiagnosticsKey]; + [metadata addMetadata:self.apiKey withKey:BSGKeyApiKey toSection:BugsnagDiagnosticsKey]; + + NSDictionary *systemVersion = [NSDictionary dictionaryWithContentsOfFile: + @"/System/Library/CoreServices/SystemVersion.plist"]; - NSDictionary *systemInfo = [BSG_KSSystemInfo systemInfo]; + BugsnagDeviceWithState *device = [BugsnagDeviceWithState new]; + device.id = DeviceId(); + device.manufacturer = @"Apple"; + device.osName = systemVersion[@"ProductName"]; + device.osVersion = systemVersion[@"ProductVersion"]; - BugsnagDeviceWithState *device = [dataSource generateDeviceWithState:systemInfo]; - device.id = DeviceId(); +#if TARGET_OS_OSX || TARGET_OS_SIMULATOR || (defined(TARGET_OS_MACCATALYST) && TARGET_OS_MACCATALYST) + device.model = Sysctl("hw.model"); +#else + device.model = Sysctl("hw.machine"); + device.modelNumber = Sysctl("hw.model"); +#endif BugsnagEvent *event = - [[BugsnagEvent alloc] initWithApp:[dataSource generateAppWithState:systemInfo] + [[BugsnagEvent alloc] initWithApp:[BugsnagAppWithState new] device:device handledState:[BugsnagHandledState handledStateWithSeverityReason:HandledError] user:[[BugsnagUser alloc] init] @@ -235,20 +241,6 @@ - (nullable BugsnagEvent *)eventWithError:(BugsnagError *)error // MARK: Delivery - (NSURLRequest *)requestForEvent:(nonnull BugsnagEvent *)event error:(NSError * __autoreleasing *)errorPtr { - id dataSource = self.dataSource; - if (!dataSource) { - return nil; - } - - NSURL *url = dataSource.configuration.notifyURL; - if (!url) { - if (errorPtr) { - *errorPtr = [NSError errorWithDomain:@"BugsnagConfigurationErrorDomain" code:0 - userInfo:@{NSLocalizedDescriptionKey: @"Missing notify URL"}]; - } - return nil; - } - NSMutableDictionary *requestPayload = [NSMutableDictionary dictionary]; requestPayload[BSGKeyEvents] = @[[event toJsonWithRedactedKeys:nil]]; requestPayload[BSGKeyNotifier] = [[[BugsnagNotifier alloc] init] toDict]; @@ -266,7 +258,7 @@ - (NSURLRequest *)requestForEvent:(nonnull BugsnagEvent *)event error:(NSError * headers[BugsnagHTTPHeaderNamePayloadVersion] = EventPayloadVersion; headers[BugsnagHTTPHeaderNameSentAt] = [BSG_RFC3339DateTool stringFromDate:[NSDate date]]; - NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; + NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:self.endpoint]; request.allHTTPHeaderFields = headers; request.HTTPBody = data; request.HTTPMethod = @"POST"; @@ -303,7 +295,7 @@ - (void)sendEvent:(nonnull BugsnagEvent *)event { CC_SHA1_Update(&ctx, uuid, sizeof(uuid)); #elif TARGET_OS_WATCH uuid_t uuid = {0}; - [[[NSClassFromString(@"WKInterfaceDevice") currentDevice] identifierForVendor] getUUIDBytes:uuid]; + [[[WKInterfaceDevice currentDevice] identifierForVendor] getUUIDBytes:uuid]; CC_SHA1_Update(&ctx, uuid, sizeof(uuid)); #else #error Unsupported target platform @@ -325,3 +317,12 @@ - (void)sendEvent:(nonnull BugsnagEvent *)event { } return [[NSString alloc] initWithBytes:hex length:sizeof(hex) encoding:NSASCIIStringEncoding]; } + +static NSString * Sysctl(const char *name) { + char buffer[32] = {0}; + if (bsg_kssysctl_stringForName(name, buffer, sizeof buffer - 1)) { + return @(buffer); + } else { + return nil; + } +} diff --git a/Bugsnag/Helpers/BSGRunContext.m b/Bugsnag/Helpers/BSGRunContext.m index 4fa17c910..50742b339 100644 --- a/Bugsnag/Helpers/BSGRunContext.m +++ b/Bugsnag/Helpers/BSGRunContext.m @@ -504,6 +504,7 @@ static void ResizeAndMapFile(int fd) { } memset(ptr, 0, SIZEOF_STRUCT); + mlock(ptr, SIZEOF_STRUCT); bsg_runContext = ptr; return; diff --git a/Bugsnag/KSCrash/Source/KSCrash/Recording/Sentry/BSG_KSCrashSentry_MachException.c b/Bugsnag/KSCrash/Source/KSCrash/Recording/Sentry/BSG_KSCrashSentry_MachException.c index 761d81216..60aed6db2 100644 --- a/Bugsnag/KSCrash/Source/KSCrash/Recording/Sentry/BSG_KSCrashSentry_MachException.c +++ b/Bugsnag/KSCrash/Source/KSCrash/Recording/Sentry/BSG_KSCrashSentry_MachException.c @@ -289,6 +289,14 @@ void *ksmachexc_i_handleExceptions(void *const userData) { "Crash handling complete. Restoring original handlers."); bsg_kscrashsentry_uninstall(BSG_KSCrashTypeAsyncSafe); bsg_kscrashsentry_resumeThreads(); + + // Must run before endHandlingCrash unblocks secondary crashed threads. + BSG_KSCrash_Context *context = crashContext(); + if (context->crash.attemptDelivery) { + BSG_KSLOG_DEBUG("Attempting delivery."); + context->crash.attemptDelivery(); + } + bsg_kscrashsentry_endHandlingCrash(); } diff --git a/Bugsnag/KSCrash/Source/KSCrash/Recording/Tools/BSG_KSCrashStringConversion.c b/Bugsnag/KSCrash/Source/KSCrash/Recording/Tools/BSG_KSCrashStringConversion.c index 36093ecf2..bba3be301 100644 --- a/Bugsnag/KSCrash/Source/KSCrash/Recording/Tools/BSG_KSCrashStringConversion.c +++ b/Bugsnag/KSCrash/Source/KSCrash/Recording/Tools/BSG_KSCrashStringConversion.c @@ -100,13 +100,13 @@ static size_t positive_double_to_string(const double value, char* dst, int max_s // isnan() is basically ((x) != (x)) if(isnan(value)) { - strcpy(dst, "nan"); + strlcpy(dst, "nan", 4); return 3; } // isinf() is a compiler intrinsic. if(isinf(value)) { - strcpy(dst, "inf"); + strlcpy(dst, "inf", 4); return 3; } diff --git a/Bugsnag/Payload/BugsnagNotifier.m b/Bugsnag/Payload/BugsnagNotifier.m index 6882a8382..a5a74d968 100644 --- a/Bugsnag/Payload/BugsnagNotifier.m +++ b/Bugsnag/Payload/BugsnagNotifier.m @@ -23,7 +23,7 @@ - (instancetype)init { #else _name = @"Bugsnag Objective-C"; #endif - _version = @"6.24.0"; + _version = @"6.25.0"; _url = @"https://github.com/bugsnag/bugsnag-cocoa"; _dependencies = @[]; } diff --git a/Bugsnag/include/Bugsnag/BugsnagConfiguration.h b/Bugsnag/include/Bugsnag/BugsnagConfiguration.h index 56daf9216..9b5bb38c5 100644 --- a/Bugsnag/include/Bugsnag/BugsnagConfiguration.h +++ b/Bugsnag/include/Bugsnag/BugsnagConfiguration.h @@ -298,6 +298,30 @@ BUGSNAG_EXTERN */ @property (nonatomic) BOOL sendLaunchCrashesSynchronously; +/** + * Whether Bugsnag should try to send crashing errors prior to app termination. + * + * Delivery will only be attempted for uncaught Objective-C exceptions and Mach + * exceptions, and while in progress will block the crashing thread for up to 3 + * seconds. + * + * Delivery will be unreliable due to the necessary short timeout and potential + * memory corruption that caused the crashing error in the first place. + * + * If it fails prior to termination, delivery will be reattempted at next launch + * (the default behavior). + * + * Use of this feature is discouraged because it: + * - may cause the app to hang while delivery occurs and impact the hang rate + * reported in Xcode Organizer + * - will result in duplicate crashes in your dashboard for crashes that were + * fully sent but without receiving an HTTP response within the timeout + * - may prevent other crash reporters from detecting the crash. + * + * By default this value is false. + */ +@property (nonatomic) BOOL attemptDeliveryOnCrash; + /** * The types of breadcrumbs which will be captured. By default, this is all types. */ @@ -488,33 +512,6 @@ BUGSNAG_EXTERN */ @property (nonatomic) BSGTelemetryOptions telemetry; -// ============================================================================= -// MARK: - Experimental -// ============================================================================= - -/** - * Whether Bugsnag should try to send crashing errors prior to app termination. - * - * Delivery will only be attempted for uncaught Objective-C exceptions, and - * while in progress will block the crashing thread for up to 3 seconds. - * - * Delivery will be unreliable due to the necessary short timeout and potential - * memory corruption that caused the crashing error in the first place. - * - * If it fails prior to termination, delivery will be reattempted at next launch - * (the default behavior). - * - * Use of this feature is discouraged because it: - * - may cause the app to hang while delivery occurs and impact the hang rate - * reported in Xcode Organizer - * - will result in duplicate crashes in your dashboard for crashes that were - * fully sent but without receiving an HTTP response within the timeout - * - may prevent other crash reporters from detecting the crash. - * - * By default this value is false. - */ -@property (nonatomic) BOOL attemptDeliveryOnCrash; - // ============================================================================= // MARK: - Plugins // ============================================================================= diff --git a/Bugsnag/include/Bugsnag/BugsnagDevice.h b/Bugsnag/include/Bugsnag/BugsnagDevice.h index 1cfda3850..ed1fe5b94 100644 --- a/Bugsnag/include/Bugsnag/BugsnagDevice.h +++ b/Bugsnag/include/Bugsnag/BugsnagDevice.h @@ -38,12 +38,12 @@ BUGSNAG_EXTERN @property (copy, nullable, nonatomic) NSString *manufacturer; /** - * The model name of the device used + * The model ID of the device used, e.g. "iPhone14,1" or "MacBookPro17,1" */ @property (copy, nullable, nonatomic) NSString *model; /** - * The model number of the device used + * The model number of the device used, e.g. "N841AP" */ @property (copy, nullable, nonatomic) NSString *modelNumber; diff --git a/BugsnagNetworkRequestPlugin.podspec.json b/BugsnagNetworkRequestPlugin.podspec.json index 66ec5eac6..0296c3a22 100644 --- a/BugsnagNetworkRequestPlugin.podspec.json +++ b/BugsnagNetworkRequestPlugin.podspec.json @@ -1,16 +1,16 @@ { "name": "BugsnagNetworkRequestPlugin", - "version": "6.24.0", + "version": "6.25.0", "summary": "Network request monitoring support for Bugsnag.", "homepage": "https://bugsnag.com", "license": "MIT", "authors": { "Bugsnag": "notifiers@bugsnag.com" }, - "readme": "https://raw.githubusercontent.com/bugsnag/bugsnag-cocoa/v6.24.0/BugsnagNetworkRequestPlugin/README.md", + "readme": "https://raw.githubusercontent.com/bugsnag/bugsnag-cocoa/v6.25.0/BugsnagNetworkRequestPlugin/README.md", "source": { "git": "https://github.com/bugsnag/bugsnag-cocoa.git", - "tag": "v6.24.0" + "tag": "v6.25.0" }, "dependencies": { "Bugsnag": "~> 6.13" diff --git a/CHANGELOG.md b/CHANGELOG.md index d3983abd8..cbd3d432b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,12 +1,22 @@ Changelog ========= +## 6.25.0 (2022-10-26) + +### Enhancements + +* Expand `configuration.attemptDeliveryOnCrash` to send Mach exceptions (e.g. + Swift fatal errors and bad memory accesses) at crash time. + [#1496](https://github.com/bugsnag/bugsnag-cocoa/pull/1496) + ## 6.24.0 (2022-10-05) ### Enhancements -* Add (experimental) `configuration.attemptDeliveryOnCrash` to allow uncaught - Objective-C exceptions to be sent at crash time, prior to app termination. +* Add `configuration.attemptDeliveryOnCrash` to allow uncaught Objective-C + exceptions to be sent at crash time, prior to app termination. Use of this + feature may impair user experience and other crash reporters; please read + https://docs.bugsnag.com/platforms/ios/configuration-options/#attemptdeliveryoncrash [#1488](https://github.com/bugsnag/bugsnag-cocoa/pull/1488) ### Bug fixes diff --git a/Framework/Info.plist b/Framework/Info.plist index ff3d9cdea..23311a816 100644 --- a/Framework/Info.plist +++ b/Framework/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 6.24.0 + 6.25.0 CFBundleVersion 1 diff --git a/Tests/BugsnagTests/BSGInternalErrorReporterTests.m b/Tests/BugsnagTests/BSGInternalErrorReporterTests.m index 88fcc82e7..1027464aa 100644 --- a/Tests/BugsnagTests/BSGInternalErrorReporterTests.m +++ b/Tests/BugsnagTests/BSGInternalErrorReporterTests.m @@ -17,7 +17,7 @@ #import "BugsnagEvent+Private.h" #import "BugsnagNotifier.h" -@interface BSGInternalErrorReporterTests : XCTestCase +@interface BSGInternalErrorReporterTests : XCTestCase @property (nonatomic) BugsnagConfiguration *configuration; @@ -33,9 +33,13 @@ - (void)setUp { self.configuration = [[BugsnagConfiguration alloc] initWithApiKey:@"0192837465afbecd0192837465afbecd"]; } +- (BSGInternalErrorReporter *)makeReporter { + return [[BSGInternalErrorReporter alloc] initWithApiKey:self.configuration.apiKey endpoint:[NSURL URLWithString:self.configuration.endpoints.notify]]; +} + - (void)testEventWithErrorClass { BugsnagConfiguration *configuration = [[BugsnagConfiguration alloc] initWithApiKey:@"0192837465afbecd0192837465afbecd"]; - BSGInternalErrorReporter *reporter = [[BSGInternalErrorReporter alloc] initWithDataSource:self]; + BSGInternalErrorReporter *reporter = [self makeReporter]; BugsnagEvent *event = [reporter eventWithErrorClass:@"Internal error" context:@"test" message:@"Something went wrong" diagnostics:@{}]; XCTAssertEqualObjects(event.errors[0].errorClass, @"Internal error"); @@ -54,7 +58,7 @@ - (void)testEventWithErrorClass { - (void)testEventWithException { BugsnagConfiguration *configuration = [[BugsnagConfiguration alloc] initWithApiKey:@"0192837465afbecd0192837465afbecd"]; - BSGInternalErrorReporter *reporter = [[BSGInternalErrorReporter alloc] initWithDataSource:self]; + BSGInternalErrorReporter *reporter = [self makeReporter]; NSException *exception = nil; @try { @@ -80,7 +84,7 @@ - (void)testEventWithException { - (void)testEventWithRecrashReport { BugsnagConfiguration *configuration = [[BugsnagConfiguration alloc] initWithApiKey:@"0192837465afbecd0192837465afbecd"]; - BSGInternalErrorReporter *reporter = [[BSGInternalErrorReporter alloc] initWithDataSource:self]; + BSGInternalErrorReporter *reporter = [self makeReporter]; NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"RecrashReport" ofType:@"json" inDirectory:@"Data"]; id recrashReport = [NSJSONSerialization JSONObjectWithData:[NSData dataWithContentsOfFile:path] options:0 error:nil]; @@ -105,7 +109,7 @@ - (void)testRequestForEvent { self.configuration.endpoints.notify = @"https://notify.example.com"; BugsnagNotifier *notifier = [[BugsnagNotifier alloc] init]; - BSGInternalErrorReporter *reporter = [[BSGInternalErrorReporter alloc] initWithDataSource:self]; + BSGInternalErrorReporter *reporter = [self makeReporter]; BugsnagEvent *event = [[BugsnagEvent alloc] init]; @@ -132,7 +136,7 @@ - (void)testPerformBlock { XCTAssertNotNil(reporter); [expectation fulfill]; }]; - [BSGInternalErrorReporter setSharedInstance:[[BSGInternalErrorReporter alloc] initWithDataSource:self]]; + [BSGInternalErrorReporter setSharedInstance:[[BSGInternalErrorReporter alloc] initWithApiKey:self.configuration.apiKey endpoint:[NSURL URLWithString:self.configuration.endpoints.notify]]]; [self waitForExpectations:@[expectation] timeout:1]; expectation = [self expectationWithDescription:@"+performBlock: block is called immediately"]; diff --git a/Tests/BugsnagTests/BugsnagMetadataTests.m b/Tests/BugsnagTests/BugsnagMetadataTests.m index 5b39c6a27..24a121b9a 100644 --- a/Tests/BugsnagTests/BugsnagMetadataTests.m +++ b/Tests/BugsnagTests/BugsnagMetadataTests.m @@ -422,7 +422,8 @@ - (void)testMetadataStorageBuffer { while (!threads[i]) {} } - char *scratch = malloc(1024 * 1024); + size_t size = 1024 * 1024; + char *scratch = malloc(size); for (int i = 0; i < 10000; i++) { // Threads must be suspended to prevent the metadata buffer from being freed while @@ -432,7 +433,7 @@ - (void)testMetadataStorageBuffer { thread_suspend(threads[i]); } - strcpy(scratch, buffer); + strlcpy(scratch, buffer, size); for (int i = 0; i < threadCount; i++) { thread_resume(threads[i]); diff --git a/Tests/BugsnagTests/Info.plist b/Tests/BugsnagTests/Info.plist index e3ab0ce7b..74d28fecc 100644 --- a/Tests/BugsnagTests/Info.plist +++ b/Tests/BugsnagTests/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType $(PRODUCT_BUNDLE_PACKAGE_TYPE) CFBundleShortVersionString - 6.24.0 + 6.25.0 CFBundleVersion 1 diff --git a/Tests/TestHost-iOS/Info.plist b/Tests/TestHost-iOS/Info.plist index 2a4a3e590..5cb2e3d3f 100644 --- a/Tests/TestHost-iOS/Info.plist +++ b/Tests/TestHost-iOS/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType $(PRODUCT_BUNDLE_PACKAGE_TYPE) CFBundleShortVersionString - 6.24.0 + 6.25.0 CFBundleVersion 1 LSRequiresIPhoneOS diff --git a/VERSION b/VERSION index 2496b04b8..961b1c8ec 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -6.24.0 +6.25.0 diff --git a/features/delivery.feature b/features/delivery.feature index ae325f34d..4ce317685 100644 --- a/features/delivery.feature +++ b/features/delivery.feature @@ -157,13 +157,15 @@ Feature: Delivery of errors And the event "usage.system.stringCharsTruncated" is not null And the event "usage.system.stringsTruncated" is not null - Scenario: Attempt Delivery On Crash - When I run "AttemptDeliveryOnCrashScenario" + Scenario Outline: Attempt Delivery On Crash + When I set the app to "" mode + And I run "AttemptDeliveryOnCrashScenario" And I wait to receive an error Then the error is valid for the error reporting API And the event "context" equals "OnSendError" - And the event "metaData.error.nsexception.name" equals "NSRangeException" - And the event "metaData.error.type" equals "nsexception" + And the exception "errorClass" equals "" + And the exception "message" equals "" + And the event "metaData.error.type" equals "" And the event "unhandled" is true And the event "usage.config.attemptDeliveryOnCrash" is true And I discard the oldest error @@ -171,3 +173,8 @@ Feature: Delivery of errors And I configure Bugsnag for "AttemptDeliveryOnCrashScenario" And I wait to receive 2 sessions Then I should receive no error + Examples: + | scenario_mode | error_type | error_class | message | + | NSException | nsexception | NSRangeException | *** -[__NSArray0 objectAtIndex:]: index 42 beyond bounds for empty NSArray | + | SwiftFatalError | mach | Fatal error | Unexpectedly found nil while unwrapping an Optional value | + | BadAccess | mach | EXC_BAD_ACCESS | Attempted to dereference garbage pointer 0x20. | diff --git a/features/fixtures/shared/scenarios/AttemptDeliveryOnCrashScenario.swift b/features/fixtures/shared/scenarios/AttemptDeliveryOnCrashScenario.swift index f51ed57d5..c3ccf1ae4 100644 --- a/features/fixtures/shared/scenarios/AttemptDeliveryOnCrashScenario.swift +++ b/features/fixtures/shared/scenarios/AttemptDeliveryOnCrashScenario.swift @@ -19,6 +19,24 @@ class AttemptDeliveryOnCrashScenario: Scenario { } override func run() { - NSArray().object(at: 42) + guard let eventMode = eventMode else { return } + switch eventMode { + case "BadAccess": + if let ptr = UnsafePointer(bitPattern: 42) { + strlen(ptr) + } + break + + case "NSException": + NSArray().object(at: 42) + break + + case "SwiftFatalError": + _ = URL(string: "")! + break + + default: + break + } } }