-
Notifications
You must be signed in to change notification settings - Fork 29.7k
[CP-stable] Fix crash when NSAttributedString is passed to insertText on macOS #176329
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[CP-stable] Fix crash when NSAttributedString is passed to insertText on macOS #176329
Conversation
Fixes a crash that occurs when the text input system passes an NSAttributedString instead of NSString to the insertText:replacementRange: method in FlutterTextInputPlugin. The insertText:replacementRange: method can receive either NSString or NSAttributedString as per the NSTextInputClient protocol documentation. The previous implementation directly called UTF8String on the string parameter without checking its type, which caused a crash when an NSAttributedString was passed, as NSAttributedString doesn't respond to the UTF8String selector. This fix adds type checking to extract the underlying NSString from NSAttributedString before converting to UTF8, following the same pattern already used in the setMarkedText:selectedRange:replacementRange: method in the same file. Crash stack trace: -[NSConcreteMutableAttributedString UTF8String]: unrecognized selector sent to instance 0x6000017e7300
|
It looks like this pull request may not have tests. Please make sure to add tests or get an explicit test exemption before merging. If you are not sure if you need tests, consider this rule of thumb: the purpose of a test is to make sure someone doesn't accidentally revert the fix. Ask yourself, is there anything in your PR that you feel it is important we not accidentally revert back to how it was before your fix? Reviewers: Read the Tree Hygiene page and make sure this patch meets those guidelines before LGTMing. If you believe this PR qualifies for a test exemption, contact "@test-exemption-reviewer" in the #hackers channel in Discord (don't just cc them here, they won't see it!). The test exemption team is a small volunteer group, so all reviewers should feel empowered to ask for tests, without delegating that responsibility entirely to the test exemption group. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code Review
This pull request correctly fixes a crash that occurs when an NSAttributedString is passed to insertText:replacementRange:. The approach of checking the type and extracting the underlying NSString is sound and follows existing patterns in the file.
I've added one comment to further improve the robustness of the implementation by handling potential nil input, which could otherwise lead to a crash.
engine/src/flutter/shell/platform/darwin/macos/framework/Source/FlutterTextInputPlugin.mm
Outdated
Show resolved
Hide resolved
…e/FlutterTextInputPlugin.mm Checks if UTF8String returns NULL before constructing std::string. Uses empty string as fallback to prevent crashes from nil input." Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
|
Hello, could you add some tests? In the mean time I'm converting this to draft. |
Adds test coverage for insertText:replacementRange: to verify: - NSAttributedString is correctly converted to NSString - nil input is handled safely without crashes - Empty NSAttributedString is processed correctly
|
@hellohuanlin I added some tests. |
Remove InsertTextHandlesNilString test as it violates NSTextInputClient protocol contract where string parameter must be non-null.
LongCatIsLooong
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. Thanks for the fix!
|
@LongCatIsLooong could you look into the Google testing failure? |
|
The test failures don't seem to be related. I re-ran them and in case they don't fix themselves we can override the that CI check. |
|
@LongCatIsLooong Could you please update the status? |
|
I overrode the google testing. This PR needs one more approval to be merged. In case this misses the release cutoff date, feel free to request a cherrypick (the process is automated: https://github.com/flutter/flutter/blob/master/docs/releases/Flutter-Cherrypick-Process.md) |
vashworth
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM! Thanks for PR!
|
autosubmit label was removed for flutter/flutter/176329, because The base commit of the PR is older than 7 days and can not be merged. Please merge the latest changes from the main into this branch and resubmit the PR. |
Roll Flutter from a873a27309b0 to 891d7d539256 (32 revisions) flutter/flutter@a873a27...891d7d5 2025-10-18 [email protected] Roll Skia from b4981b621a54 to 74df18176924 (1 revision) (flutter/flutter#177204) 2025-10-18 [email protected] Roll Fuchsia Linux SDK from ZHuhfPyyV-LcKDLRh... to M8WT2GMY46e_0fFho... (flutter/flutter#177200) 2025-10-18 [email protected] [material/dropdown_menu.dart] Refactor _RenderDropdownMenuBody.computeDryLayout (flutter/flutter#176503) 2025-10-18 [email protected] Roll Skia from 579c72d673dd to b4981b621a54 (2 revisions) (flutter/flutter#177199) 2025-10-17 [email protected] Roll Skia from 89a8bc508a7c to 579c72d673dd (15 revisions) (flutter/flutter#177194) 2025-10-17 [email protected] [test_fixes] Enable `deprecated_member_use_from_same_package`. (flutter/flutter#177183) 2025-10-17 [email protected] [a11y] fix table semantics cache for cells (flutter/flutter#177073) 2025-10-17 [email protected] [web] Self-cleaning service worker (flutter/flutter#176834) 2025-10-17 [email protected] Manual roll Skia from 2d9df7c70b6f to 89a8bc508a7c (24 revisions) (flutter/flutter#177182) 2025-10-17 [email protected] Fixing WindowManagerTest::DialogCanNeverBeFullscreen possibly hanging (flutter/flutter#177179) 2025-10-17 [email protected] [VPAT][A11y][a11y-app] Add a text label to slider. (flutter/flutter#177130) 2025-10-17 [email protected] Manual roll Dart SDK from a4485e5ef821 to a66f334fee2a (5 revisions) (flutter/flutter#177142) 2025-10-17 [email protected] [web][a11y] Fix the semantics tree reconstruction logic when a subtree is reparented to another node. (flutter/flutter#177069) 2025-10-17 [email protected] `SelectableRegion` should use flutter rendered menu on the web for Android and iOS (flutter/flutter#177122) 2025-10-17 [email protected] Refactor: Convert Title widget to StatefulWidget (flutter/flutter#176010) 2025-10-17 [email protected] Bump AGP, KGP, Gradle Templates (flutter/flutter#176858) 2025-10-17 [email protected] Roll Packages from 835dccb to 3747006 (3 revisions) (flutter/flutter#177170) 2025-10-17 [email protected] Mark windows_unopt test as flakey (flutter/flutter#177173) 2025-10-17 [email protected] Tapping outside of `SelectableRegion` should dismiss the selection (flutter/flutter#176843) 2025-10-17 [email protected] Roll Fuchsia Linux SDK from _dd0Jv50H0oUI2Ad8... to ZHuhfPyyV-LcKDLRh... (flutter/flutter#177137) 2025-10-17 [email protected] Manual roll Dart to a4485e5ef821 (3.11.0-25.0.dev) (flutter/flutter#177132) 2025-10-17 [email protected] Make sure that a MenuAcceleratorLabel doesn't crash in 0x0 environment (flutter/flutter#176646) 2025-10-16 [email protected] Make sure that a NavigationRail doesn't crash in 0x0 environment (flutter/flutter#177022) 2025-10-16 [email protected] Make sure that a SubmenuButton doesn't crash in 0x0 environment (flutter/flutter#176535) 2025-10-16 [email protected] Fix typo in ButtonBar documentation (flutter/flutter#177078) 2025-10-16 [email protected] Make sure that an InkResponse doesn't crash in 0x0 environment (flutter/flutter#175426) 2025-10-16 [email protected] [Gradle 9] Resolve Gradle 9 Deprecations in flutter/flutter part 1 (flutter/flutter#176865) 2025-10-16 [email protected] Revert "Resolve resolve native Flutter dependencies in Android Studio (#167332)" (flutter/flutter#177053) 2025-10-16 [email protected] Manual roll Dart SDK from 2d8e0359a767 to 25b6094026e4 (5 revisions) (flutter/flutter#177109) 2025-10-16 [email protected] Add textfield prop to SearchAnchor (flutter/flutter#174497) 2025-10-16 [email protected] Fix crash when NSAttributedString is passed to insertText on macOS (flutter/flutter#176329) 2025-10-16 [email protected] Correct basque time format (flutter/flutter#177031) If this roll has caused a breakage, revert this CL and stop the roller using the controls here: https://autoroll.skia.org/r/flutter-packages Please CC [email protected],[email protected] on the revert to ensure that a human is aware of the problem. To file a bug in Packages: https://github.com/flutter/flutter/issues/new/choose To report a problem with the AutoRoller itself, please file a bug: https://issues.skia.org/issues/new?component=1389291&template=1850622 Documentation for the AutoRoller is here: https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md ...
|
@p1318k based on the tags on the commit, it looks like it didn't make it into the latest beta release. Could you try out the automated cherry-pick process if you're still interested in getting the commit into the stable release? AFAIK you'll have to request a CP to the beta channel, once that's done the next stable release should include this fix too. |
|
@LongCatIsLooong , thank you for the reminder. I have added the “CP-stable” prefix to the title as you guided. |
I think the "label" in the wiki page refers to "github labels" not PR titles. IIRC in the GitHub web UI it's close to where you add new PR reviewers. |
|
@LongCatIsLooong I don’t seem to have permission to add labels. Could you please add them for me? |
|
The faq section says anyone can request a cherry pick. Let me check tomorrow. |
|
@LongCatIsLooong my previous PR was cherry-picked by a Googler, who then added the 'cp: stable' label to it. |
…lutter#176329) ## Description This PR fixes a crash in the macOS text input plugin that occurs when `NSAttributedString` is passed to the `insertText:replacementRange:` method instead of `NSString`. ### Root Cause The `insertText:replacementRange:` method of `NSTextInputClient` protocol can receive either `NSString` or `NSAttributedString`. The previous implementation directly called `UTF8String` on the input parameter without type checking. Since `NSAttributedString` doesn't respond to the `UTF8String` selector, this caused a crash with the error: -[NSConcreteMutableAttributedString UTF8String]: unrecognized selector sent to instance ### Changes Made - Added type checking to determine if the input is `NSAttributedString` - Extract the underlying `NSString` using `[string string]` before calling `UTF8String` - This follows the same pattern already implemented in the `setMarkedText:selectedRange:replacementRange:` method in the same file ### Crash Stack Trace Thread 0 Crashed: 0 CoreFoundation __exceptionPreprocess 1 libobjc.A.dylib objc_exception_throw 2 CoreFoundation -[NSObject(NSObject) doesNotRecognizeSelector:] 3 FlutterMacOS -[FlutterTextInputPlugin insertText:replacementRange:] (FlutterTextInputPlugin.mm:784) 4 AppKit -[NSTextInputContext(NSInputContext_WithCompletion) insertText:replacementRange:completionHandler:] ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. **Note**: The Flutter team is currently trialing the use of [Gemini Code Assist for GitHub](https://developers.google.com/gemini-code-assist/docs/review-github-code). Comments from the `gemini-code-assist` bot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md --------- Co-authored-by: Kim Ki Cheol <[email protected]> Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
…n macOS (#177401) This pull request is created by [automatic cherry pick workflow](https://github.com/flutter/flutter/blob/main/docs/releases/Flutter-Cherrypick-Process.md#automatically-creates-a-cherry-pick-request) Please fill in the form below, and a flutter domain expert will evaluate this cherry pick request. ### Issue Link: What is the link to the issue this cherry-pick is addressing? There does not appear to be a dedicated issue. The issue description can be found in the PR description: #176329 The PR fixes a macOS text input crash caused by down-casting the string argument from `Any` to a `NSString`, from [this API](https://developer.apple.com/documentation/appkit/nstextinputclient/inserttext(_:replacementrange:)#parameters). The documentation says it can either be a `NSString` or `NSAttributedString` ### Changelog Description: Explain this cherry pick in one line that is accessible to most Flutter developers. See [best practices](https://github.com/flutter/flutter/blob/main/docs/releases/Hotfix-Documentation-Best-Practices.md) for examples > Fixes a crash on macOS when the input method (or other services) inserts a `NSAttributedString` instead of `NSString` into a text field. ### Impact Description: What is the impact (ex. visual jank on Samsung phones, app crash, cannot ship an iOS app)? Does it impact development (ex. flutter doctor crashes when Android Studio is installed), or the shipping production app (the app crashes on launch) App crashes on macOS when interacting with certain IMEs or other system services, if they decided to use `NSAttributedString` instead of `NSString`. It affects production apps. ### Workaround: Is there a workaround for this issue? None. Users or app developers have little control over what the IME / services decide to do. The problematic code path in the engine directly interacts with system services so app developer can't workaround that. ### Risk: What is the risk level of this cherry-pick? ### Test Coverage: Are you confident that your fix is well-tested by automated tests? ### Validation Steps: What are the steps to validate that this fix works? The PR description does not have repro steps. @p1318k could you add the steps to trigger the bug here?
…lutter#176329) ## Description This PR fixes a crash in the macOS text input plugin that occurs when `NSAttributedString` is passed to the `insertText:replacementRange:` method instead of `NSString`. ### Root Cause The `insertText:replacementRange:` method of `NSTextInputClient` protocol can receive either `NSString` or `NSAttributedString`. The previous implementation directly called `UTF8String` on the input parameter without type checking. Since `NSAttributedString` doesn't respond to the `UTF8String` selector, this caused a crash with the error: -[NSConcreteMutableAttributedString UTF8String]: unrecognized selector sent to instance ### Changes Made - Added type checking to determine if the input is `NSAttributedString` - Extract the underlying `NSString` using `[string string]` before calling `UTF8String` - This follows the same pattern already implemented in the `setMarkedText:selectedRange:replacementRange:` method in the same file ### Crash Stack Trace Thread 0 Crashed: 0 CoreFoundation __exceptionPreprocess 1 libobjc.A.dylib objc_exception_throw 2 CoreFoundation -[NSObject(NSObject) doesNotRecognizeSelector:] 3 FlutterMacOS -[FlutterTextInputPlugin insertText:replacementRange:] (FlutterTextInputPlugin.mm:784) 4 AppKit -[NSTextInputContext(NSInputContext_WithCompletion) insertText:replacementRange:completionHandler:] ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. **Note**: The Flutter team is currently trialing the use of [Gemini Code Assist for GitHub](https://developers.google.com/gemini-code-assist/docs/review-github-code). Comments from the `gemini-code-assist` bot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md --------- Co-authored-by: Kim Ki Cheol <[email protected]> Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Description
This PR fixes a crash in the macOS text input plugin that occurs when
NSAttributedStringis passed to theinsertText:replacementRange:method instead ofNSString.Root Cause
The
insertText:replacementRange:method ofNSTextInputClientprotocol can receive eitherNSStringorNSAttributedString. The previous implementation directly calledUTF8Stringon the input parameter without type checking. SinceNSAttributedStringdoesn't respond to theUTF8Stringselector, this caused a crash with the error:-[NSConcreteMutableAttributedString UTF8String]: unrecognized selector sent to instance
Changes Made
NSAttributedStringNSStringusing[string string]before callingUTF8StringsetMarkedText:selectedRange:replacementRange:method in the same fileCrash Stack Trace
Thread 0 Crashed: 0 CoreFoundation __exceptionPreprocess 1 libobjc.A.dylib objc_exception_throw 2 CoreFoundation -[NSObject(NSObject) doesNotRecognizeSelector:] 3 FlutterMacOS -[FlutterTextInputPlugin insertText:replacementRange:] (FlutterTextInputPlugin.mm:784) 4 AppKit -[NSTextInputContext(NSInputContext_WithCompletion) insertText:replacementRange:completionHandler:]
Pre-launch Checklist
///).If you need help, consider asking for advice on the #hackers-new channel on Discord.
Note: The Flutter team is currently trialing the use of Gemini Code Assist for GitHub. Comments from the
gemini-code-assistbot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed.