Skip to content
Open
Show file tree
Hide file tree
Changes from all 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