flutter / flutter/flutter

[Flutter 3.44.8] SkParagraph crash in ParagraphImpl::cluster with U+061C and font fallback

Open
#190,569 5 comments 0 reactions 0 assignees View on GitHub
a: text input c: crash c: fatal crash dependency: skia engine P2 team-text-input triaged-text-input
Dominant language
Dart
Stars
179k
Forks
31.1k
PR merge metrics
PR metrics pending

Description

### Is there an existing issue for this?

- [x] I searched the existing issues.
- [x] This looks closely related to #135003, but that issue was closed as fixed in a newer version. This crash was observed on Flutter 3.44.8 and the top frame is now `ParagraphImpl::cluster`.

### Minimal reduced reproduction

A two-line, fully anonymized text value now reproduces the crash consistently:

```dart
const String text =
'purple toaster +\u061C\n'
'cloudy bicycle orchestra';
```

The visible text is ASCII-only; the first line ends with U+061C ARABIC LETTER MARK.

The crash reproduces in a plain multiline `TextField` with a normal `TextEditingController`. No custom formatter, controller subclass, styled spans, CSV parsing, or large input is required. The value is assigned one second after launch:

```dart
controller.value = const TextEditingValue(
text: 'purple toaster +\u061C\ncloudy bicycle orchestra',
selection: TextSelection.collapsed(offset: 42),
composing: TextRange.empty,
);
```

The `TextField` is rendered under this application font configuration (the named font families are bundled as Flutter assets):

```dart
ThemeData(
useMaterial3: true,
fontFamily: 'NotoSansMonoDigits',
fontFamilyFallback: const [
'Inter',
'NotoSansArabic',
'NotoSansArmenian',
'NotoSansDevanagari',
'NotoSansGeorgian',
'NotoSansGujarati',
'NotoSansHebrew',
'NotoSansJP',
'NotoSansKR',
'NotoSansSC',
'NotoSansTamil',
'NotoSansTC',
'NotoSansTelugu',
'NotoSansThai',
'NotoSans',
'LibertinusMath',
],
);
```

Observed on Flutter 3.44.8/macOS:

- First line alone (`purple toaster +\u061C`): **does not crash**.
- Both lines together (42 characters total): **consistently crashes**.
- The same two lines after removing U+061C: **does not crash**.
- The complete original 7,658-line input also crashes with the same native stack.
- The complete input after stripping invisible formatting characters remains running.
- A plain `TextField` with the default Material font configuration did not reproduce, so font selection/fallback is part of the trigger.

### Expected results

Text input should not terminate the process, regardless of Unicode bidi/control characters or font fallback.

### Actual results

The macOS process terminates with `EXC_BREAKPOINT (SIGTRAP)` on the main thread inside SkParagraph:

```
0 FlutterMacOS skia::textlayout::ParagraphImpl::cluster(unsigned long) + 96
1 FlutterMacOS skia::textlayout::TextLine::measureTextInsideOneRun(...) const + 724
2 FlutterMacOS skia::textlayout::TextLine::iterateThroughSingleRunByStyles(...) const + 544
3 FlutterMacOS skia::textlayout::TextLine::ensureTextBlobCachePopulated()::$_0::operator()(...) + 144
4 FlutterMacOS skia::textlayout::TextLine::iterateThroughVisualRuns(...) const + 500
5 FlutterMacOS skia::textlayout::TextLine::ensureTextBlobCachePopulated() + 180
6 FlutterMacOS skia::textlayout::TextLine::paint(...) + 224
7 FlutterMacOS skia::textlayout::ParagraphImpl::paint(...) + 92
8 FlutterMacOS txt::ParagraphSkia::Paint(...) + 84
```

### Workaround / additional context

Stripping invisible formatting characters before they reach the text rendering path prevents the crash in the application. The source data also contained U+2063 INVISIBLE SEPARATOR and U+2064 INVISIBLE PLUS, but neither is required for the reduced two-line reproduction above.

Related issue: #135003

### Flutter Doctor output

```console
[✓] Flutter (Channel stable, 3.44.8, on macOS 15.6.1 24G90 darwin-arm64, locale en-KZ)
• Flutter version 3.44.8 on channel stable
• Framework revision 058e0af2c2
• Engine revision 0cd610717b
• Dart version 3.12.2
• DevTools version 2.57.0

[✓] Xcode - develop for iOS and macOS (Xcode 26.3)
• Build 17C529
• CocoaPods version 1.16.2

• No issues found!
```

Contributor guide

Open the contributing guide

Research direction

Start by reproducing the reduced Dart TextField case with U+061C and the listed font fallback configuration, then compare it with the one-line and stripped-character variants. Trace the native stack from txt::ParagraphSkia::Paint through ParagraphImpl::cluster and inspect the related issue #135003. Done means the reduced input no longer terminates the macOS process while preserving text rendering.

Written by the indexing model from the issue text.

Assessment

Tech stack
dart, macos
Domain
computer-graphics
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
64/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.