MCMrARM / revolution-irc

A modern Android IRC client. #revolutionirc on Libera.chat
GNU General Public License v3.0
555 stars 62 forks source link

Crashing On Channel Load #301

Open danshick opened 3 years ago

danshick commented 3 years ago

I have revolution connecting to my bouncer (soju) which manages my persistent connection to libra.chat. When I click on certain channels (e.g. #nix-darwin), revolution instantly crashes. Other channels work fine and other IRC clients have no issue connecting to my bouncer and these channels. I've attached logcat logs that I believe are relevant to this issue.

2021-06-16-08-46-15.txt

Please let me know if I can provide any further information.

jugendhacker commented 3 years ago

I have a very similar stacktrace also with soju as bouncer

Long stacktrace pulled out of adb logcat ``` 06-22 18:53:07.954 28451 28451 E AndroidRuntime: FATAL EXCEPTION: main 06-22 18:53:07.954 28451 28451 E AndroidRuntime: Process: io.mrarm.irc, PID: 28451 06-22 18:53:07.954 28451 28451 E AndroidRuntime: java.lang.NullPointerException: Attempt to invoke interface method 'int java.lang.CharSequence.length()' on a null object reference 06-22 18:53:07.954 28451 28451 E AndroidRuntime: at android.text.SpannableString.(SpannableString.java:34) 06-22 18:53:07.954 28451 28451 E AndroidRuntime: at android.text.SpannableString.(SpannableString.java:43) 06-22 18:53:07.954 28451 28451 E AndroidRuntime: at io.mrarm.irc.util.IRCColorUtils.getFormattedString(IRCColorUtils.java:132) 06-22 18:53:07.954 28451 28451 E AndroidRuntime: at io.mrarm.irc.util.MessageBuilder.buildMessage(MessageBuilder.java:372) 06-22 18:53:07.954 28451 28451 E AndroidRuntime: at io.mrarm.irc.chat.ChatMessagesAdapter$MessageHolder.bind(ChatMessagesAdapter.java:437) 06-22 18:53:07.954 28451 28451 E AndroidRuntime: at io.mrarm.irc.chat.ChatMessagesAdapter.onBindViewHolder(ChatMessagesAdapter.java:280) 06-22 18:53:07.954 28451 28451 E AndroidRuntime: at androidx.recyclerview.widget.RecyclerView$Adapter.onBindViewHolder(RecyclerView.java:7065) 06-22 18:53:07.954 28451 28451 E AndroidRuntime: at androidx.recyclerview.widget.RecyclerView$Adapter.bindViewHolder(RecyclerView.java:7107) 06-22 18:53:07.954 28451 28451 E AndroidRuntime: at androidx.recyclerview.widget.RecyclerView$Recycler.tryBindViewHolderByDeadline(RecyclerView.java:6012) 06-22 18:53:07.954 28451 28451 E AndroidRuntime: at androidx.recyclerview.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:6279) 06-22 18:53:07.954 28451 28451 E AndroidRuntime: at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6118) 06-22 18:53:07.954 28451 28451 E AndroidRuntime: at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6114) 06-22 18:53:07.954 28451 28451 E AndroidRuntime: at androidx.recyclerview.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2303) 06-22 18:53:07.954 28451 28451 E AndroidRuntime: at androidx.recyclerview.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1627) 06-22 18:53:07.954 28451 28451 E AndroidRuntime: at androidx.recyclerview.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1587) 06-22 18:53:07.954 28451 28451 E AndroidRuntime: at androidx.recyclerview.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:640) 06-22 18:53:07.954 28451 28451 E AndroidRuntime: at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:4134) 06-22 18:53:07.954 28451 28451 E AndroidRuntime: at androidx.recyclerview.widget.RecyclerView.dispatchLayout(RecyclerView.java:3851) 06-22 18:53:07.954 28451 28451 E AndroidRuntime: at androidx.recyclerview.widget.RecyclerView.onLayout(RecyclerView.java:4404) 06-22 18:53:07.954 28451 28451 E AndroidRuntime: at android.view.View.layout(View.java:22509) 06-22 18:53:07.954 28451 28451 E AndroidRuntime: at android.view.ViewGroup.layout(ViewGroup.java:7190) 06-22 18:53:07.954 28451 28451 E AndroidRuntime: at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323) 06-22 18:53:07.954 28451 28451 E AndroidRuntime: at android.widget.FrameLayout.onLayout(FrameLayout.java:261) 06-22 18:53:07.954 28451 28451 E AndroidRuntime: at android.view.View.layout(View.java:22509) 06-22 18:53:07.954 28451 28451 E AndroidRuntime: at android.view.ViewGroup.layout(ViewGroup.java:7190) 06-22 18:53:07.954 28451 28451 E AndroidRuntime: at androidx.viewpager.widget.ViewPager.onLayout(ViewPager.java:1775) 06-22 18:53:07.954 28451 28451 E AndroidRuntime: at android.view.View.layout(View.java:22509) 06-22 18:53:07.954 28451 28451 E AndroidRuntime: at android.view.ViewGroup.layout(ViewGroup.java:7190) 06-22 18:53:07.954 28451 28451 E AndroidRuntime: at android.widget.RelativeLayout.onLayout(RelativeLayout.java:1083) 06-22 18:53:07.954 28451 28451 E AndroidRuntime: at android.view.View.layout(View.java:22509) 06-22 18:53:07.954 28451 28451 E AndroidRuntime: at android.view.ViewGroup.layout(ViewGroup.java:7190) 06-22 18:53:07.954 28451 28451 E AndroidRuntime: at android.widget.RelativeLayout.onLayout(RelativeLayout.java:1083) 06-22 18:53:07.954 28451 28451 E AndroidRuntime: at android.view.View.layout(View.java:22509) 06-22 18:53:07.954 28451 28451 E AndroidRuntime: at android.view.ViewGroup.layout(ViewGroup.java:7190) 06-22 18:53:07.954 28451 28451 E AndroidRuntime: at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323) 06-22 18:53:07.954 28451 28451 E AndroidRuntime: at android.widget.FrameLayout.onLayout(FrameLayout.java:261) 06-22 18:53:07.954 28451 28451 E AndroidRuntime: at android.view.View.layout(View.java:22509) 06-22 18:53:07.954 28451 28451 E AndroidRuntime: at android.view.ViewGroup.layout(ViewGroup.java:7190) 06-22 18:53:07.954 28451 28451 E AndroidRuntime: at android.widget.RelativeLayout.onLayout(RelativeLayout.java:1083) 06-22 18:53:07.954 28451 28451 E AndroidRuntime: at android.view.View.layout(View.java:22509) 06-22 18:53:07.954 28451 28451 E AndroidRuntime: at android.view.ViewGroup.layout(ViewGroup.java:7190) 06-22 18:53:07.954 28451 28451 E AndroidRuntime: at androidx.drawerlayout.widget.DrawerLayout.onLayout(DrawerLayout.java:1231) 06-22 18:53:07.954 28451 28451 E AndroidRuntime: at android.view.View.layout(View.java:22509) 06-22 18:53:07.954 28451 28451 E AndroidRuntime: at android.view.ViewGroup.layout(ViewGroup.java:7190) 06-22 18:53:07.954 28451 28451 E AndroidRuntime: at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323) 06-22 18:53:07.954 28451 28451 E AndroidRuntime: at android.widget.FrameLayout.onLayout(FrameLayout.java:261) 06-22 18:53:07.954 28451 28451 E AndroidRuntime: at android.view.View.layout(View.java:22509) 06-22 18:53:07.954 28451 28451 E AndroidRuntime: at android.view.ViewGroup.layout(ViewGroup.java:7190) 06-22 18:53:07.954 28451 28451 E AndroidRuntime: at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323) 06-22 18:53:07.954 28451 28451 E AndroidRuntime: at android.widget.FrameLayout.onLayout(FrameLayout.java:261) 06-22 18:53:07.954 28451 28451 E AndroidRuntime: at android.view.View.layout(View.java:22509) 06-22 18:53:07.954 28451 28451 E AndroidRuntime: at android.view.ViewGroup.layout(ViewGroup.java:7190) 06-22 18:53:07.954 28451 28451 E AndroidRuntime: at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323) 06-22 18:53:07.954 28451 28451 E AndroidRuntime: at android.widget.FrameLayout.onLayout(FrameLayout.java:261) 06-22 18:53:07.954 28451 28451 E AndroidRuntime: at android.view.View.layout(View.java:22509) 06-22 18:53:07.954 28451 28451 E AndroidRuntime: at android.view.ViewGroup.layout(ViewGroup.java:7190) 06-22 18:53:07.955 28451 28451 E AndroidRuntime: at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1812) 06-22 18:53:07.955 28451 28451 E AndroidRuntime: at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1656) 06-22 18:53:07.955 28451 28451 E AndroidRuntime: at android.widget.LinearLayout.onLayout(LinearLayout.java:1565) 06-22 18:53:07.955 28451 28451 E AndroidRuntime: at android.view.View.layout(View.java:22509) 06-22 18:53:07.955 28451 28451 E AndroidRuntime: at android.view.ViewGroup.layout(ViewGroup.java:7190) 06-22 18:53:07.955 28451 28451 E AndroidRuntime: at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323) 06-22 18:53:07.955 28451 28451 E AndroidRuntime: at android.widget.FrameLayout.onLayout(FrameLayout.java:261) 06-22 18:53:07.955 28451 28451 E AndroidRuntime: at com.android.internal.policy.DecorView.onLayout(DecorView.java:1100) 06-22 18:53:07.955 28451 28451 E AndroidRuntime: at android.view.View.layout(View.java:22509) 06-22 18:53:07.955 28451 28451 E AndroidRuntime: at android.view.ViewGroup.layout(ViewGroup.java:7190) 06-22 18:53:07.955 28451 28451 E AndroidRuntime: at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:3456) 06-22 18:53:07.955 28451 28451 E AndroidRuntime: at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2916) 06-22 18:53:07.955 28451 28451 E AndroidRuntime: at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1964) 06-22 18:53:07.955 28451 28451 E AndroidRuntime: at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:8721) 06-22 18:53:07.955 28451 28451 E AndroidRuntime: at android.view.Choreographer$CallbackRecord.run(Choreographer.java:988) 06-22 18:53:07.955 28451 28451 E AndroidRuntime: at android.view.Choreographer.doCallbacks(Choreographer.java:765) 06-22 18:53:07.955 28451 28451 E AndroidRuntime: at android.view.Choreographer.doFrame(Choreographer.java:700) 06-22 18:53:07.955 28451 28451 E AndroidRuntime: at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:967) 06-22 18:53:07.955 28451 28451 E AndroidRuntime: at android.os.Handler.handleCallback(Handler.java:873) 06-22 18:53:07.955 28451 28451 E AndroidRuntime: at android.os.Handler.dispatchMessage(Handler.java:99) 06-22 18:53:07.955 28451 28451 E AndroidRuntime: at android.os.Looper.loop(Looper.java:216) 06-22 18:53:07.955 28451 28451 E AndroidRuntime: at android.app.ActivityThread.main(ActivityThread.java:7266) 06-22 18:53:07.955 28451 28451 E AndroidRuntime: at java.lang.reflect.Method.invoke(Native Method) 06-22 18:53:07.955 28451 28451 E AndroidRuntime: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:494) 06-22 18:53:07.955 28451 28451 E AndroidRuntime: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:975) ```
benoliver999 commented 2 years ago

Yep same here, on soju. For me it's when I click on the server itself.

The connection remains fine and I can click on other servers. In this case it's libera.chat, and it was working fine until I joined ##Ben

Now when I click libera.chat, the app crashes.

Here's a logcat, hopefully truncated at the right point

logcat.txt

elouin commented 2 years ago

I have the same issue/error with soju and quakenet.

0x5c commented 2 years ago

Same crash on channel load, also soju and libera. Affects some channels and some private message buffers

Problem showed up right after switching from znc to soju

I wonder there's a borked capability on the client or bouncer side

0x5c commented 2 years ago

Since clearing the (local) logs for affected networks fixes the crash until a reconnect is done, I looked at the raw log database files with an sql editor.

  1. The problem seems (mostly) concentrated on channels that don't have topics.
  2. The logcat traces posted here all point to a chat formatting routine attempting to get the character length of a null pointer.
  3. In the log database files, networks on a znc instance (no crash on those networks) only have topic messages logged for channels that actually have topics set. Those show in logs as two messages, a type 8 containing a topic and a type 10 containing info about who set the topic and when. That message is logged fewer times than there are reconnects to the znc.
  4. On networks accessed through soju, channels that have topics behave exactly like described above. But the channels that don't have a topic log a single and completely nulled type 8 message, with no type 10 message.

I tested creating a new channel on libera, which instantly crashed the client. In the log there was a single completely nulled type 8 message. Tried the same on OFTC, with the same results.

Once a buggy channel is joined, which channels will crash seems random; all buffers (server, channel, private message) could potentially crash on click.

Interestingly enough, leaving all topic-less channels in a network completely and instantly frees that network from click-crashes, without even restarting the app or clearing the logs in the settings.

0x5c commented 2 years ago

Oh hey, the soju author has made an issue about it already and it has been marked as fixed in a commit: #248 It is sadly not part of a release yet, and by extension not currently available in the stores

But considering it does not happen with other bouncers, I wonder if the root cause is soju sending spurious empty topics.

jugendhacker commented 2 years ago

But as this is fixed we should close this issue, right?

kurahaupo commented 2 years ago

But as this is fixed we should close this issue, right?

Absolutely not.

One particular (proxy) server has been fixed; that still leaves RevolutionIRC vulnerable to any other misbehaving server.

A robust program should never crash just because a program at the other end of a network connection (or pipe) is misbehaving. (That's different from telling the user "I give up because...", and then exiting; that could be a reasonable design choice in some circumstances.)

(Using the term "server" is not a mistake: a proxy or "bouncer" is simply a server and a client running back-to-back in the same program, but and the server half is all we care about here.)

benoliver999 commented 2 years ago

No no I misread this too - they mean that this app has been fixed, but not yet released - not soju.

On 2022-01-10 07:40:25, Martin Kealey wrote:

But as this is fixed we should close this issue, right?

Absolutely not.

One particular (proxy) server has been fixed; that still leaves RevolutionIRC vulnerable to any other misbehaving server.

A robust program should never crash just because a program at the other end of a network connection (or pipe) is misbehaving. (That's different from telling the user "I give up because...", and then exiting; that could be a reasonable design choice in some circumstances.)

(Using the term "server" is not a mistake: a proxy or "bouncer" is simply a server and a client running back-to-back in the same program, but and the server half is all we care about here.)

-- Reply to this email directly or view it on GitHub: https://github.com/MCMrARM/revolution-irc/issues/301#issuecomment-1009005481 You are receiving this because you commented.

Message ID: @.***>

kurahaupo commented 2 years ago

@benoliver999 right you are.

To the original point, the usual process on Github is to mark the ticket as dependent on a PR; then it's automatically closed when the PR is merged. In this case commit d01efade0e1b253a4b62954a17f6358aec619342 doesn't seem to have a PR (#248 is an issue not a PR).

0x5c commented 2 years ago

There was no PR since the developer pushed the commit directly. As far as Revolution IRC is concerned, the isue reported here is a duplicate of #248, which has been fixed in d01efade. This issue here should be closed too.

On the soju side there was indeed a bug, which has now been solved in emersion/soju@7060547809be03aa3342ae47151b97c8206230fb
The crash in revolution will still happen until the app's logs for the affected networks are purged, or you use a revolution build that includes d01efade.