Summary: | xdg-desktop-portal-kde crashes when opening and closing file dialog | ||
---|---|---|---|
Product: | [Plasma] xdg-desktop-portal-kde | Reporter: | Nicolas Fella <nicolas.fella> |
Component: | general | Assignee: | Plasma Bugs List <plasma-bugs> |
Status: | CONFIRMED --- | ||
Severity: | crash | CC: | aleixpol, kde, kde, kde, kdedev, nate, nyanpasu64, rodrigo.pedra, sitter |
Priority: | HI | Keywords: | drkonqi |
Version First Reported In: | 6.4.4 | ||
Target Milestone: | --- | ||
Platform: | Fedora RPMs | ||
OS: | Linux | ||
See Also: | https://bugs.kde.org/show_bug.cgi?id=508745 | ||
Latest Commit: | Version Fixed In: | ||
Sentry Crash Report: | https://crash-reports.kde.org/organizations/kde/issues/232084/events/7a05269aac6d45bbb49dbfda9909fb36/ | ||
Attachments: | Reproducing program |
Description
Nicolas Fella
2025-08-10 14:57:26 UTC
Sentry has lots of similar-ish issues where we crash somewhere in KFileWidget, starting with 6.4 Based on that I suspect https://invent.kde.org/plasma/xdg-desktop-portal-kde/-/commit/6d48d32ef8c125687208519d8477b1e315f14db5 causes this QWidgetLineControl::text (this=0xb1) We got a nullptr somewhere Created attachment 183934 [details]
Reproducing program
I can reproduce it relatively reliably with this program.
It depends a bit on timing/number of files in the relevant directory though
================================================================= ==199634==ERROR: AddressSanitizer: heap-use-after-free on address 0x7c4f162b62e8 at pc 0x7f0f252b31e3 bp 0x7ffcae7362a0 sp 0x7ffcae736298 READ of size 8 at 0x7c4f162b62e8 thread T0 #0 0x7f0f252b31e2 in QString::size() const /home/nico/kde-qtdev/usr/include/QtCore/qstring.h:239 #1 0x7f0f25368d31 in QConcatenable<QString>::size(QString const&) /home/nico/kde-qtdev/usr/include/QtCore/qstringbuilder.h:251 #2 0x7f0f253da2d9 in QConcatenable<QStringBuilder<QStringBuilder<QStringView, QStringView&>, QString&> >::size(QStringBuilder<QStringBuilder<QStringV #3 0x7f0f253d8397 in QString QStringBuilder<QStringBuilder<QStringView, QStringView&>, QString&>::convertTo<QString>() const /home/nico/kde-qtdev/usr #4 0x7f0f253d5866 in QStringBuilder<QStringBuilder<QStringView, QStringView&>, QString&>::operator QString() const /home/nico/kde-qtdev/usr/include/Q #5 0x7f0f253b3fda in KFileWidgetPrivate::updateLocationEditExtension(QString const&) /home/nico/kde-qtdev/src/kio/src/filewidgets/kfilewidget.cpp:254 #6 0x7f0f253b34da in KFileWidgetPrivate::updateAutoSelectExtension() /home/nico/kde-qtdev/src/kio/src/filewidgets/kfilewidget.cpp:2481 #7 0x7f0f253a68e0 in KFileWidgetPrivate::slotMimeFilterChanged() /home/nico/kde-qtdev/src/kio/src/filewidgets/kfilewidget.cpp:1613 #8 0x7f0f253a03c9 in operator() /home/nico/kde-qtdev/src/kio/src/filewidgets/kfilewidget.cpp:1361 #9 0x7f0f253c9b85 in operator() /home/nico/kde-qtdev/usr/include/QtCore/qobjectdefs_impl.h:116 #10 0x7f0f253cb653 in call_internal<void, QtPrivate::FunctorCall<std::integer_sequence<long unsigned int>, QtPrivate::List<>, void, KFileWidgetPrivat #11 0x7f0f253c9c8b in call /home/nico/kde-qtdev/usr/include/QtCore/qobjectdefs_impl.h:115 #12 0x7f0f253c6276 in call<QtPrivate::List<>, void> /home/nico/kde-qtdev/usr/include/QtCore/qobjectdefs_impl.h:337 #13 0x7f0f253c4e1c in impl /home/nico/kde-qtdev/usr/include/QtCore/qobjectdefs_impl.h:547 #14 0x7f0f19eeeeb2 in QtPrivate::QSlotObjectBase::call(QObject*, void**) /home/nico/workspace/qt6-dev/qtbase/src/corelib/kernel/qobjectdefs_impl.h:46 #15 0x7f0f19eeeeb2 in void doActivate<false>(QObject*, int, void**) /home/nico/workspace/qt6-dev/qtbase/src/corelib/kernel/qobject.cpp:4284 #16 0x7f0f19ed2bca in QMetaObject::activate(QObject*, QMetaObject const*, int, void**) /home/nico/workspace/qt6-dev/qtbase/src/corelib/kernel/qobject #17 0x7f0f19f24c19 in void QMetaObject::activate<void, QTimer::QPrivateSignal>(QObject*, QMetaObject const*, int, void*, QTimer::QPrivateSignal const #18 0x7f0f19f24c19 in QTimer::timeout(QTimer::QPrivateSignal) /home/nico/workspace/qt6-dev/qtbase/src/corelib/Core_autogen/include/moc_qtimer.cpp:182 #19 0x7f0f19f25e0d in QTimer::timerEvent(QTimerEvent*) /home/nico/workspace/qt6-dev/qtbase/src/corelib/kernel/qtimer.cpp:322 #20 0x7f0f19ecaea2 in QObject::event(QEvent*) /home/nico/workspace/qt6-dev/qtbase/src/corelib/kernel/qobject.cpp:1440 #21 0x7f0f1ce859fe in QApplicationPrivate::notify_helper(QObject*, QEvent*) /home/nico/workspace/qt6-dev/qtbase/src/widgets/kernel/qapplication.cpp:3 #22 0x7f0f1cea0f8a in QApplication::notify(QObject*, QEvent*) /home/nico/workspace/qt6-dev/qtbase/src/widgets/kernel/qapplication.cpp:3254 #23 0x7f0f19dbf37b in QCoreApplication::notifyInternal2(QObject*, QEvent*) /home/nico/workspace/qt6-dev/qtbase/src/corelib/kernel/qcoreapplication.cp #24 0x7f0f19dbf566 in QCoreApplication::sendEvent(QObject*, QEvent*) /home/nico/workspace/qt6-dev/qtbase/src/corelib/kernel/qcoreapplication.cpp:1549 #25 0x7f0f1a2e978a in QTimerInfoList::activateTimers() /home/nico/workspace/qt6-dev/qtbase/src/corelib/kernel/qtimerinfo_unix.cpp:426 #26 0x7f0f1a67ce92 in timerSourceDispatch /home/nico/workspace/qt6-dev/qtbase/src/corelib/kernel/qeventdispatcher_glib.cpp:152 #27 0x7f0f1a67ceff in idleTimerSourceDispatch /home/nico/workspace/qt6-dev/qtbase/src/corelib/kernel/qeventdispatcher_glib.cpp:199 #28 0x7f0f19509eb2 in g_main_dispatch ../glib/gmain.c:3398 #29 0x7f0f19509eb2 in g_main_context_dispatch_unlocked ../glib/gmain.c:4249 #30 0x7f0f1950bce7 in g_main_context_iterate_unlocked ../glib/gmain.c:4314 #31 0x7f0f1950c52b in g_main_context_iteration ../glib/gmain.c:4379 #32 0x7f0f1a67d56f in QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) /home/nico/workspace/qt6-dev/qtbase/src/corelib/kern #33 0x7f0f1c422ebb in QPAEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) /home/nico/workspace/qt6-dev/qtbase/src/gui/platfo #34 0x7f0f19ddf609 in QEventLoop::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) /home/nico/workspace/qt6-dev/qtbase/src/corelib/kernel/qeventl #35 0x7f0f19de0c04 in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) /home/nico/workspace/qt6-dev/qtbase/src/corelib/kernel/qeventloop.cpp:1 #36 0x7f0f19dc9253 in QCoreApplication::exec() /home/nico/workspace/qt6-dev/qtbase/src/corelib/kernel/qcoreapplication.cpp:1452 #37 0x7f0f1b456e71 in QGuiApplication::exec() /home/nico/workspace/qt6-dev/qtbase/src/gui/kernel/qguiapplication.cpp:1973 #38 0x7f0f1ce82866 in QApplication::exec() /home/nico/workspace/qt6-dev/qtbase/src/widgets/kernel/qapplication.cpp:2571 #39 0x0000007b599a in main /home/nico/kde-qtdev/src/xdg-desktop-portal-kde/src/xdg-desktop-portal-kde.cpp:68 #40 0x7f0f1922b37a in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58 #41 0x7f0f1922b44a in __libc_start_main_impl ../csu/libc-start.c:360 #42 0x000000433094 in _start ../sysdeps/x86_64/start.S:115 0x7c4f162b62e8 is located 168 bytes inside of 440-byte region [0x7c4f162b6240,0x7c4f162b63f8) freed by thread T0 here: #0 0x7f0f25f2369b in operator delete(void*, unsigned long) ../../../../libsanitizer/asan/asan_new_delete.cpp:155 #1 0x7f0f253d6780 in std::default_delete<KFileWidgetPrivate>::operator()(KFileWidgetPrivate*) const /usr/include/c++/15/bits/unique_ptr.h:93 #2 0x7f0f253d1e44 in std::unique_ptr<KFileWidgetPrivate, std::default_delete<KFileWidgetPrivate> >::~unique_ptr() /usr/include/c++/15/bits/unique_ptr #3 0x7f0f25390ff9 in KFileWidget::~KFileWidget() /home/nico/kde-qtdev/src/kio/src/filewidgets/kfilewidget.cpp:504 #4 0x7f0f25391089 in KFileWidget::~KFileWidget() /home/nico/kde-qtdev/src/kio/src/filewidgets/kfilewidget.cpp:504 #5 0x7f0f19ed7de5 in QObjectPrivate::deleteChildren() /home/nico/workspace/qt6-dev/qtbase/src/corelib/kernel/qobject.cpp:2264 #6 0x7f0f1cfcc650 in QWidget::~QWidget() /home/nico/workspace/qt6-dev/qtbase/src/widgets/kernel/qwidget.cpp:1571 #7 0x7f0f1d6fee8d in QDialog::~QDialog() /home/nico/workspace/qt6-dev/qtbase/src/widgets/dialogs/qdialog.cpp:402 #8 0x00000058de6c in FileDialog::~FileDialog() /home/nico/kde-qtdev/src/xdg-desktop-portal-kde/src/filechooser.cpp:142 #9 0x00000058ded1 in FileDialog::~FileDialog() /home/nico/kde-qtdev/src/xdg-desktop-portal-kde/src/filechooser.cpp:142 #10 0x7f0f19ecad87 in QObject::event(QEvent*) /home/nico/workspace/qt6-dev/qtbase/src/corelib/kernel/qobject.cpp:1450 #11 0x7f0f1cfe01cc in QWidget::event(QEvent*) /home/nico/workspace/qt6-dev/qtbase/src/widgets/kernel/qwidget.cpp:9448 #12 0x7f0f1ce859fe in QApplicationPrivate::notify_helper(QObject*, QEvent*) /home/nico/workspace/qt6-dev/qtbase/src/widgets/kernel/qapplication.cpp:3 #13 0x7f0f1ce9bff5 in QApplication::notify(QObject*, QEvent*) /home/nico/workspace/qt6-dev/qtbase/src/widgets/kernel/qapplication.cpp:3250 #14 0x7f0f19dbf37b in QCoreApplication::notifyInternal2(QObject*, QEvent*) /home/nico/workspace/qt6-dev/qtbase/src/corelib/kernel/qcoreapplication.cp #15 0x7f0f19dbf566 in QCoreApplication::sendEvent(QObject*, QEvent*) /home/nico/workspace/qt6-dev/qtbase/src/corelib/kernel/qcoreapplication.cpp:1549 #16 0x7f0f19dc18bc in QCoreApplicationPrivate::sendPostedEvents(QObject*, int, QThreadData*) /home/nico/workspace/qt6-dev/qtbase/src/corelib/kernel/q #17 0x7f0f19dc1bd7 in QCoreApplication::sendPostedEvents(QObject*, int) /home/nico/workspace/qt6-dev/qtbase/src/corelib/kernel/qcoreapplication.cpp:1 #18 0x7f0f1a67f17f in postEventSourceDispatch /home/nico/workspace/qt6-dev/qtbase/src/corelib/kernel/qeventdispatcher_glib.cpp:246 #19 0x7f0f19509eb2 in g_main_dispatch ../glib/gmain.c:3398 #20 0x7f0f19509eb2 in g_main_context_dispatch_unlocked ../glib/gmain.c:4249 previously allocated by thread T0 here: #0 0x7f0f25f2273b in operator new(unsigned long) ../../../../libsanitizer/asan/asan_new_delete.cpp:86 #1 0x7f0f2538e921 in KFileWidget::KFileWidget(QUrl const&, QWidget*) /home/nico/kde-qtdev/src/kio/src/filewidgets/kfilewidget.cpp:353 #2 0x00000058d086 in FileDialog::FileDialog(QDialog*, QFlags<Qt::WindowType>) /home/nico/kde-qtdev/src/xdg-desktop-portal-kde/src/filechooser.cpp:111 #3 0x00000059ad00 in FileChooserPortal::SaveFile(QDBusObjectPath const&, QString const&, QString const&, QString const&, QMap<QString, QVariant> cons #4 0x000000439a50 in FileChooserPortal::qt_static_metacall(QObject*, QMetaObject::Call, int, void**) /home/nico/kde-qtdev/build/xdg-desktop-portal-kd #5 0x00000043a043 in FileChooserPortal::qt_metacall(QMetaObject::Call, int, void**) /home/nico/kde-qtdev/build/xdg-desktop-portal-kde/src/xdg-desktop #6 0x7f0f1acc65da in QDBusConnectionPrivate::deliverCall(QObject*, QDBusMessage const&, QList<QMetaType> const&, int) /home/nico/workspace/qt6-dev/qt #7 0x7f0f1acce88f in QDBusConnectionPrivate::activateCall(QObject*, QFlags<QDBusConnection::RegisterOption>, QDBusMessage const&) /home/nico/workspac #8 0x7f0f1accffbe in QDBusConnectionPrivate::activateObject(QDBusConnectionPrivate::ObjectTreeNode&, QDBusMessage const&, int) /home/nico/workspace/q #9 0x7f0f1acd9655 in QDBusActivateObjectEvent::placeMetaCall(QObject*) /home/nico/workspace/qt6-dev/qtbase/src/dbus/qdbusintegrator.cpp:1613 #10 0x7f0f19ecb15a in QObject::event(QEvent*) /home/nico/workspace/qt6-dev/qtbase/src/corelib/kernel/qobject.cpp:1465 #11 0x7f0f1ce859fe in QApplicationPrivate::notify_helper(QObject*, QEvent*) /home/nico/workspace/qt6-dev/qtbase/src/widgets/kernel/qapplication.cpp:3 #12 0x7f0f1cea0f8a in QApplication::notify(QObject*, QEvent*) /home/nico/workspace/qt6-dev/qtbase/src/widgets/kernel/qapplication.cpp:3254 #13 0x7f0f19dbf37b in QCoreApplication::notifyInternal2(QObject*, QEvent*) /home/nico/workspace/qt6-dev/qtbase/src/corelib/kernel/qcoreapplication.cp #14 0x7f0f19dbf566 in QCoreApplication::sendEvent(QObject*, QEvent*) /home/nico/workspace/qt6-dev/qtbase/src/corelib/kernel/qcoreapplication.cpp:1549 #15 0x7f0f19dc18bc in QCoreApplicationPrivate::sendPostedEvents(QObject*, int, QThreadData*) /home/nico/workspace/qt6-dev/qtbase/src/corelib/kernel/q #16 0x7f0f19dc1bd7 in QCoreApplication::sendPostedEvents(QObject*, int) /home/nico/workspace/qt6-dev/qtbase/src/corelib/kernel/qcoreapplication.cpp:1 #17 0x7f0f1a67f17f in postEventSourceDispatch /home/nico/workspace/qt6-dev/qtbase/src/corelib/kernel/qeventdispatcher_glib.cpp:246 #18 0x7f0f19509eb2 in g_main_dispatch ../glib/gmain.c:3398 #19 0x7f0f19509eb2 in g_main_context_dispatch_unlocked ../glib/gmain.c:4249 SUMMARY: AddressSanitizer: heap-use-after-free /home/nico/kde-qtdev/usr/include/QtCore/qstring.h:239 in QString::size() const Timer that calls slotMimeFilterChanged But its correctly guarded? https://invent.kde.org/frameworks/kio/-/blob/master/src/filewidgets/kfilewidget.cpp#L1360 Deletion happens via deleteLater it seems I've tried every which way with randomized sleeps all over the place but I can't seem to trigger the crash. That said. KFileWidget has a number of internal eventloop spinning that may have a role to play here. But most/all of them are ExcludeUserInputEvents, so they shouldn't process a manual Esc hit, failing to explain the initial reproduction steps. It is however worth noting that there is a bool result = statJob->exec(); call just prior to the locationEditCurrentText call. Can you maybe get asan to print the complete delete trace? https://bugs.kde.org/show_bug.cgi?id=508085#c4 has "freed by thread T0 here:" if that's what you mean (In reply to Nicolas Fella from comment #8) > https://bugs.kde.org/show_bug.cgi?id=508085#c4 has "freed by thread T0 > here:" if that's what you mean That isn't the complete trace I think, note how it misses the _start frame. d_ed also had a thought that maybe running through valgrind may give some hints. FWIW the only viable theory we have right now: - slotMimeFilterChanged runs. everything is dandy still. all objects exist - some nested eventloop::exec inside kfilewidget - finished gets emitted - deleteLater gets called - deleteLater gets executed - eventloop ends - slotMimeFilterChanged runs on deleted objects - kaboom! I ran into this bug on my own. Observations: - If I run set -Ux GTK_USE_PORTAL 1 in Fish, launching Firefox by clicking SyncThingy will not set the variable but fall back to GTK file dialogs. Launching Firefox from a pinned app will. This is strange because in both cases Firefox is spawned by systemd --user -> /usr/lib64/firefox/firefox. - You don't need to click Esc to trigger the bug; I've triggered crashes by repeatedly saving an image, then clicking Save or pressing Enter or Alt+S (<50% success rate each time). In the past when faced with this kind of mystery crash, I've had success adding logging to program control flow. I would record events which happened, check for program inconsistencies, and dump the sequence of events to a file (and alert the user) if an error was detected. My code is located at https://github.com/Dn-Programming-Core-Management/Dn-FamiTracker/blob/b4ea10d93bfbd9bac906f59d7e619d765e23463e/Source/SoundGen.cpp#L77-L180. The bug I was tracing was harder because it was multithreaded (is this one too?) and extremely rare to catch, while this KDE one is harder because (looking at the ASan log) it involves complex Qt control flow like d-pointers, the Qt event loop, and timers. The primary barrier here is that I don't know the desktop portal codebase or how to build and run a modified codebase locally; I think the people most equipped to track this down are existing KDE developers. - The design of "multiple file dialogs from one server process" suggests using actor concurrency/memory management to isolate this behavior? I don't know much about it. |