react / react/react-native

[Android][0.87.1] numberOfLines crashes when a decorated nested Text range is outside the truncated layout

Ouverte
#58,356 0 commentaires 0 réactions 0 personnes assignées Voir sur GitHub

Personne n'a encore pris cette issue.

Needs: Triage :mag: Platform: Android
Langage dominant
C++
Étoiles
127k
Forks
25.3k
Merge moyen
1 j 23 h
PR mergées (30 j)
4

Description

Description

On Android, a Text with numberOfLines can crash the application when a nested Text has textDecorationLine: 'underline' or 'line-through' and the decorated range starts after content that is omitted by the truncated native layout.

Both decoration types fail in the same native drawing path. This is a fatal main-thread exception rather than a redbox or a JavaScript error.

Additional context

drawSpannedDecoration() obtains start and end from the complete Spanned text, then calls layout.getPrimaryHorizontal(start/end). With numberOfLines, the native Layout can end before the decorated span. In this example, the span starts at offset 60 while the only layout line ends at offset 19, so Android throws before drawing the decoration.

Underline and line-through share this drawing function, which explains why both variants crash. A safe fix likely needs to skip or clip decoration ranges to offsets represented by the truncated Layout before calling getPrimaryHorizontal.

Relevant React Native 0.87.1 source:

This may be adjacent to #57900, which reports Android text-decoration rendering differences. This report is specifically about a fatal out-of-bounds exception caused by a decorated range outside a truncated layout.

Steps to reproduce
  1. Clone [react-native-text-decoration-crash-repro](https://github.com/ouabing/react-native-text-decoration-crash-repro).
  2. npm install.
  3. npm start.
  4. npm run android.
  5. Press Reproduce with underline or Reproduce with line-through.

The minimal trigger is:

<Text numberOfLines={1} ellipsizeMode="tail">
  {'Visible first line\n\nThird paragraph\n\nHidden decorated text: '}
  <Text style={{textDecorationLine: 'line-through'}}>
    decorated text outside the one-line layout
  </Text>
</Text>

Changing line-through to underline reproduces the same crash. Removing numberOfLines, the line breaks, or textDecorationLine avoids it.

React Native Version

0.87.1

Affected Platforms

Runtime - Android

Output of npx @react-native-community/cli info
System:
  OS: macOS 26.6.1
  CPU: Apple M1 Pro (arm64)
Binaries:
  Node: 22.13.1
  npm: 10.9.2
  Java: 17.0.16
npmPackages:
  react: 19.2.3
  react-native: 0.87.1
Android:
  Android 14 / API 34 arm64 emulator
  hermesEnabled: true
  newArchEnabled: true
Stacktrace or Logs
FATAL EXCEPTION: main
Process: com.rntextdecorationcrashrepro
java.lang.IndexOutOfBoundsException: offset(60) should be less than line limit(19)
    at android.text.TextLine.measure(TextLine.java:389)
    at android.text.Layout.getHorizontal(Layout.java:1390)
    at android.text.Layout.getHorizontal(Layout.java:1366)
    at android.text.Layout.getPrimaryHorizontal(Layout.java:1336)
    at android.text.Layout.getPrimaryHorizontal(Layout.java:1325)
    at com.facebook.react.views.text.TextDecorationStyleKt.drawSpannedDecoration(TextDecorationStyle.kt:182)
    at com.facebook.react.views.text.internal.span.ReactUnderlineSpan.onDraw(ReactUnderlineSpan.kt:31)
    at com.facebook.react.views.text.ReactTextView.drawTextEffects(ReactTextView.java:283)
    at com.facebook.react.views.text.ReactTextView.onDraw(ReactTextView.java:227)
MANDATORY Reproducer

https://github.com/ouabing/react-native-text-decoration-crash-repro

Screenshots and Videos

No response

Guide de contribution

Ouvrir le guide de contribution

Par où commencer

  1. Lisez l'issue en entier, puis le guide de contribution du projet.
  2. Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
  3. Forkez le dépôt et travaillez sur une branche.
  4. Ouvrez une pull request qui référence le numéro de l'issue.

Piste de recherche

Commencez par TextDecorationStyle.kt, en particulier les appels à getPrimaryHorizontal, puis examinez ReactUnderlineSpan.kt et ReactStrikethroughSpan.kt afin de suivre les deux chemins de décoration. Exécutez le reproducer obligatoire avec npm install, npm start et npm run android, et vérifiez que underline et line-through ne provoquent plus de crash lorsque leur plage décorée se trouve au-delà du layout tronqué.

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Évaluation

Stack technique
android, kotlin, react-native
Domaine
mobile
Type d'issue
Bug
Difficulté
3/5
Temps estimé
1-2 jours
Activité
Active
Clarté
Clairement spécifiée
Accessibilité débutants
75/100

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.