From 9b7ada60290555c7a78e6eac3d8a056440ccc71b Mon Sep 17 00:00:00 2001 From: Jeff Tung <100387939+jtung-apple@users.noreply.github.com> Date: Thu, 4 Apr 2024 15:38:36 -0700 Subject: [PATCH] [Darwin] MTRAttributePath NSSecureCoding fix --- src/darwin/Framework/CHIP/MTRBaseDevice.mm | 59 +++++++++++++++++++ .../Framework/CHIPTests/MTRDeviceTests.m | 44 ++++++++++++++ 2 files changed, 103 insertions(+) diff --git a/src/darwin/Framework/CHIP/MTRBaseDevice.mm b/src/darwin/Framework/CHIP/MTRBaseDevice.mm index 914917a77adcde..cb93d2db5d0e5b 100644 --- a/src/darwin/Framework/CHIP/MTRBaseDevice.mm +++ b/src/darwin/Framework/CHIP/MTRBaseDevice.mm @@ -2597,6 +2597,7 @@ - (nullable instancetype)initWithCoder:(NSCoder *)decoder - (void)encodeWithCoder:(NSCoder *)coder { + [super encodeWithCoder:coder]; [coder encodeObject:_attribute forKey:sAttributeKey]; } @@ -2663,6 +2664,35 @@ - (ConcreteEventPath)_asConcretePath return ConcreteEventPath([self.endpoint unsignedShortValue], static_cast([self.cluster unsignedLongValue]), static_cast([self.event unsignedLongValue])); } + +static NSString * const sEventKey = @"eventKey"; + ++ (BOOL)supportsSecureCoding +{ + return YES; +} + +- (nullable instancetype)initWithCoder:(NSCoder *)decoder +{ + self = [super initWithCoder:decoder]; + if (self == nil) { + return nil; + } + + _event = [decoder decodeObjectOfClass:[NSNumber class] forKey:sEventKey]; + if (_event && ![_event isKindOfClass:[NSNumber class]]) { + MTR_LOG_ERROR("MTREventPath decoded %@ for event, not NSNumber.", _event); + return nil; + } + + return self; +} + +- (void)encodeWithCoder:(NSCoder *)coder +{ + [super encodeWithCoder:coder]; + [coder encodeObject:_event forKey:sEventKey]; +} @end @implementation MTREventPath (Deprecated) @@ -2718,6 +2748,35 @@ - (id)copyWithZone:(NSZone *)zone { return [MTRCommandPath commandPathWithEndpointID:self.endpoint clusterID:self.cluster commandID:_command]; } + +static NSString * const sCommandKey = @"commandKey"; + ++ (BOOL)supportsSecureCoding +{ + return YES; +} + +- (nullable instancetype)initWithCoder:(NSCoder *)decoder +{ + self = [super initWithCoder:decoder]; + if (self == nil) { + return nil; + } + + _command = [decoder decodeObjectOfClass:[NSNumber class] forKey:sCommandKey]; + if (_command && ![_command isKindOfClass:[NSNumber class]]) { + MTR_LOG_ERROR("MTRCommandPath decoded %@ for command, not NSNumber.", _command); + return nil; + } + + return self; +} + +- (void)encodeWithCoder:(NSCoder *)coder +{ + [super encodeWithCoder:coder]; + [coder encodeObject:_command forKey:sCommandKey]; +} @end @implementation MTRCommandPath (Deprecated) diff --git a/src/darwin/Framework/CHIPTests/MTRDeviceTests.m b/src/darwin/Framework/CHIPTests/MTRDeviceTests.m index 1d71c7b00ea4ce..34d39289cd5772 100644 --- a/src/darwin/Framework/CHIPTests/MTRDeviceTests.m +++ b/src/darwin/Framework/CHIPTests/MTRDeviceTests.m @@ -2914,6 +2914,50 @@ - (void)test031_MTRDeviceAttributeCacheLocalTestStorage } #endif // MTR_PER_CONTROLLER_STORAGE_ENABLED +- (void)test032_MTRPathClassesEncoding +{ + NSError * encodeError; + NSData * encodedData; + NSError * decodeError; + id decodedValue; + + // Test attribute path encode / decode + MTRAttributePath * originalAttributePath = [MTRAttributePath attributePathWithEndpointID:@(101) clusterID:@(102) attributeID:@(103)]; + encodedData = [NSKeyedArchiver archivedDataWithRootObject:originalAttributePath requiringSecureCoding:YES error:&encodeError]; + XCTAssertNil(encodeError); + + decodedValue = [NSKeyedUnarchiver unarchivedObjectOfClasses:[NSSet setWithObject:[MTRAttributePath class]] fromData:encodedData error:&decodeError]; + XCTAssertNil(decodeError); + XCTAssertTrue([decodedValue isKindOfClass:[MTRAttributePath class]]); + + MTRAttributePath * decodedAttributePath = decodedValue; + XCTAssertEqualObjects(originalAttributePath, decodedAttributePath); + + // Test event path encode / decode + MTREventPath * originalEventPath = [MTREventPath eventPathWithEndpointID:@(201) clusterID:@(202) eventID:@(203)]; + encodedData = [NSKeyedArchiver archivedDataWithRootObject:originalEventPath requiringSecureCoding:YES error:&encodeError]; + XCTAssertNil(encodeError); + + decodedValue = [NSKeyedUnarchiver unarchivedObjectOfClasses:[NSSet setWithObject:[MTREventPath class]] fromData:encodedData error:&decodeError]; + XCTAssertNil(decodeError); + XCTAssertTrue([decodedValue isKindOfClass:[MTREventPath class]]); + + MTREventPath * decodedEventPath = decodedValue; + XCTAssertEqualObjects(originalEventPath, decodedEventPath); + + // Test command path encode / decode + MTRCommandPath * originalCommandPath = [MTRCommandPath commandPathWithEndpointID:@(301) clusterID:@(302) commandID:@(303)]; + encodedData = [NSKeyedArchiver archivedDataWithRootObject:originalCommandPath requiringSecureCoding:YES error:&encodeError]; + XCTAssertNil(encodeError); + + decodedValue = [NSKeyedUnarchiver unarchivedObjectOfClasses:[NSSet setWithObject:[MTRCommandPath class]] fromData:encodedData error:&decodeError]; + XCTAssertNil(decodeError); + XCTAssertTrue([decodedValue isKindOfClass:[MTRCommandPath class]]); + + MTRCommandPath * decodedCommandPath = decodedValue; + XCTAssertEqualObjects(originalCommandPath, decodedCommandPath); +} + @end @interface MTRDeviceEncoderTests : XCTestCase