From 47e8d7d1252cbef7c37012019368073eb40ab020 Mon Sep 17 00:00:00 2001 From: importRyan Date: Wed, 16 Oct 2024 12:08:26 -0700 Subject: [PATCH 1/7] Fix iOS text selection crash by returning nil range --- .../darwin/ios/framework/Source/FlutterTextInputPlugin.mm | 4 +++- .../darwin/ios/framework/Source/TextInputSemanticsObject.mm | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.mm b/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.mm index 9358431cf5a6f..c5353bd93ac64 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.mm @@ -1290,7 +1290,9 @@ - (NSString*)textInRange:(UITextRange*)range { NSAssert([range isKindOfClass:[FlutterTextRange class]], @"Expected a FlutterTextRange for range (got %@).", [range class]); NSRange textRange = ((FlutterTextRange*)range).range; - NSAssert(textRange.location != NSNotFound, @"Expected a valid text range."); + if (textRange.location == NSNotFound) { + return nil; + } // Sanitize the range to prevent going out of bounds. NSUInteger location = MIN(textRange.location, self.text.length); NSUInteger length = MIN(self.text.length - location, textRange.length); diff --git a/shell/platform/darwin/ios/framework/Source/TextInputSemanticsObject.mm b/shell/platform/darwin/ios/framework/Source/TextInputSemanticsObject.mm index f258367ae7f84..4d69d169faa5d 100644 --- a/shell/platform/darwin/ios/framework/Source/TextInputSemanticsObject.mm +++ b/shell/platform/darwin/ios/framework/Source/TextInputSemanticsObject.mm @@ -42,7 +42,9 @@ - (NSString*)textInRange:(UITextRange*)range { NSAssert([range isKindOfClass:[FlutterTextRange class]], @"Expected a FlutterTextRange for range (got %@).", [range class]); NSRange textRange = ((FlutterTextRange*)range).range; - NSAssert(textRange.location != NSNotFound, @"Expected a valid text range."); + if (textRange.location == NSNotFound) { + return nil; + } return [self.text substringWithRange:textRange]; } From 5b680c50c2d9dc42d1d4405d8ec0811738459003 Mon Sep 17 00:00:00 2001 From: importRyan Date: Sat, 2 Nov 2024 23:51:50 -0700 Subject: [PATCH 2/7] review: add comment linking issue --- .../darwin/ios/framework/Source/FlutterTextInputPlugin.mm | 1 + .../darwin/ios/framework/Source/TextInputSemanticsObject.mm | 1 + 2 files changed, 2 insertions(+) diff --git a/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.mm b/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.mm index c5353bd93ac64..4ea9f1f7ecb93 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.mm @@ -1291,6 +1291,7 @@ - (NSString*)textInRange:(UITextRange*)range { @"Expected a FlutterTextRange for range (got %@).", [range class]); NSRange textRange = ((FlutterTextRange*)range).range; if (textRange.location == NSNotFound) { + /// Avoids [crashes](https://github.com/flutter/flutter/issues/138464) from an assertion against NSNotFound. return nil; } // Sanitize the range to prevent going out of bounds. diff --git a/shell/platform/darwin/ios/framework/Source/TextInputSemanticsObject.mm b/shell/platform/darwin/ios/framework/Source/TextInputSemanticsObject.mm index 4d69d169faa5d..5a1029809ec41 100644 --- a/shell/platform/darwin/ios/framework/Source/TextInputSemanticsObject.mm +++ b/shell/platform/darwin/ios/framework/Source/TextInputSemanticsObject.mm @@ -43,6 +43,7 @@ - (NSString*)textInRange:(UITextRange*)range { @"Expected a FlutterTextRange for range (got %@).", [range class]); NSRange textRange = ((FlutterTextRange*)range).range; if (textRange.location == NSNotFound) { + /// Avoids [crashes](https://github.com/flutter/flutter/issues/138464) from an assertion against NSNotFound. return nil; } return [self.text substringWithRange:textRange]; From 9fe3b92c144897530edbd00b693be51fa7739ae6 Mon Sep 17 00:00:00 2001 From: importRyan Date: Thu, 7 Nov 2024 11:27:52 -0800 Subject: [PATCH 3/7] fix: linter complaint fix: missed second linter complaint --- .../darwin/ios/framework/Source/FlutterTextInputPlugin.mm | 3 ++- .../darwin/ios/framework/Source/TextInputSemanticsObject.mm | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.mm b/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.mm index 4ea9f1f7ecb93..89c65d6f29817 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.mm @@ -1291,7 +1291,8 @@ - (NSString*)textInRange:(UITextRange*)range { @"Expected a FlutterTextRange for range (got %@).", [range class]); NSRange textRange = ((FlutterTextRange*)range).range; if (textRange.location == NSNotFound) { - /// Avoids [crashes](https://github.com/flutter/flutter/issues/138464) from an assertion against NSNotFound. + /// Avoids [crashes](https://github.com/flutter/flutter/issues/138464) from an assertion + /// against NSNotFound. return nil; } // Sanitize the range to prevent going out of bounds. diff --git a/shell/platform/darwin/ios/framework/Source/TextInputSemanticsObject.mm b/shell/platform/darwin/ios/framework/Source/TextInputSemanticsObject.mm index 5a1029809ec41..131e7e12f2875 100644 --- a/shell/platform/darwin/ios/framework/Source/TextInputSemanticsObject.mm +++ b/shell/platform/darwin/ios/framework/Source/TextInputSemanticsObject.mm @@ -43,7 +43,8 @@ - (NSString*)textInRange:(UITextRange*)range { @"Expected a FlutterTextRange for range (got %@).", [range class]); NSRange textRange = ((FlutterTextRange*)range).range; if (textRange.location == NSNotFound) { - /// Avoids [crashes](https://github.com/flutter/flutter/issues/138464) from an assertion against NSNotFound. + /// Avoids [crashes](https://github.com/flutter/flutter/issues/138464) from an assertion + /// against NSNotFound. return nil; } return [self.text substringWithRange:textRange]; From 5c7daf17595858bdcfe441207ba33b0e2f59f5d9 Mon Sep 17 00:00:00 2001 From: importRyan Date: Sun, 3 Nov 2024 00:26:59 -0700 Subject: [PATCH 4/7] review: test against crash --- .../framework/Source/FlutterTextInputPluginTest.mm | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/shell/platform/darwin/ios/framework/Source/FlutterTextInputPluginTest.mm b/shell/platform/darwin/ios/framework/Source/FlutterTextInputPluginTest.mm index be00f6e1e63d4..8e93046ccab93 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterTextInputPluginTest.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterTextInputPluginTest.mm @@ -516,6 +516,19 @@ - (void)testTextInRange { XCTAssertEqual(substring.length, 0ul); } +- (void)testTextInRangeAcceptsNSNotFoundLocationGracefully { + NSDictionary* config = self.mutableTemplateCopy; + [self setClientId:123 configuration:config]; + NSArray* inputFields = self.installedInputViews; + FlutterTextInputView* inputView = inputFields[0]; + + [inputView insertText:@"text"]; + UITextRange* range = [FlutterTextRange rangeWithNSRange:NSMakeRange(NSNotFound, 0)]; + + NSString* substring = [inputView textInRange:range]; + XCTAssertNil(substring); +} + - (void)testStandardEditActions { NSDictionary* config = self.mutableTemplateCopy; [self setClientId:123 configuration:config]; From a3d596a226f2ff55f9e6ad778295b576b9096aa2 Mon Sep 17 00:00:00 2001 From: importRyan Date: Wed, 18 Dec 2024 16:45:36 -0800 Subject: [PATCH 5/7] review: add todo against newly opened issue --- .../darwin/ios/framework/Source/FlutterTextInputPlugin.mm | 5 +++-- .../darwin/ios/framework/Source/TextInputSemanticsObject.mm | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.mm b/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.mm index 89c65d6f29817..2f5c252898439 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.mm @@ -1291,8 +1291,9 @@ - (NSString*)textInRange:(UITextRange*)range { @"Expected a FlutterTextRange for range (got %@).", [range class]); NSRange textRange = ((FlutterTextRange*)range).range; if (textRange.location == NSNotFound) { - /// Avoids [crashes](https://github.com/flutter/flutter/issues/138464) from an assertion - /// against NSNotFound. + // Avoids [crashes](https://github.com/flutter/flutter/issues/138464) from an assertion + // against NSNotFound. + // TODO(hellohuanlin): root cause https://github.com/flutter/flutter/issues/160100 return nil; } // Sanitize the range to prevent going out of bounds. diff --git a/shell/platform/darwin/ios/framework/Source/TextInputSemanticsObject.mm b/shell/platform/darwin/ios/framework/Source/TextInputSemanticsObject.mm index 131e7e12f2875..674d653dadd87 100644 --- a/shell/platform/darwin/ios/framework/Source/TextInputSemanticsObject.mm +++ b/shell/platform/darwin/ios/framework/Source/TextInputSemanticsObject.mm @@ -43,8 +43,9 @@ - (NSString*)textInRange:(UITextRange*)range { @"Expected a FlutterTextRange for range (got %@).", [range class]); NSRange textRange = ((FlutterTextRange*)range).range; if (textRange.location == NSNotFound) { - /// Avoids [crashes](https://github.com/flutter/flutter/issues/138464) from an assertion - /// against NSNotFound. + // Avoids [crashes](https://github.com/flutter/flutter/issues/138464) from an assertion + // against NSNotFound. + // TODO(hellohuanlin): root cause https://github.com/flutter/flutter/issues/160100 return nil; } return [self.text substringWithRange:textRange]; From 4229674c9dc163634c2bed89f632f9a234545ee2 Mon Sep 17 00:00:00 2001 From: importRyan Date: Wed, 18 Dec 2024 18:48:33 -0800 Subject: [PATCH 6/7] chore: trigger ci again as I lack a button --- .../darwin/ios/framework/Source/TextInputSemanticsObject.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shell/platform/darwin/ios/framework/Source/TextInputSemanticsObject.mm b/shell/platform/darwin/ios/framework/Source/TextInputSemanticsObject.mm index 674d653dadd87..5d30415449bf6 100644 --- a/shell/platform/darwin/ios/framework/Source/TextInputSemanticsObject.mm +++ b/shell/platform/darwin/ios/framework/Source/TextInputSemanticsObject.mm @@ -45,7 +45,7 @@ - (NSString*)textInRange:(UITextRange*)range { if (textRange.location == NSNotFound) { // Avoids [crashes](https://github.com/flutter/flutter/issues/138464) from an assertion // against NSNotFound. - // TODO(hellohuanlin): root cause https://github.com/flutter/flutter/issues/160100 + // TODO(hellohuanlin): https://github.com/flutter/flutter/issues/160100 return nil; } return [self.text substringWithRange:textRange]; From c4e7b738f676346e8bcf8bba407169c029ff158c Mon Sep 17 00:00:00 2001 From: importRyan Date: Thu, 19 Dec 2024 11:46:36 -0800 Subject: [PATCH 7/7] review: comment contents --- .../darwin/ios/framework/Source/FlutterTextInputPlugin.mm | 4 +++- .../darwin/ios/framework/Source/TextInputSemanticsObject.mm | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.mm b/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.mm index 2f5c252898439..4ba6ed66a58a6 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.mm @@ -1293,7 +1293,9 @@ - (NSString*)textInRange:(UITextRange*)range { if (textRange.location == NSNotFound) { // Avoids [crashes](https://github.com/flutter/flutter/issues/138464) from an assertion // against NSNotFound. - // TODO(hellohuanlin): root cause https://github.com/flutter/flutter/issues/160100 + // TODO(hellohuanlin): This is a temp workaround, but we should look into why + // framework is providing NSNotFound to the engine. + // https://github.com/flutter/flutter/issues/160100 return nil; } // Sanitize the range to prevent going out of bounds. diff --git a/shell/platform/darwin/ios/framework/Source/TextInputSemanticsObject.mm b/shell/platform/darwin/ios/framework/Source/TextInputSemanticsObject.mm index 5d30415449bf6..0057d05e0effc 100644 --- a/shell/platform/darwin/ios/framework/Source/TextInputSemanticsObject.mm +++ b/shell/platform/darwin/ios/framework/Source/TextInputSemanticsObject.mm @@ -45,7 +45,9 @@ - (NSString*)textInRange:(UITextRange*)range { if (textRange.location == NSNotFound) { // Avoids [crashes](https://github.com/flutter/flutter/issues/138464) from an assertion // against NSNotFound. - // TODO(hellohuanlin): https://github.com/flutter/flutter/issues/160100 + // TODO(hellohuanlin): This is a temp workaround, but we should look into why + // framework is providing NSNotFound to the engine. + // https://github.com/flutter/flutter/issues/160100 return nil; } return [self.text substringWithRange:textRange];