Skip to content

Commit

Permalink
Implement NSSecureCoding on MTRErrorHolder.
Browse files Browse the repository at this point in the history
Otherwise the errors we create cannot be usefully encoded/decoded.
  • Loading branch information
bzbarsky-apple committed Feb 18, 2023
1 parent 0edb83a commit 53ed8ea
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 1 deletion.
40 changes: 39 additions & 1 deletion src/darwin/Framework/CHIP/MTRError.mm
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@

// Class for holding on to a CHIP_ERROR that we can use as the value
// in a dictionary.
@interface MTRErrorHolder : NSObject
@interface MTRErrorHolder : NSObject <NSSecureCoding>
@property (nonatomic, readonly) CHIP_ERROR error;

- (instancetype)init NS_UNAVAILABLE;
Expand Down Expand Up @@ -299,4 +299,42 @@ - (instancetype)initWithError:(CHIP_ERROR)error
return self;
}

#pragma mark - NSSecureCoding

static NSString * const MTRErrorHolderCodingKeyErrorNumber = @"MTREH.ck.errorNumber";

+ (BOOL)supportsSecureCoding
{
return YES;
}

- (void)encodeWithCoder:(NSCoder *)coder
{
// We don't try to save our file/line info, because that's pointing to our
// process memory, so there is no really good way to decode it on the other
// side without leaking the filename string.
[coder encodeObject:@(self.error.AsInteger()) forKey:MTRErrorHolderCodingKeyErrorNumber];
}

- (instancetype _Nullable)initWithCoder:(NSCoder *)decoder
{
using namespace chip;

NSNumber * errorNumber = [decoder decodeObjectOfClass:[NSNumber class] forKey:MTRErrorHolderCodingKeyErrorNumber];
if (decoder == nil) {
return nil;
}

// Use unsignedLongLongValue so we are not making assumptions about the size
// of ChipError::StorageType
auto error = static_cast<ChipError::StorageType>(errorNumber.unsignedLongLongValue);

return [self initWithError:ChipError(error)];
}

- (NSString *)description
{
return [NSString stringWithFormat:@"<MTRErrorHolder>[error: %s]", self.error.AsString()];
}

@end
22 changes: 22 additions & 0 deletions src/darwin/Framework/CHIPTests/MTRSetupPayloadParserTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,28 @@ - (void)testOnboardingPayloadParser_QRCode_WrongVersion

XCTAssertNil(payload);
XCTAssertNotNil(error);

// Use the fact that this is actually a Matter error to test our
// NSSecureCoding implementation.
XCTAssertNotNil(error.userInfo);
XCTAssertNotNil(error.userInfo[@"underlyingError"]);

XCTAssertTrue([[error description] containsString:@"MTRSetupPayload.mm"]);
XCTAssertTrue([[error description] containsString:@"0x0000002F"]);

NSError * encodingError;
NSData * encoded = [NSKeyedArchiver archivedDataWithRootObject:error requiringSecureCoding:YES error:&encodingError];
XCTAssertNotNil(encoded);
XCTAssertNil(encodingError);

NSSet * classes = [NSSet setWithObjects:[NSError class], NSClassFromString(@"MTRErrorHolder"), nil];
NSError * decodingError;
NSError * decoded = [NSKeyedUnarchiver unarchivedObjectOfClasses:classes fromData:encoded error:&decodingError];
XCTAssertNotNil(decoded);
XCTAssertNil(decodingError);

XCTAssertFalse([[decoded description] containsString:@"MTRSetupPayload.mm"]);
XCTAssertTrue([[error description] containsString:@"0x0000002F"]);
}

- (void)testOnboardingPayloadParser_NFC_NoError
Expand Down

0 comments on commit 53ed8ea

Please sign in to comment.