Skip to content

Crash when deleting mixed selection or using Chinese/IME keyboard #276

@GeekJC

Description

@GeekJC

Description

The app crashes with NSRangeException when:

  1. Deleting a mixed selection (normal text + formatted elements like bold, italic, etc.)
  2. Using Chinese keyboard (or other IME keyboards) and deleting text

The crash occurs in ENRMWordsUtils getAffectedWordsFromText:modificationRange: when the modificationRange exceeds the current text length, creating an invalid NSRange for rangeOfCharacterFromSet:.

Error

NSRangeException: *** -[NSTaggedPointerString rangeOfCharacterFromSet:options:range:]: Range {0, 5} out of bounds; string length 3
  3   Hopick.debug.dylib                  0x0000000109b8bce0 +[ENRMWordsUtils getAffectedWordsFromText:modificationRange:] + 344
  4   Hopick.debug.dylib                  0x0000000109b71f18 -[ENRMDetectorPipeline processTextChange:modificationRange:] + 112
  5   Hopick.debug.dylib                  0x0000000109b5e330 -[EnrichedMarkdownTextInput handleTextChanged] + 1872

Steps to Reproduce

  1. Open markdown input to write text
  2. Select text that includes both normal text and formatted elements (but not the whole input text)
  3. Press the delete key
  4. App crashes

Or with Chinese keyboard:

  1. Open markdown input
  2. Type text using Chinese keyboard
  3. Try to delete text
  4. App crashes

Root Cause

In EnrichedMarkdownTextInput.mm, the editLocation (from _preEditSelectedRange) can exceed the new text length after deletion. This out-of-bounds modificationRange is then passed to ENRMWordsUtils, which creates an invalid NSRange for rangeOfCharacterFromSet:.

Additionally, in ENRMWordsUtils.mm, the getAffectedWordsFromText:modificationRange: method doesn't validate the input range bounds before processing.

Proposed Fix

Two changes needed:

  1. In ENRMWordsUtils.mm: Add bounds checking at the start of getAffectedWordsFromText:modificationRange: to clamp the modification range to valid text bounds:
// Clamp modification range to valid text bounds
if (range.location > textLength) {
  range.location = textLength;
}
NSUInteger maxLength = textLength - range.location;
if (range.length > maxLength) {
  range.length = maxLength;
}
if (range.length == 0) {
  return @[];
}
  1. In EnrichedMarkdownTextInput.mm: Clamp editLocation to the new text length in handleTextChanged before it's used:
NSRange preEditSelection = _preEditSelectedRange;
NSUInteger editLocation = preEditSelection.location;

// Clamp editLocation to valid bounds for the new text
if (editLocation > newLength) {
  editLocation = newLength;
}

Related Issues

Related to #273

Environment

  • react-native-enriched-markdown: 0.5.0
  • Platform: iOS
  • React Native: Latest

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions