Automattic / Automattic/simplenote-android

Crash: IndexOutOfBoundsException When Inserting Checklist Item Above Empty Checklist Item

Open
#1,036 4 comments 0 reactions 0 assignees View on GitHub
[feature] checklist [Type] Bug crash
Dominant language
Java
Stars
1.9k
Forks
318
Avg merge
15h 23m
Merged PRs (30d)
5

Description

### Expected
When tapping the **_Enter_**/**_Return_** key at the end of a line of a checklist item with the next line containing an empty checklist item and the line after that being a checklist item, the app inserts a new checklist item and does not crash.

### Observed
When tapping the **_Enter_**/**_Return_** key at the end of a line of a checklist item with the next line containing an empty checklist item and the line after that being a checklist item, the app does not insert a new checklist item and does crash. See the stack trace below for details.

Stack Trace

java.lang.IndexOutOfBoundsException: 5, -1

at android.text.PackedIntVector.deleteAt(PackedIntVector.java:222)
at android.text.DynamicLayout.reflow(DynamicLayout.java:317)
at android.text.DynamicLayout.-wrap0
at android.text.DynamicLayout$ChangeWatcher.reflow(DynamicLayout.java:750)
at android.text.DynamicLayout$ChangeWatcher.onSpanChanged(DynamicLayout.java:779)
at android.text.SpannableStringBuilder.sendSpanChanged(SpannableStringBuilder.java:1292)
at android.text.SpannableStringBuilder.sendToSpanWatchers(SpannableStringBuilder.java:647)
at android.text.SpannableStringBuilder.replace(SpannableStringBuilder.java:577)
at android.text.SpannableStringBuilder.insert(SpannableStringBuilder.java:224)
at android.text.SpannableStringBuilder.insert(SpannableStringBuilder.java:222)
at com.automattic.simplenote.utils.AutoBullet.apply
at com.automattic.simplenote.NoteEditorFragment.attemptAutoList
at com.automattic.simplenote.NoteEditorFragment.afterTextChanged
at android.widget.TextView.sendAfterTextChanged(TextView.java:9375)
at android.widget.TextView$ChangeWatcher.afterTextChanged(TextView.java:11917)
at android.text.SpannableStringBuilder.sendAfterTextChanged(SpannableStringBuilder.java:1262)
at android.text.SpannableStringBuilder.replace(SpannableStringBuilder.java:574)
at android.text.SpannableStringBuilder.replace(SpannableStringBuilder.java:504)
at android.text.SpannableStringBuilder.replace(SpannableStringBuilder.java:502)
at android.text.method.QwertyKeyListener.onKeyDown(QwertyKeyListener.java:228)
at android.text.method.TextKeyListener.onKeyDown(TextKeyListener.java:141)
at android.widget.TextView.doKeyDown(TextView.java:7316)
at android.widget.TextView.onKeyDown(TextView.java:7093)
at android.view.KeyEvent.dispatch(KeyEvent.java:2688)
at android.view.View.dispatchKeyEvent(View.java:11662)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1827)
at androidx.core.widget.NestedScrollView.dispatchKeyEvent
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1827)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1827)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1827)
at androidx.core.widget.NestedScrollView.dispatchKeyEvent
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1827)
at androidx.viewpager.widget.ViewPager.dispatchKeyEvent
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1827)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1827)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1827)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1827)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1827)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1827)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1827)
at com.android.internal.policy.DecorView.superDispatchKeyEvent(DecorView.java:437)
at com.android.internal.policy.PhoneWindow.superDispatchKeyEvent(PhoneWindow.java:1818)
at androidx.core.view.KeyEventDispatcher.activitySuperDispatchKeyEventPre28
at androidx.core.view.KeyEventDispatcher.dispatchKeyEvent
at androidx.core.app.ComponentActivity.dispatchKeyEvent
at androidx.appcompat.app.AppCompatActivity.dispatchKeyEvent
at androidx.appcompat.view.WindowCallbackWrapper.dispatchKeyEvent
at androidx.appcompat.app.AppCompatDelegateImpl$AppCompatWindowCallback.dispatchKeyEvent
at androidx.appcompat.view.WindowCallbackWrapper.dispatchKeyEvent
at com.android.internal.policy.DecorView.dispatchKeyEvent(DecorView.java:351)
at android.view.ViewRootImpl$ViewPostImeInputStage.processKeyEvent(ViewRootImpl.java:4714)
at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:4586)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4128)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4181)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4147)
at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:4274)
at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:4155)
at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:4331)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4128)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4181)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4147)
at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:4155)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4128)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4181)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4147)
at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:4307)
at android.view.ViewRootImpl$ImeInputStage.onFinishedInputEvent(ViewRootImpl.java:4468)
at android.view.inputmethod.InputMethodManager$PendingEvent.run(InputMethodManager.java:2435)
at android.view.inputmethod.InputMethodManager.invokeFinishedInputEventCallback(InputMethodManager.java:1998)
at android.view.inputmethod.InputMethodManager.finishedInputEvent(InputMethodManager.java:1989)
at android.view.inputmethod.InputMethodManager$ImeInputEventSender.onInputEventFinished(InputMethodManager.java:2412)
at android.view.InputEventSender.dispatchInputEventFinished(InputEventSender.java:141)
at android.os.MessageQueue.nativePollOnce(MessageQueue.java)
at android.os.MessageQueue.next(MessageQueue.java:325)
at android.os.Looper.loop(Looper.java:142)
at android.app.ActivityThread.main(ActivityThread.java:6541)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)

### Reproduced
1. Tap **_New Note_** floating action button.
2. Tap ***Toggle Checklist*** item in app bar.
3. Tap **_Enter_**/**_Return_** key twice.
4. Tap end of first line.
5. Tap **_Enter_**/**_Return_** key.
6. Notice crash.

Make|Model|Android Version|App Version
-|-|-|-
Google|Pixel 2|8.0.0|2.5.1

Contributor guide

Open the contributing guide

Research direction

Start with AutoBullet.apply and follow its callers in NoteEditorFragment.attemptAutoList and afterTextChanged. Reproduce the sequence with an empty checklist item between two checklist items, then verify that pressing Enter inserts the new checklist item without an IndexOutOfBoundsException.

Written by the indexing model from the issue text.

Assessment

Tech stack
android, java
Domain
mobile
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.