Fix NSRangeException crash in updateCodeBlockSelection after document swap - #151
Merged
luca-chen198 merged 1 commit intoAug 12, 2026
Conversation
… swap updateCodeBlockSelection reads cachedCodeBlockTokens (ranges from a previous parse) and calls substring(with:) against the text view's CURRENT string. When the host swaps documents and the new text is shorter than the old one, an async-queued update from updateNSView can still run with the stale cached tokens; their ranges exceed the new string's length, so -[NSString substringWithRange:] raises an NSRangeException and the process aborts (SIGABRT). Guard each cached token's range and contentRange against the current string length and skip stale ones — the next parse refreshes the cache and the copy-button overlays reappear with correct geometry. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Crash
A macOS app embedding this package crashes with SIGABRT via an uncaught
NSRangeExceptionfrom-[NSString substringWithRange:]. Faulting stack from a real .ips crash report:Root cause
In
Sources/MarkdownEngine/TextView/Coordinator/NativeTextViewCoordinator+CodeBlocks.swift,updateCodeBlockSelectionreadscachedCodeBlockTokens— token ranges produced by a previous parse — and callsnsText.substring(with: token.contentRange)against the text view's current string.When the host swaps documents and the new text is shorter than the old one, an async-queued update from
updateNSViewcan run with the stale cached tokens. Their ranges exceed the new string's length, sosubstringWithRange:raisesNSRangeExceptionand the process aborts. Any document-switch path can trigger it.Reproduction sketch
updateCodeBlockSelectioncall still holds the old parse's token cache, whose ranges are out of bounds for the new string → crash.Fix
Add a bounds guard at the top of the
compactMapclosure that skips tokens whoserangeorcontentRangeextends past the current string length. Stale tokens are only possible for one async hop after a document swap; the next parse refreshes the cache and the copy-button overlays come back with correct geometry.🤖 Generated with Claude Code