Skip to content

fix(SquirrelInputController): boundary check to prevent crash#1044

Merged
LEOYoon-Tsaw merged 3 commits intorime:masterfrom
ecstasoy:fix/inline-crash
Jul 10, 2025
Merged

fix(SquirrelInputController): boundary check to prevent crash#1044
LEOYoon-Tsaw merged 3 commits intorime:masterfrom
ecstasoy:fix/inline-crash

Conversation

@ecstasoy
Copy link
Contributor

@ecstasoy ecstasoy commented Jul 3, 2025

Make sure candidatePreview is trimmed only when it is legal
Fallback to empty string when pulling out the switcher with caption as preedit text

This seems to solve the problem mentioned in #1041

@lotem lotem requested a review from LEOYoon-Tsaw July 3, 2025 07:05
@ecstasoy ecstasoy changed the title fix(SquirrelInputController): boundary check for inlinePreedit fix(SquirrelInputController): boundary check to prevent crash Jul 3, 2025
@ecstasoy
Copy link
Contributor Author

ecstasoy commented Jul 6, 2025

关于 #1045

此前的代码中:

candidatePreview = String(candidatePreview[..<candidatePreview.index(candidatePreview.endIndex, offsetBy: -max(0, preedit.distance(from: end, to: preedit.endIndex)))])

和我之前的commit:
https://github.com/ecstasoy/squirrel/blob/b20aea24f843899fff5bc83372cacffddd818573/sources/SquirrelInputController.swift#L472

self	Squirrel.SquirrelInputController	0x000000012f6049d0
status	RimeStatus_stdbool	
ctx	RimeContext_stdbool	
preedit	String	",‸"	
start	String.Index	1[utf8]	
end	String.Index	1[utf8]	
caretPos	String.Index	1[utf8]	
candidatePreview	String	""	
trimCount	Int	1

这里会出问题:

selRange: NSRange(location: start.utf16Offset(in: candidatePreview), length: candidatePreview.utf16.distance(from: start, to: candidatePreview.endIndex)),

修改后:

self	Squirrel.SquirrelInputController	0x000000012d21f7c0
status	RimeStatus_stdbool	
ctx	RimeContext_stdbool	
preedit	String	",‸"	
start	String.Index	1[utf8]	
end	String.Index	1[utf8]	
caretPos	String.Index	1[utf8]	
candidatePreview	String	","	
trimCount	Int	0
Screenshot 2025-07-05 at 8 08 17 PM

此时符号能正常作为candidate和preedit同时出现并且不会崩溃

@ecstasoy
Copy link
Contributor Author

ecstasoy commented Jul 6, 2025

UPDATE: 编译测试一切正常且 #1041 #1045 中所述问题不再能复现。

@ecstasoy ecstasoy force-pushed the fix/inline-crash branch from b20aea2 to d66e20b Compare July 6, 2025 04:42
- make sure candidatePreview is trimmed only when it is legal
- add clamped() util function to clamp out-of-bounds values
- prevent index out-of-bounds when candidatePreview is empty
@ecstasoy ecstasoy force-pushed the fix/inline-crash branch from a751bb2 to 58f42e6 Compare July 6, 2025 09:12
@ecstasoy ecstasoy requested a review from lotem July 6, 2025 17:34
@lotem
Copy link
Member

lotem commented Jul 7, 2025

觀察輸入,原先的算法似乎不會導致越界錯誤。

我重現了崩潰,但崩潰的不是鼠鬚管,而是 Chrome。
崩潰步驟是鍵入拼音後,左移光標到輸入碼開始位置。
方案選單沒有發生崩潰。
而其他應用裏也沒有問題。

這個 PR 的改法是讓鼠鬚管無法發出導致錯誤的消息,從而規避問題。
因此要把原本光標在預覽輸入串中移動的功能廢除了。
那還不如關閉相關配置項,也可規避問題。

@lotem lotem closed this Jul 7, 2025
@lotem
Copy link
Member

lotem commented Jul 7, 2025

关于 #1045

此前的代码中:

candidatePreview = String(candidatePreview[..<candidatePreview.index(candidatePreview.endIndex, offsetBy: -max(0, preedit.distance(from: end, to: preedit.endIndex)))])

和我之前的commit:
https://github.com/ecstasoy/squirrel/blob/b20aea24f843899fff5bc83372cacffddd818573/sources/SquirrelInputController.swift#L472

self	Squirrel.SquirrelInputController	0x000000012f6049d0
status	RimeStatus_stdbool	
ctx	RimeContext_stdbool	
preedit	String	",‸"	
start	String.Index	1[utf8]	
end	String.Index	1[utf8]	
caretPos	String.Index	1[utf8]	
candidatePreview	String	""	
trimCount	Int	1

这里会出问题:

selRange: NSRange(location: start.utf16Offset(in: candidatePreview), length: candidatePreview.utf16.distance(from: start, to: candidatePreview.endIndex)),

修改后:

self	Squirrel.SquirrelInputController	0x000000012d21f7c0
status	RimeStatus_stdbool	
ctx	RimeContext_stdbool	
preedit	String	",‸"	
start	String.Index	1[utf8]	
end	String.Index	1[utf8]	
caretPos	String.Index	1[utf8]	
candidatePreview	String	","	
trimCount	Int	0
Screenshot 2025-07-05 at 8 08 17 PM 此时符号能正常作为candidate和preedit同时出现并且不会崩溃

This case seems to be a bug. I'll keep looking into it.

@lotem lotem reopened this Jul 7, 2025
@ecstasoy
Copy link
Contributor Author

ecstasoy commented Jul 7, 2025

觀察輸入,原先的算法似乎不會導致越界錯誤。

我重現了崩潰,但崩潰的不是鼠鬚管,而是 Chrome。 崩潰步驟是鍵入拼音後,左移光標到輸入碼開始位置。 方案選單沒有發生崩潰。 而其他應用裏也沒有問題。

這個 PR 的改法是讓鼠鬚管無法發出導致錯誤的消息,從而規避問題。 因此要把原本光標在預覽輸入串中移動的功能廢除了。 那還不如關閉相關配置項,也可規避問題。

这个确信是另一个问题,当inline_preedit和inline_candidate都是true的时候show()中的caretPos计算会产生负数,我之前说clamped可能还有用处就是这里,您可以再看看。

[DEBUG] rimeUpdate:
  preedit: 'ce ui' (length: 5)
  composition - sel_start: 0, sel_end: 5, cursor_pos: 0
  converted positions - start: 0, end: 5, caretPos: 0
  inline settings - inlineCandidate: true, inlinePreedit: true
  candidatePreview: '测试' (length: 2)
  Branch: inlinePreedit = true
    will append suffix: false
    final candidatePreview: '测试'
    final selRange: location=0, length=2
    caret calculation: rawOffset=5, clampedOffset=2, rawCaretPos=-3, caretPos=0

@lotem
Copy link
Member

lotem commented Jul 7, 2025

之前的測試方法不對,
設置爲

patch:
  style/inline_preedit: false
  style/inline_candidate: true

可以重現崩潰。

@lotem
Copy link
Member

lotem commented Jul 7, 2025

不如擇期重新實現吧。
這塊邏輯太複雜了,不可控。

我沒想到 LEO 老師會做這麼複雜的功能,如果給 librime 多加接口,做起來應該會容易些。

@LEOYoon-Tsaw
Copy link
Member

不如擇期重新實現吧。

這塊邏輯太複雜了,不可控。

我沒想到 LEO 老師會做這麼複雜的功能,如果給 librime 多加接口,做起來應該會容易些。

我想的是任何開關都可以任意組合,確實由librime來實現會好得多,前端就做展示,不做複雜邏輯

@ecstasoy
Copy link
Contributor Author

ecstasoy commented Jul 7, 2025

崩溃的问题还是要尽快解决的

When inlineCandidate = true and inlinePreedit = false
Control + grave result in crash
Fix rime#1041
@LEOYoon-Tsaw
Copy link
Member

Let's focus on the bug #1041 itself, don't make other changes.

@LEOYoon-Tsaw LEOYoon-Tsaw merged commit 1a70873 into rime:master Jul 10, 2025
@ecstasoy ecstasoy deleted the fix/inline-crash branch July 10, 2025 03:24
@ecstasoy ecstasoy restored the fix/inline-crash branch July 10, 2025 03:24
@LEOYoon-Tsaw
Copy link
Member

Potentially fixed #1040, #1045

@ecstasoy
Copy link
Contributor Author

ecstasoy commented Jul 10, 2025

Potentially fixed #1040, #1045

#1045 似乎并没有解决。我开了新的PR,您可以看看

@lotem
Copy link
Member

lotem commented Jul 12, 2025

前端就做展示,不做複雜邏輯

R²ime ?

@LEOYoon-Tsaw
Copy link
Member

前端就做展示,不做複雜邏輯

R²ime ?

一開始只是順手把這個組合實現了,沒想到還有不少人真的用,那確實可以mark一下,雖然不知道R²ime排期到哪年了😂

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.

3 participants