Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"Split terminal horizontally" segfaults on Plasma Wayland. #806

Closed
uthidata opened this issue Mar 12, 2021 · 10 comments · Fixed by lxqt/qtermwidget#424
Closed

"Split terminal horizontally" segfaults on Plasma Wayland. #806

uthidata opened this issue Mar 12, 2021 · 10 comments · Fixed by lxqt/qtermwidget#424
Labels
bug platform:Wayland Wayland-specific issues

Comments

@uthidata
Copy link

Expected Behavior

Program does not crash when splitting terminal horizontally.

Current Behavior

Program does crash when splitting terminal horizontally.
This does not happen in X11.

Possible Solution
Steps to Reproduce (for bugs)
  1. Log in to a Plasma (Full Wayland) session
  2. Open QTerminal
  3. Right click on terminal, select "Split terminal horizontally"
  4. Crash
Context

I was trying out wayland on plasma and checked if everything I used still works there.

System Information
  • Distribution & Version: OpenSUSE Tumbleweed
  • Kernel: 5.11.2-1-default
  • Qt Version: 5.15.2
  • qtermwidget Version: 0.16.1-1.4
  • lxqt-build-tools Version: 0.8.0-1.2
  • Package version: 0.16.1-1.3
@tsujan
Copy link
Member

tsujan commented Mar 12, 2021

Not reproducible under Weston. The problem may be in Plasma Wayland.

Please attach a backtrace when reporting a crash!

@uthidata
Copy link
Author

Trace generated when debugging with Qt Creator: backtrace.txt

@tsujan
Copy link
Member

tsujan commented Mar 14, 2021

I confirm that splitting makes the latest git QTerminal crash under Plasma Wayland with the backtrace @uthidata attached. More precisely:

#0  0x00007fe4f2f37e6e in Konsole::PlainTextDecoder::decodeLine(Konsole::Character const*, int, unsigned char) ()
   from /usr/lib/libqtermwidget5.so.0
#1  0x00007fe4f2f4503e in Konsole::TerminalDisplay::inputMethodQuery(Qt::InputMethodQuery) const ()
   from /usr/lib/libqtermwidget5.so.0
#2  0x00007fe4f2829fff in QWidget::event(QEvent*) () from /usr/lib/libQt5Widgets.so.5
#3  0x00007fe4f27e8752 in QApplicationPrivate::notify_helper(QObject*, QEvent*) () from /usr/lib/libQt5Widgets.so.5
#4  0x00007fe4f1d20cda in QCoreApplication::notifyInternal2(QObject*, QEvent*) () from /usr/lib/libQt5Core.so.5
#5  0x00007fe4ee7b898c in ?? () from /usr/lib/libQt5WaylandClient.so.5
#6  0x00007fe4f20ef6d9 in QGuiApplicationPrivate::_q_updateFocusObject(QObject*) () from /usr/lib/libQt5Gui.so.5
#7  0x00007fe4f1d58070 in ?? () from /usr/lib/libQt5Core.so.5
#8  0x00007fe4f20ff0f3 in QWindow::focusObjectChanged(QObject*) () from /usr/lib/libQt5Gui.so.5
#9  0x00007fe4f2823753 in QWidget::setFocus(Qt::FocusReason) () from /usr/lib/libQt5Widgets.so.5
#10 0x00007fe4f2f2aba5 in QTermWidget::init(int) () from /usr/lib/libqtermwidget5.so.0
#11 0x0000564fbe390be0 in TermWidgetImpl::TermWidgetImpl(TerminalConfig&, QWidget*) ()
#12 0x0000564fbe3912ad in TermWidget::TermWidget(TerminalConfig&, QWidget*) ()
#13 0x0000564fbe395265 in TermWidgetHolder::newTerm(TerminalConfig&) ()
#14 0x0000564fbe395e44 in TermWidgetHolder::split(TermWidget*, Qt::Orientation, TerminalConfig) ()
#15 0x0000564fbe395f9f in TermWidgetHolder::splitHorizontal(TermWidget*) ()
#16 0x0000564fbe38cb5e in TabWidget::splitHorizontally() ()
#17 0x00007fe4f1d58070 in ?? () from /usr/lib/libQt5Core.so.5
#18 0x00007fe4f27e1f63 in QAction::triggered(bool) () from /usr/lib/libQt5Widgets.so.5
#19 0x00007fe4f27e4845 in QAction::activate(QAction::ActionEvent) () from /usr/lib/libQt5Widgets.so.5
#20 0x00007fe4f296617b in ?? () from /usr/lib/libQt5Widgets.so.5
#21 0x00007fe4f296d8b2 in ?? () from /usr/lib/libQt5Widgets.so.5
#22 0x00007fe4f2829b0e in QWidget::event(QEvent*) () from /usr/lib/libQt5Widgets.so.5
#23 0x00007fe4f27e8752 in QApplicationPrivate::notify_helper(QObject*, QEvent*) () from /usr/lib/libQt5Widgets.so.5
#24 0x00007fe4f27ef87b in QApplication::notify(QObject*, QEvent*) () from /usr/lib/libQt5Widgets.so.5
#25 0x00007fe4f1d20cda in QCoreApplication::notifyInternal2(QObject*, QEvent*) () from /usr/lib/libQt5Core.so.5
#26 0x00007fe4f27ee87e in QApplicationPrivate::sendMouseEvent(QWidget*, QMouseEvent*, QWidget*, QWidget*, QWidget**, QPointer<QWidget>&, bool, bool) () from /usr/lib/libQt5Widgets.so.5
#27 0x00007fe4f28427cf in ?? () from /usr/lib/libQt5Widgets.so.5
#28 0x00007fe4f284563f in ?? () from /usr/lib/libQt5Widgets.so.5
#29 0x00007fe4f27e8752 in QApplicationPrivate::notify_helper(QObject*, QEvent*) () from /usr/lib/libQt5Widgets.so.5
#30 0x00007fe4f1d20cda in QCoreApplication::notifyInternal2(QObject*, QEvent*) () from /usr/lib/libQt5Core.so.5
#31 0x00007fe4f20fb4ac in QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::MouseEvent*) ()
   from /usr/lib/libQt5Gui.so.5
#32 0x00007fe4f20d0bac in QWindowSystemInterface::sendWindowSystemEvents(QFlags<QEventLoop::ProcessEventsFlag>) ()
   from /usr/lib/libQt5Gui.so.5
#33 0x00007fe4ee7d70b1 in ?? () from /usr/lib/libQt5WaylandClient.so.5
#34 0x00007fe4f0b1cbfc in g_main_context_dispatch () from /usr/lib/libglib-2.0.so.0
#35 0x00007fe4f0b6e1f9 in ?? () from /usr/lib/libglib-2.0.so.0
#36 0x00007fe4f0b1b421 in g_main_context_iteration () from /usr/lib/libglib-2.0.so.0
#37 0x00007fe4f1d79941 in QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) ()
   from /usr/lib/libQt5Core.so.5
#38 0x00007fe4f1d1f65c in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) () from /usr/lib/libQt5Core.so.5
#39 0x00007fe4f296b251 in ?? () from /usr/lib/libQt5Widgets.so.5
#40 0x00007fe4f296b38f in QMenu::exec(QPoint const&, QAction*) () from /usr/lib/libQt5Widgets.so.5
#41 0x0000564fbe3924f0 in TermWidgetImpl::customContextMenuCall(QPoint const&) ()
#42 0x00007fe4f1d58036 in ?? () from /usr/lib/libQt5Core.so.5
#43 0x00007fe4f280ef76 in QWidget::customContextMenuRequested(QPoint const&) () from /usr/lib/libQt5Widgets.so.5
#44 0x00007fe4f282a8e7 in QWidget::event(QEvent*) () from /usr/lib/libQt5Widgets.so.5
#45 0x00007fe4f27e8752 in QApplicationPrivate::notify_helper(QObject*, QEvent*) () from /usr/lib/libQt5Widgets.so.5
#46 0x00007fe4f27f0525 in QApplication::notify(QObject*, QEvent*) () from /usr/lib/libQt5Widgets.so.5
#47 0x00007fe4f1d20cda in QCoreApplication::notifyInternal2(QObject*, QEvent*) () from /usr/lib/libQt5Core.so.5
#48 0x00007fe4f2842db1 in ?? () from /usr/lib/libQt5Widgets.so.5
#49 0x00007fe4f284563f in ?? () from /usr/lib/libQt5Widgets.so.5
#50 0x00007fe4f27e8752 in QApplicationPrivate::notify_helper(QObject*, QEvent*) () from /usr/lib/libQt5Widgets.so.5
#51 0x00007fe4f1d20cda in QCoreApplication::notifyInternal2(QObject*, QEvent*) () from /usr/lib/libQt5Core.so.5

No crash under Weston.

@tsujan
Copy link
Member

tsujan commented Apr 20, 2021

I succeeded in preventing the crash here and in #820 by using:

diff -ruNp qtermwidget-orig/lib/TerminalCharacterDecoder.cpp qtermwidget/lib/TerminalCharacterDecoder.cpp
--- qtermwidget-orig/lib/TerminalCharacterDecoder.cpp
+++ qtermwidget/lib/TerminalCharacterDecoder.cpp
@@ -79,6 +79,16 @@ void PlainTextDecoder::decodeLine(const
         _linePositions << pos;
     }
 
+    // check the real length
+    for (int i = 0 ; i < count ; i++)
+    {
+        if (characters + i == nullptr)
+        {
+            count = i;
+            break;
+        }
+    }
+
     //TODO should we ignore or respect the LINE_WRAPPED line property?
 
     //note:  we build up a QString and send it to the text stream rather writing into the text

But I'm not familiar with the code and don't know if this makes sense. @yan12125?

EDIT: I made the patch more logical.

@yan12125
Copy link
Member

Sorry for the late response. My todo queue is way too long 😥

The issue seems related to input methods, while I cannot reproduce crashes with either creating new tabs or splitting terminals under Plasma wayland with Fcitx 5 input method, so I don't know the exact cause. I guess this fix from Konsole is relevant.

Although I believe decoders should be called with correct parameters, tsujan's patch is still good to have to avoid crashes due to other bugs. Some qCWarning() calls will be nice to notify developers that the passed arguments may be incorrect.

@tsujan
Copy link
Member

tsujan commented Apr 28, 2021

I guess this fix from Konsole is relevant.

I'd noticed isCursorOnDisplay(); it had no effect by itself. Didn't try the other changes alongside it though.

The above-mentioned patch prevents the crashes here. IMO, the method PlainTextDecoder::decodeLine() has a serious flaw without it: the lack of an out-of-range check. it shouldn't depend on other classes for that.

while I cannot reproduce crashes

They happen only under Plasma-Wayland (= KWin's Wayland), not under other Wayland compositors.

@yan12125
Copy link
Member

yan12125 commented May 1, 2021

I agree PlainTextDecoder::decodeLine() should check whether inputs are valid. But the actual issue (incorrect computation in TerminalDisplay::inputMethodQuery()) should be fixed as well. Could you create a pull request for the range check first? After that we can look into the actual issue.

They happen only under Plasma-Wayland (= KWin's Wayland), not under other Wayland compositors.

Yeah I tested under the latest Plasma Wayland via sddm under Arch Linux. With or without Fcitx 5 (my daily Chinese input method), qterminal does not crash.

@tsujan
Copy link
Member

tsujan commented May 1, 2021

Konsole checks nullity in a different way and skips it, without checking the range (Konsole → PlainTextDecoder.cpp → PlainTextDecoder::decodeLine). To me, also that code seems hanging by a hair.

My patch was just a simple check that worked here; it wasn't based on a knowledge of the whole code (which I don't have). Because of that, it could interfere with your importing Konsole's fixes later.

When you imported Konsole's fixes, just tell me to test them; the crash is 100% reproducible here with a non-patched qtermwidget.

@yan12125
Copy link
Member

yan12125 commented May 2, 2021

Ah forgot to say, I don't plan to backport Konsole's commit anymore after reading it. It seems to return the whole line for Qt::ImSurroundingText, which sounds strange. I looked into some discussions about "surrounding texts" in input methods, while none of them provides a clear definition. The actual issue may not be fixed soon as it requires in-depth understanding of input methods, which I don't have :(

@tsujan
Copy link
Member

tsujan commented May 2, 2021

Ah forgot to say, I don't plan to backport Konsole's commit anymore after reading it.

OK, I'll make a small PR today. I think it'll be harmless if the root cause is eliminated.

tsujan added a commit to lxqt/qtermwidget that referenced this issue May 2, 2021
With this check, I can't make QTerminal crash by splitting or opening new tabs under Plasma Wayland.

Fixes lxqt/qterminal#806 and fixes lxqt/qterminal#820
yan12125 pushed a commit to lxqt/qtermwidget that referenced this issue May 2, 2021
With this check, I can't make QTerminal crash by splitting or opening new tabs under Plasma Wayland.

Fixes lxqt/qterminal#806 and fixes lxqt/qterminal#820
@yan12125 yan12125 added the platform:Wayland Wayland-specific issues label Jan 27, 2023
inventor2525 pushed a commit to inventor2525/qtermwidget that referenced this issue May 14, 2024
With this check, I can't make QTerminal crash by splitting or opening new tabs under Plasma Wayland.

Fixes lxqt/qterminal#806 and fixes lxqt/qterminal#820
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug platform:Wayland Wayland-specific issues
Projects
Status: Done
Development

Successfully merging a pull request may close this issue.

3 participants