Skip to content

fix(macOS): validate cached find range before Replace#245

Draft
cursor[bot] wants to merge 1 commit into
mainfrom
cursor/recent-commits-critical-bugs-5dfa
Draft

fix(macOS): validate cached find range before Replace#245
cursor[bot] wants to merge 1 commit into
mainfrom
cursor/recent-commits-critical-bugs-5dfa

Conversation

@cursor
Copy link
Copy Markdown

@cursor cursor Bot commented May 9, 2026

Bug and impact

Replace in the in-note find bar used cached highlight NSRanges without confirming the underlying text still matched the search query. After the user edits the note, reapplySearchHighlights() only skips out-of-bounds ranges when re-applying yellow backgrounds; it does not shrink or invalidate the cached array. A range can remain in bounds but point at the wrong substring (e.g. the old offset now spans "orld" instead of "test"). Replace would then substitute the replacement string into the wrong part of the document — silent data corruption with a plausible everyday trigger (find a word, edit earlier in the line, press Replace).

Root cause

replaceCurrentMatch read lastSearchHighlightRanges[focusIndex] and called replaceCharacters after shouldChangeText, with no check that storage.string.substring(with: range) still matched the query.

Fix

  • Before mutating: require the range fits the storage, and that the substring compares equal to the query under .caseInsensitive.
  • If validation fails, the replace is a no-op (same trade-off as other stale UI states).

Validation

  • Added FindReplaceSafetyTests.test_replaceCurrent_skipsWhenCachedRangeNoLongerContainsQuery, which reproduces the stale-offset scenario by applying highlights, mutating the prefix of the string via NSTextStorage, then posting .replaceCurrentMatch; the document must stay unchanged.
  • macOS XCTest / Xcode build was not executed in this Linux agent environment; please run the Synapse test target locally to confirm.
Open in Web View Automation 

Replace Current used lastSearchHighlightRanges without checking that the
range still covers the search string. After edits, reapplySearchHighlights
skips out-of-bounds ranges but leaves stale in-bounds ranges in the cache,
so Replace could corrupt unrelated text. Require bounds and a
case-insensitive match before mutating.

Adds FindReplaceSafetyTests regression coverage.

Co-authored-by: Danny Peck <dannypeck@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant