Repository navigation
🐞 Fix crash when searching the action picker in non-English languages - #1193
NicoCorini wants to merge 1 commit into
Conversation
DirectionPickerView.fuzzyScore advanced the pattern's index with text.index(after:). A String.Index remembers how wide the character at that position is in the string it came from, so when an action name has a multi-byte character (e.g. "à" in the Italian "Metà inferiore"), the next lookup in the search text read past its end and trapped. Advance the index with pattern.index(after:) instead. fuzzyScore is now static so it can be unit tested, and DirectionPickerSearchTests covers the regression. Fixes mrkai77#1187
|
I'm unable to recreate this crash. Could you attach a screen recording of the version you're testing with (so, about > version) and any typed queries that cause the crash? |
Sure, recording attached: Loop 🧪 1.4.3 (1783), macOS 15.8.1, system language Italian. The About window at the start shows the version, and the macOS crash dialog at the end shows The key detail is the language: the crash only happens when action names contain non-ASCII characters, so it won't reproduce in English. To reproduce:
It also crashes with German, French, Spanish, Portuguese (BR) and Polish action names. Without the fix, the regression test loop-1187-crash.mp4 |
Description
Typing in the keybind action picker's search field could crash Loop (SIGILL in
String.subscript.getter) when the UI language has accented action names. In English every name is ASCII, so it never shows up there.The subsequence matcher in
fuzzyScoremoved the pattern's index forward using the action name:while tIndex < text.endIndex, pIndex < pattern.endIndex { if text[tIndex] == pattern[pIndex] { - pIndex = text.index(after: pIndex) + pIndex = pattern.index(after: pIndex) } tIndex = text.index(after: tIndex) }A
String.Indexremembers the width of the character it points to in the string it came from. For example, with the name "Metà inferiore" and the search "meta", after matchingm,e,tthe index lands on byte 3, which in the name is the 2-byte "à". Reading the 4-byte search text at that index then goes past its end and traps.Apart from the one-line fix:
fuzzyScoreis nowstatic(it uses no view state), so the tests can call it.LoopTests/DirectionPickerSearchTests.swift, covering the prefix, substring and subsequence scores plus the regression.Side effect: some searches containing accented letters that silently returned no results now match correctly (e.g. "mà ie" → "Metà inferiore"). Scores for ASCII names are unchanged.
Fixes #1187
How has this been tested?
macOS Sequoia 15.8.1, Intel MacBook Pro.
DirectionPickerSearchTests: before the fix,fuzzyScore("Metà inferiore", "meta")crashes the test host with the same stack as the issue (String.subscript.getter←fuzzyScore). After the fix all 6 tests pass.fuzzyScoreagainst every localized action name fromLocalizable.xcstringswith random search strings: the old code crashes for it, de, fr, es, pt-BR and pl; the fixed code never crashes.-AppleLanguages (it)): typed and deleted many strings, including "meta" and accented ones, in Keybinds → Add → action picker. No crash.Two things I noticed while testing, not touched in this PR:
develop,LoopTestsdoesn't build becauseCycleProgressStoreTests.swiftuses API that no longer exists onCycleProgressStore. I temporarily moved that file out locally to run the tests.AppDelegate).Checklist:
Please describe to which degree, if any, an LLM was used in creating this pull request.
I used Claude (Claude Code) to read the crash reports and the source, write a small harness that reproduced the crash outside the app, and draft the fix, the tests and this description. A separate Claude instance reviewed the diff. I reproduced the original crash myself, verified the fix manually in the app, and reviewed and edited all code and text.