From d3b41df22ca8eea95a11011f355133de6368d9d4 Mon Sep 17 00:00:00 2001 From: Brandon Sneed Date: Mon, 24 Aug 2020 13:34:26 -0700 Subject: [PATCH] Fixed issue where non-serializable types would get into payload --- Analytics/Internal/SEGUtils.h | 4 ++++ Analytics/Internal/SEGUtils.m | 30 ++++++++++++++++++++++------- AnalyticsTests/SerializationTests.m | 20 +++++++++++++++++++ Podfile.lock | 2 +- 4 files changed, 48 insertions(+), 8 deletions(-) diff --git a/Analytics/Internal/SEGUtils.h b/Analytics/Internal/SEGUtils.h index 1d7e8b85c..2b067a3fa 100644 --- a/Analytics/Internal/SEGUtils.h +++ b/Analytics/Internal/SEGUtils.h @@ -62,6 +62,10 @@ NSString *_Nullable SEGIDFA(void); NSString *SEGEventNameForScreenTitle(NSString *title); +@interface NSJSONSerialization (Serializable) ++ (BOOL)isOfSerializableType:(id)obj; +@end + // Deep copy and check NSCoding conformance @protocol SEGSerializableDeepCopy -(id _Nullable) serializableMutableDeepCopy; diff --git a/Analytics/Internal/SEGUtils.m b/Analytics/Internal/SEGUtils.m index 780c6d943..602dcdd07 100644 --- a/Analytics/Internal/SEGUtils.m +++ b/Analytics/Internal/SEGUtils.m @@ -559,6 +559,20 @@ static id SEGCoerceJSONObject(id obj) } +@implementation NSJSONSerialization(Serializable) ++ (BOOL)isOfSerializableType:(id)obj +{ + if ([obj isKindOfClass:[NSArray class]] || + [obj isKindOfClass:[NSDictionary class]] || + [obj isKindOfClass:[NSString class]] || + [obj isKindOfClass:[NSNumber class]] || + [obj isKindOfClass:[NSNull class]]) + return YES; + return NO; +} +@end + + @implementation NSDictionary(SerializableDeepCopy) - (id)serializableDeepCopy:(BOOL)mutable @@ -569,11 +583,12 @@ - (id)serializableDeepCopy:(BOOL)mutable id aValue = [self objectForKey:key]; id theCopy = nil; - if (![aValue conformsToProtocol:@protocol(NSCoding)]) { + if (![NSJSONSerialization isOfSerializableType:aValue]) { + NSString *className = NSStringFromClass([aValue class]); #ifdef DEBUG - NSAssert(FALSE, @"key `%@` doesn't conform to NSCoding and can't be serialized for delivery.", key); + NSAssert(FALSE, @"key `%@` is a %@ and can't be serialized for delivery.", key, className); #else - SEGLog(@"key `%@` doesn't conform to NSCoding and can't be serialized for delivery.", key); + SEGLog(@"key `%@` is a %@ and can't be serializaed for delivery.", key, className); // simply leave it out since we can't encode it anyway. continue; #endif @@ -617,16 +632,17 @@ -(id)serializableDeepCopy:(BOOL)mutable for (id aValue in self) { id theCopy = nil; - if (![aValue conformsToProtocol:@protocol(NSCoding)]) { + if (![NSJSONSerialization isOfSerializableType:aValue]) { + NSString *className = NSStringFromClass([aValue class]); #ifdef DEBUG - NSAssert(FALSE, @"type `%@` doesn't conform to NSCoding and can't be serialized for delivery.", NSStringFromClass([aValue class])); + NSAssert(FALSE, @"found a %@ which can't be serialized for delivery.", className); #else - SEGLog(@"type `%@` doesn't conform to NSCoding and can't be serialized for delivery.", NSStringFromClass([aValue class])); + SEGLog(@"found a %@ which can't be serializaed for delivery.", className); // simply leave it out since we can't encode it anyway. continue; #endif } - + if ([aValue conformsToProtocol:@protocol(SEGSerializableDeepCopy)]) { theCopy = [aValue serializableDeepCopy:mutable]; } else if ([aValue conformsToProtocol:@protocol(NSCopying)]) { diff --git a/AnalyticsTests/SerializationTests.m b/AnalyticsTests/SerializationTests.m index 76c57eb66..8503285b8 100644 --- a/AnalyticsTests/SerializationTests.m +++ b/AnalyticsTests/SerializationTests.m @@ -9,6 +9,10 @@ #import @import Analytics; +@interface NSJSONSerialization (Serializable) ++ (BOOL)isOfSerializableType:(id)obj; +@end + @protocol SEGSerializableDeepCopy -(id _Nullable) serializableDeepCopy; @end @@ -52,4 +56,20 @@ - (void)testDeepCopyAndConformance { XCTAssertThrows([nonserializable serializableDeepCopy]); } +- (void)testDateIssue { + NSDate *date = [NSDate date]; + NSString *test = @"test"; + + XCTAssertFalse([NSJSONSerialization isOfSerializableType:date]); + XCTAssertTrue([NSJSONSerialization isOfSerializableType:test]); + + NSDictionary *nonserializable = @{@"test": date}; + NSDictionary *serializable = @{@"test": @1}; + XCTAssertThrows([nonserializable serializableDeepCopy]); + XCTAssertNoThrow([serializable serializableDeepCopy]); + + nonserializable = @{@"test": @[date]}; + XCTAssertThrows([nonserializable serializableDeepCopy]); +} + @end diff --git a/Podfile.lock b/Podfile.lock index 02d53b3fb..a4984894f 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -13,4 +13,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: b1320b7107926418d81b6d48a9c864abdf9c3eaf -COCOAPODS: 1.9.3 +COCOAPODS: 1.9.1