Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# Unreleased
- Fix a crash when a server error response carries a non-string value under its `error` key. The EMM error handler sent `-hasPrefix:` to whatever value was present, raising an unrecognized selector exception on a number, array or object.

# 10.0.0
- **BREAKING**: Update to AppAuth 3.0.0 and GTMAppAuth 6.0.0, which raises the minimum deployment targets to iOS 15.0 and macOS 12.0, widens the `GTMSessionFetcher` dependency to allow 4.x and 5.x, and renames the version-specific Swift Package Manager manifest to `Package@swift-5.7.swift`. Projects that must keep supporting earlier OS versions should stay on GoogleSignIn 9.2.0. ([#628](https://github.com/google/GoogleSignIn-iOS/pull/628))
- Add `GIDSignIn.wrapperIdentifier` so SDKs that embed Google Sign-In can self-identify in Google's diagnostic logs via a new `gidwrapper` parameter. It is opt-in and pre-existing behavior is unchanged. ([#625](https://github.com/google/GoogleSignIn-iOS/pull/625))
Expand Down
34 changes: 18 additions & 16 deletions GoogleSignIn/Sources/GIDEMMErrorHandler.m
Original file line number Diff line number Diff line change
Expand Up @@ -64,23 +64,25 @@ - (BOOL)handleErrorFromResponse:(NSDictionary<NSString *, id> *)response
if (!_pendingDialog && [UIAlertController class] &&
[response isKindOfClass:[NSDictionary class]]) {
id errorValue = response[kErrorKey];
if ([errorValue isEqual:kScreenlockRequiredError]) {
errorCode = ErrorCodeScreenlockRequired;
} else if ([errorValue hasPrefix:kAppVerificationRequiredErrorPrefix]) {
errorCode = ErrorCodeAppVerificationRequired;
NSString *appVerificationString =
[errorValue substringFromIndex:kAppVerificationRequiredErrorPrefix.length];
if ([appVerificationString hasPrefix:kErrorPayloadSeparator]) {
appVerificationString =
[appVerificationString substringFromIndex:kErrorPayloadSeparator.length];
if ([errorValue isKindOfClass:[NSString class]]) {
if ([errorValue isEqual:kScreenlockRequiredError]) {
errorCode = ErrorCodeScreenlockRequired;
} else if ([errorValue hasPrefix:kAppVerificationRequiredErrorPrefix]) {
errorCode = ErrorCodeAppVerificationRequired;
NSString *appVerificationString =
[errorValue substringFromIndex:kAppVerificationRequiredErrorPrefix.length];
if ([appVerificationString hasPrefix:kErrorPayloadSeparator]) {
appVerificationString =
[appVerificationString substringFromIndex:kErrorPayloadSeparator.length];
}
appVerificationString = [appVerificationString
stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
if (appVerificationString.length) {
appVerificationURL = [NSURL URLWithString:appVerificationString];
}
} else if ([errorValue hasPrefix:kGeneralErrorPrefix]) {
errorCode = ErrorCodeDeviceNotCompliant;
}
appVerificationString = [appVerificationString
stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
if (appVerificationString.length) {
appVerificationURL = [NSURL URLWithString:appVerificationString];
}
} else if ([errorValue hasPrefix:kGeneralErrorPrefix]) {
errorCode = ErrorCodeDeviceNotCompliant;
}
if (errorCode) {
_pendingDialog = YES;
Expand Down
18 changes: 18 additions & 0 deletions GoogleSignIn/Tests/Unit/GIDEMMErrorHandlerTest.m
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,24 @@ - (void)testNoError {
XCTAssertNil(_presentedViewController);
}

// Verifies that a non-string value under the `error` key is ignored rather than crashing.
// The value comes straight from a server JSON response and is typed `id`, so it can be any
// plist type. `-hasPrefix:` is an `NSString` method, so before the type check was added it
// raised an unrecognized selector exception on a number, array or dictionary.
- (void)testNonStringErrorValue {
NSArray *nonStringValues = @[ @123, @[ @"emm_passcode_required" ], @{ @"a" : @"b" } ];
for (id nonStringValue in nonStringValues) {
__block BOOL completionCalled = NO;
NSDictionary<NSString *, id> *response = @{ @"error" : nonStringValue };
BOOL result = [[GIDEMMErrorHandler sharedInstance] handleErrorFromResponse:response
completion:^() {
completionCalled = YES;
}];
XCTAssertFalse(result);
XCTAssertTrue(completionCalled);
}
}

// Verifies that the handler doesn't handle non-EMM error.
- (void)testNoEMMError {
__block BOOL completionCalled = NO;
Expand Down
Loading