Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Conversation

@dnfield
Copy link
Contributor

@dnfield dnfield commented Apr 25, 2019

Factored out a couple sanitization methods into FML so that Desktop can use them and we can unit test them more easily.

See flutter/flutter#31468 and the linked issues from that for an attempt to fix this on the framework side.

Root cause:

  • On iOS, it's possible to get the cursor at any byte position in the strong once you're at the second line of a multi-line text field (Caret is able to select within emoji characters on the second line of text with emojis flutter#24802)
  • In this case, typing will end up inserting bytes into the middle of what is meant to be a single unicode sequence, creating an invalid UTF string.
  • We were handling this property for incrementing or decrementing the position, but not for setting the selection. The meat of this patch is adding the sanitiztion to set selection.
  • When we go to encode or decode this to JSON, we hit an assert (because the JSON codec on iOS is not tolerant of invalid UTF), and the app crashes.

This fixes the input handling on iOS so we don't crash, and makes flutter/flutter#24802 not be a crasher.

Fixes flutter/flutter#31525

@dnfield
Copy link
Contributor Author

dnfield commented Apr 25, 2019

/cc @dansunhappy @songfei

@dnfield dnfield mentioned this pull request Apr 25, 2019
9 tasks
@dnfield dnfield requested a review from GaryQian April 25, 2019 23:13
@dnfield
Copy link
Contributor Author

dnfield commented Apr 25, 2019

To be clear: we still need to fix the cursor positioning logic in Dart side, but this makes it slightly less bad.


// Helper to get the correct boundary of a character position in an NSString
// given a byte index.
NSRange rangeForCharacterAtIndex(NSString* text, NSUInteger index);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here and elsewhere, please use CapitalCase.


namespace fml {

// Helper to get the correct boundary of a character position in an NSString
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: here and below |NSString| etc. for identifiers.

namespace fml {

// Helper to get the correct boundary of a character position in an NSString
// given a byte index.
Copy link
Member

@cbracken cbracken Apr 25, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider rephrasing as Returns the range of the grapheme cluster in which |index| is located.

Generally, starting with a third-person verb tends to encourage comments that focus on what the code does. I'd also avoid the use of the word 'character' as it's pretty ambiguous. Similar below.

I'd also document behaviour in cases where index is invalid.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The underlying impelementation throws an exception (NSInvalidArgumentException). Is that fair for us to just do?

Copy link
Member

@cbracken cbracken left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM stamp from a Japanese personal seal

LGTM modulo nits + a test for naughty indices.

[view setSelectedTextRange:[FlutterTextRange rangeWithNSRange:NSMakeRange(1, 0)]];
FlutterTextRange* selectedRange = (FlutterTextRange*)[view selectedTextRange];
EXPECT_EQ(selectedRange.range.location, 2);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add tests for bogus indices.

@dnfield dnfield requested a review from cbracken April 25, 2019 23:53
Copy link
Member

@cbracken cbracken left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-LGTM

namespace fml {

NSRange RangeForCharacterAtIndex(NSString* text, NSUInteger index) {
if (text == nil || index > text.length) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd be tempted to use index >= text.length for consistency with Apple's APIs. It also feels a bit more intuitive: the underlying string has no character at index == length.

That said, text positions do allow for end-of-string positions. If every call to this is expected to have to defend against end-of-string positions, then it probably makes sense as-is, but I'd definitely document the range of valid indices in the header.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll go with >=, good catch.

@dnfield dnfield merged commit 57bf1c0 into flutter:master Apr 26, 2019
@dnfield dnfield deleted the ios_cursor_crash branch April 26, 2019 22:43
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Apr 26, 2019
engine-flutter-autoroll added a commit to flutter/flutter that referenced this pull request Apr 27, 2019
flutter/engine@e0bda06...7f753f8

git log e0bda06..7f753f8 --no-merges --oneline
7f753f8 Roll src/third_party/dart 6c3a91f281..c46deebfb6 (3 commits)
57bf1c0 Fix crash when cursor ends up at invalid position (flutter/engine#8747)

The AutoRoll server is located here: https://autoroll.skia.org/r/flutter-engine-flutter-autoroll

Documentation for the AutoRoller is here:
https://skia.googlesource.com/buildbot/+/master/autoroll/README.md

If the roll is causing failures, please contact the current sheriff ([email protected]), and stop
the roller if necessary.
Copy link
Member

@cbracken cbracken left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm to the fix! Thank you sir!

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

iOS crash if platform message has invalid UTF8

4 participants