Skip to content

Commit 168470f

Browse files
authored
Try fixing index OOB issues in Editable.checkSuggestionNeeded (#6303)
- Fix the case where the order for `start` and `end` is reversed. - Fix the case where `start` or `end` may be outside the editable's range (`0..length`).
1 parent f8d0de2 commit 168470f

File tree

1 file changed

+21
-3
lines changed
  • libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/components/markdown

1 file changed

+21
-3
lines changed

libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/components/markdown/MarkdownTextInput.kt

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ import io.element.android.libraries.textcomposer.model.SuggestionType
4242
import io.element.android.libraries.textcomposer.model.aMarkdownTextEditorState
4343
import io.element.android.wysiwyg.compose.RichTextEditorStyle
4444
import io.element.android.wysiwyg.compose.internal.applyStyleInCompose
45+
import timber.log.Timber
4546

4647
@Suppress("ModifierMissing")
4748
@Composable
@@ -149,8 +150,20 @@ fun MarkdownTextInput(
149150

150151
private fun Editable.checkSuggestionNeeded(): Suggestion? {
151152
if (this.isEmpty()) return null
152-
val start = Selection.getSelectionStart(this)
153-
val end = Selection.getSelectionEnd(this)
153+
var start = Selection.getSelectionStart(this)
154+
var end = Selection.getSelectionEnd(this)
155+
val range = 0..this.length
156+
157+
if (start !in range || end !in range) {
158+
Timber.tag("checkSuggestionNeeded").e("Selection indices are out of bounds: start=$start, end=$end, text length=${this.length}")
159+
return null
160+
}
161+
162+
// Make sure the selection order is correct, if not swap them: sometimes we can get the end before the start
163+
val tempEnd = end
164+
end = maxOf(start, end)
165+
start = minOf(start, tempEnd)
166+
154167
var startOfWord = start
155168
while ((startOfWord > 0 || startOfWord == length) && !this[startOfWord - 1].isWhitespace()) {
156169
startOfWord--
@@ -161,11 +174,16 @@ private fun Editable.checkSuggestionNeeded(): Suggestion? {
161174
// If a mention span already exists we don't need suggestions
162175
if (getSpans<MentionSpan>(startOfWord, startOfWord + 1).isNotEmpty()) return null
163176

164-
return if (firstChar in listOf('@', '#', '/')) {
177+
return if (firstChar in listOf('@', '#', '/', ':')) {
165178
var endOfWord = end
166179
while (endOfWord < this.length && !this[endOfWord].isWhitespace()) {
167180
endOfWord++
168181
}
182+
if (startOfWord + 1 > endOfWord) {
183+
Timber.tag("checkSuggestionNeeded").e("No need to show suggestions for an invalid range (${startOfWord + 1}..$endOfWord)")
184+
return null
185+
}
186+
169187
val text = this.subSequence(startOfWord + 1, endOfWord).toString()
170188
val suggestionType = when (firstChar) {
171189
'@' -> SuggestionType.Mention

0 commit comments

Comments
 (0)