mastodon / mastodon-android

Official Android app for Mastodon
https://app.joinmastodon.org/android
GNU General Public License v3.0
1.62k stars 251 forks source link

Emote crash #820

Open gaussandhisgun opened 2 months ago

gaussandhisgun commented 2 months ago

I've blatantly stole an issue template from Moshidon for this one, just because its kinda more structured than an empty textbox. And I think they just use Megalodon's one. Anyway.

Describe the bug

If you are going around the app posting emotes, using the :emote_name: format, there is a huge chance that once you reach a certain amount of emotes that the app was trying to suggest, it will just crash. I've managed to get two traces for this, attached below.

To reproduce

Steps to reproduce the behavior:

  1. Login on a server with a lot of emotes - i tried on wetdry.world.
  2. Open the posting form.
  3. Start typing in emote names in :emote: format - usually works for me with the combination of :blobcat_comfy:, :neocat_googly: and :neofox_googly:, but should do with any combination, just longer
  4. See the app crashing in front of your face

Screenshots and screen recordings

Funnily enough, I have not managed to capture any screen recordings, its almost as if this only happens if my device is running fast.

Version

Happens on moshidon 2.1.4+fork.104.moshinda and mastodon 2.4.1 (89) from github.

Crash log

Official app:

FATAL EXCEPTION: main
Process: org.joinmastodon.android, PID: 26238
java.lang.IllegalArgumentException: start=105 > end=104
    at h0.s.l(SourceFile:67)
    at h0.s.k(SourceFile:2)
    at h0.w.onScroll(SourceFile:83)
    at h0.a0$a.b(SourceFile:22)
    at androidx.recyclerview.widget.RecyclerView.L(SourceFile:29)
    at androidx.recyclerview.widget.RecyclerView.J(SourceFile:222)
    at androidx.recyclerview.widget.RecyclerView.G(SourceFile:125)
    at androidx.recyclerview.widget.RecyclerView.z(SourceFile:84)
    at androidx.recyclerview.widget.RecyclerView.o1(SourceFile:1)
    at androidx.recyclerview.widget.RecyclerView.scrollBy(SourceFile:42)
    at u1.v.q0(SourceFile:38)
    at org.joinmastodon.android.ui.viewcontrollers.ComposeAutocompleteViewController.Q(SourceFile:52)
    at g1.w0.h(SourceFile:84)
    at org.joinmastodon.android.ui.views.ComposeEditText.onSelectionChanged(SourceFile:8)
    at android.widget.TextView.spanChange(TextView.java:12527)
    at android.widget.TextView$ChangeWatcher.onSpanChanged(TextView.java:15863)
    at android.text.SpannableStringBuilder.sendSpanChanged(SpannableStringBuilder.java:1308)
    at android.text.SpannableStringBuilder.sendToSpanWatchers(SpannableStringBuilder.java:652)
    at android.text.SpannableStringBuilder.replace(SpannableStringBuilder.java:581)
    at android.text.SpannableStringBuilder.delete(SpannableStringBuilder.java:231)
    at android.text.SpannableStringBuilder.delete(SpannableStringBuilder.java:38)
    at android.view.inputmethod.BaseInputConnection.deleteSurroundingText(BaseInputConnection.java:305)
    at android.view.inputmethod.InputConnectionWrapper.deleteSurroundingText(InputConnectionWrapper.java:152)
    at android.view.inputmethod.RemoteInputConnectionImpl.lambda$deleteSurroundingText$31(RemoteInputConnectionImpl.java:912)
    at android.view.inputmethod.RemoteInputConnectionImpl.$r8$lambda$NxJQWYbCWM_0fz9NbJNoaUOZl9Q(Unknown Source:0)
    at android.view.inputmethod.RemoteInputConnectionImpl$$ExternalSyntheticLambda6.run(Unknown Source:8)
    at android.os.Handler.handleCallback(Handler.java:958)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loopOnce(Looper.java:205)
    at android.os.Looper.loop(Looper.java:294)
    at android.app.ActivityThread.main(ActivityThread.java:8172)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:552)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:878)

Moshi:

FATAL EXCEPTION: main
Process: org.joinmastodon.android.moshinda, PID: 23420
java.lang.IllegalStateException: Can only create one instance of the view holder. parent=me.grishka.appkit.views.UsableRecyclerView{7156772 VFED..... ......I. 0,0-1080,132}, viewType=17
    at me.grishka.appkit.utils.SingleViewRecyclerAdapter.onCreateViewHolder(SingleViewRecyclerAdapter.java:24)
    at me.grishka.appkit.utils.SingleViewRecyclerAdapter.onCreateViewHolder(SingleViewRecyclerAdapter.java:9)
    at me.grishka.appkit.utils.MergeRecyclerAdapter.onCreateViewHolder(MergeRecyclerAdapter.java:118)
    at androidx.recyclerview.widget.RecyclerView$Adapter.createViewHolder(RecyclerView.java:7297)
    at androidx.recyclerview.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:6419)
    at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6303)
    at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6299)
    at androidx.recyclerview.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2328)
    at androidx.recyclerview.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1629)
    at androidx.recyclerview.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1589)
    at androidx.recyclerview.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:666)
    at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:4300)
    at androidx.recyclerview.widget.RecyclerView.dispatchLayout(RecyclerView.java:4003)
    at androidx.recyclerview.widget.RecyclerView.consumePendingUpdateOperations(RecyclerView.java:2021)
    at androidx.recyclerview.widget.RecyclerView.scrollByInternal(RecyclerView.java:2060)
    at androidx.recyclerview.widget.RecyclerView.scrollBy(RecyclerView.java:1873)
    at org.joinmastodon.android.ui.utils.UiUtils.updateList(UiUtils.java:931)
    at org.joinmastodon.android.ui.viewcontrollers.ComposeAutocompleteViewController.setText(ComposeAutocompleteViewController.java:214)
    at org.joinmastodon.android.fragments.ComposeFragment.onSelectionChanged(ComposeFragment.java:1792)
    at org.joinmastodon.android.ui.views.ComposeEditText.onSelectionChanged(ComposeEditText.java:46)
    at android.widget.TextView.spanChange(TextView.java:12527)
    at android.widget.TextView$ChangeWatcher.onSpanChanged(TextView.java:15863)
    at android.text.SpannableStringBuilder.sendSpanChanged(SpannableStringBuilder.java:1308)
    at android.text.SpannableStringBuilder.sendToSpanWatchers(SpannableStringBuilder.java:652)
    at android.text.SpannableStringBuilder.replace(SpannableStringBuilder.java:581)
    at android.text.SpannableStringBuilder.replace(SpannableStringBuilder.java:508)
    at android.text.SpannableStringBuilder.replace(SpannableStringBuilder.java:38)
    at android.view.inputmethod.BaseInputConnection.replaceTextInternal(BaseInputConnection.java:1026)
    at android.view.inputmethod.BaseInputConnection.replaceText(BaseInputConnection.java:962)
    at android.view.inputmethod.BaseInputConnection.commitText(BaseInputConnection.java:241)
    at com.android.internal.inputmethod.EditableInputConnection.commitText(EditableInputConnection.java:222)
    at android.view.inputmethod.InputConnectionWrapper.commitText(InputConnectionWrapper.java:207)
    at android.view.inputmethod.RemoteInputConnectionImpl.lambda$commitText$16(RemoteInputConnectionImpl.java:630)
    at android.view.inputmethod.RemoteInputConnectionImpl.$r8$lambda$DuD803urSTti1OmMx2Hq0yX1sSU(Unknown Source:0)
    at android.view.inputmethod.RemoteInputConnectionImpl$$ExternalSyntheticLambda15.run(Unknown Source:8)
    at android.os.Handler.handleCallback(Handler.java:958)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loopOnce(Looper.java:205)
    at android.os.Looper.loop(Looper.java:294)
    at android.app.ActivityThread.main(ActivityThread.java:8172)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:552)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:878)

I'm sending both because these might be different crashes related to the same thing, since the one in the official app happened twice during removing characters from the emote name, and the one on Moshi happened at least five times when adding characters. Both stack traces lead to ComposeAutocompleteViewController, so... yeah?

grishka commented 2 months ago

Deobfuscated first stack trace:

java.lang.IllegalArgumentException: start=105 > end=104
    at me.grishka.appkit.imageloader.ListImageLoader.loadRange(ListImageLoader.java:48)
    at me.grishka.appkit.imageloader.ListImageLoader.loadRange(ListImageLoader.java:43)
    at me.grishka.appkit.imageloader.ListImageLoaderWrapper.onScroll(ListImageLoaderWrapper.java:258)
    at me.grishka.appkit.imageloader.RecyclerViewDelegate$1.onScrolled(RecyclerViewDelegate.java:84)
    at androidx.recyclerview.widget.RecyclerView.dispatchOnScrolled(RecyclerView.java:5334)
    at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep3(RecyclerView.java:4396)
    at androidx.recyclerview.widget.RecyclerView.dispatchLayout(RecyclerView.java:4022)
    at androidx.recyclerview.widget.RecyclerView.consumePendingUpdateOperations(RecyclerView.java:2021)
    at androidx.recyclerview.widget.RecyclerView.scrollByInternal(RecyclerView.java:2060)
    at androidx.recyclerview.widget.RecyclerView.scrollBy(RecyclerView.java:1873)
    at org.joinmastodon.android.ui.utils.UiUtils.updateList(UiUtils.java:652)
    at org.joinmastodon.android.ui.viewcontrollers.ComposeAutocompleteViewController.setText(ComposeAutocompleteViewController.java:214)
    at org.joinmastodon.android.fragments.ComposeFragment.onSelectionChanged(ComposeFragment.java:1004)
    at org.joinmastodon.android.ui.views.ComposeEditText.onSelectionChanged(ComposeEditText.java:46)
    at android.widget.TextView.spanChange(TextView.java:12527)
    at android.widget.TextView$ChangeWatcher.onSpanChanged(TextView.java:15863)
    at android.text.SpannableStringBuilder.sendSpanChanged(SpannableStringBuilder.java:1308)
    at android.text.SpannableStringBuilder.sendToSpanWatchers(SpannableStringBuilder.java:652)
    at android.text.SpannableStringBuilder.replace(SpannableStringBuilder.java:581)
    at android.text.SpannableStringBuilder.delete(SpannableStringBuilder.java:231)
    at android.text.SpannableStringBuilder.delete(SpannableStringBuilder.java:38)
    at android.view.inputmethod.BaseInputConnection.deleteSurroundingText(BaseInputConnection.java:305)
    at android.view.inputmethod.InputConnectionWrapper.deleteSurroundingText(InputConnectionWrapper.java:152)
    at android.view.inputmethod.RemoteInputConnectionImpl.lambda$deleteSurroundingText$31(RemoteInputConnectionImpl.java:912)
    at android.view.inputmethod.RemoteInputConnectionImpl.$r8$lambda$NxJQWYbCWM_0fz9NbJNoaUOZl9Q(Unknown Source)
    at android.view.inputmethod.RemoteInputConnectionImpl$$ExternalSyntheticLambda6.run(Unknown Source:8)
    at android.os.Handler.handleCallback(Handler.java:958)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loopOnce(Looper.java:205)
    at android.os.Looper.loop(Looper.java:294)
    at android.app.ActivityThread.main(ActivityThread.java:8172)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:552)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:878)