From 47c99850bba4d8e14081f2e30bf0b35dc1458b98 Mon Sep 17 00:00:00 2001 From: Delisa Mason Date: Thu, 21 Jul 2016 11:56:06 -0700 Subject: [PATCH] Enforce size limit --- Source/BugsnagBreadcrumb.m | 42 ++++++++++++++++++++++++++-------- Tests/BugsnagBreadcrumbsTest.m | 28 +++++++++++++++++++++++ 2 files changed, 60 insertions(+), 10 deletions(-) diff --git a/Source/BugsnagBreadcrumb.m b/Source/BugsnagBreadcrumb.m index 470dbce72..fdba3dfbe 100644 --- a/Source/BugsnagBreadcrumb.m +++ b/Source/BugsnagBreadcrumb.m @@ -27,6 +27,7 @@ #import "Bugsnag.h" NSString *const BSGBreadcrumbDefaultName = @"manual"; +NSUInteger const BSGBreadcrumbMaxByteSize = 4096; NSString *BSGBreadcrumbTypeValue(BSGBreadcrumbType type) { switch (type) { @@ -52,6 +53,12 @@ @interface BugsnagBreadcrumbs() @property (nonatomic,readwrite,strong) NSMutableArray* breadcrumbs; + +@end + +@interface BugsnagBreadcrumb () + +- (NSDictionary *_Nullable)objectValue; @end @implementation BugsnagBreadcrumb @@ -70,6 +77,21 @@ - (BOOL)isValid { return self.name.length > 0 && self.timestamp != nil; } +- (NSDictionary *)objectValue { + NSString* timestamp = [[Bugsnag payloadDateFormatter] stringFromDate:self.timestamp]; + if (timestamp && self.name.length > 0) { + NSMutableDictionary *data = @{ + @"name": self.name, + @"timestamp": timestamp, + @"type": BSGBreadcrumbTypeValue(self.type) + }.mutableCopy; + if (self.metadata) + data[@"metaData"] = self.metadata; + return data; + } + return nil; +} + + (instancetype)breadcrumbWithBlock:(BSGBreadcrumbConfiguration)block { BugsnagBreadcrumb *crumb = [self new]; if (block) @@ -145,16 +167,16 @@ - (NSArray *)arrayValue { } NSMutableArray* contents = [[NSMutableArray alloc] initWithCapacity:[self count]]; for (BugsnagBreadcrumb* crumb in self.breadcrumbs) { - NSString* timestamp = [[Bugsnag payloadDateFormatter] stringFromDate:crumb.timestamp]; - if (timestamp && crumb.name.length > 0) { - NSMutableDictionary *data = @{ - @"name": crumb.name, - @"timestamp": timestamp, - @"type": BSGBreadcrumbTypeValue(crumb.type) - }.mutableCopy; - if (crumb.metadata) - data[@"metaData"] = crumb.metadata; - [contents addObject:data]; + NSDictionary *objectValue = [crumb objectValue]; + NSError *error = nil; + @try { + NSData* data = [NSJSONSerialization dataWithJSONObject:objectValue options:0 error:&error]; + if (data.length <= BSGBreadcrumbMaxByteSize) + [contents addObject:objectValue]; + else + NSLog(@"Dropping Bugsnag breadcrumb (%@) exceeding %lu byte size limit", crumb.name, (unsigned long)BSGBreadcrumbMaxByteSize); + } @catch (NSException *exception) { + NSLog(@"Unable to serialize breadcrumb for Bugsnag: %@", error); } } return contents; diff --git a/Tests/BugsnagBreadcrumbsTest.m b/Tests/BugsnagBreadcrumbsTest.m index a068b8a6b..cf583e1dd 100644 --- a/Tests/BugsnagBreadcrumbsTest.m +++ b/Tests/BugsnagBreadcrumbsTest.m @@ -81,4 +81,32 @@ - (void)testArrayValue { XCTAssertEqualObjects(value[2][@"metaData"][@"message"], @"Close tutorial"); } +- (void)testStateType { + BugsnagBreadcrumbs* crumbs = [BugsnagBreadcrumbs new]; + [crumbs addBreadcrumbWithBlock:^(BugsnagBreadcrumb * _Nonnull crumb) { + crumb.type = BSGBreadcrumbTypeState; + crumb.name = @"Rotated Menu"; + crumb.metadata = @{ @"direction": @"right" }; + }]; + NSArray* value = [crumbs arrayValue]; + XCTAssertEqualObjects(value[0][@"metaData"][@"direction"], @"right"); + XCTAssertEqualObjects(value[0][@"name"], @"Rotated Menu"); + XCTAssertEqualObjects(value[0][@"type"], @"state"); +} + +- (void)testByteSizeLimit { + BugsnagBreadcrumbs* crumbs = [BugsnagBreadcrumbs new]; + [crumbs addBreadcrumbWithBlock:^(BugsnagBreadcrumb * _Nonnull crumb) { + crumb.type = BSGBreadcrumbTypeState; + crumb.name = @"Rotated Menu"; + NSMutableDictionary *metadata = @{}.mutableCopy; + for (int i = 0; i < 400; i++) { + metadata[[NSString stringWithFormat:@"%d", i]] = @"!!"; + } + crumb.metadata = metadata; + }]; + NSArray* value = [crumbs arrayValue]; + XCTAssertTrue(value.count == 0); +} + @end