https://bugs.kde.org/show_bug.cgi?id=509854

--- Comment #13 from firewalker <[email protected]> ---
I tested the free version of Claude (An AI engine). After some back and forth
with test programs it produced a patch that seems to solve the issue.

Avoid nested event loop in dropEvent() for local files

Konsole::TerminalDisplay::dropEvent() runs KIO::StatJob::exec() (via
extractDroppedText() and setupCdToUrlAction()) before calling
KIO::drop(event, ...). exec() spins a nested event loop. On Wayland this
can destroy the data offer backing event->mimeData(), so KIO::drop() ends
up constructing a QPointer from a dangling QMimeData* and crashes in
QtSharedPointer::ExternalRefCountData::getAndRef().

Local files are already their own "most local URL", so skip the stat job
for them and only use it for remote URLs.

BUG: 509854

--- a/src/terminalDisplay/TerminalDisplay.cpp
+++ b/src/terminalDisplay/TerminalDisplay.cpp
@@ -3170,12 +3170,17 @@
 {
     QString dropText;
     for (int i = 0; i < urls.count(); i++) {
-        KIO::StatJob *job = KIO::mostLocalUrl(urls[i], KIO::HideProgressInfo);
-        if (!job->exec()) {
-            continue;
+        QUrl url = urls[i];
+        // Local files are already "most local". Only run the (blocking) stat
job for
+        // other URLs: job->exec() spins a nested event loop, which must be
avoided for
+        // local files inside dropEvent() (see the comment there).
+        if (!url.isLocalFile()) {
+            KIO::StatJob *job = KIO::mostLocalUrl(url, KIO::HideProgressInfo);
+            if (!job->exec()) {
+                continue;
+            }
+            url = job->mostLocalUrl();
         }
-
-        const QUrl url = job->mostLocalUrl();
         // in future it may be useful to be able to insert file names with
drag-and-drop
         // without quoting them (this only affects paths with spaces in)
         dropText += KShell::quoteArg(url.isLocalFile() ? url.path() :
url.url());
@@ -3188,12 +3193,15 @@

 void setupCdToUrlAction(const QString &dropText, const QUrl &url,
QList<QAction *> &additionalActions, TerminalDisplay *display)
 {
-    KIO::StatJob *job = KIO::mostLocalUrl(url, KIO::HideProgressInfo);
-    if (!job->exec()) {
-        return;
+    QUrl localUrl = url;
+    if (!localUrl.isLocalFile()) {
+        // See extractDroppedText(): avoid the nested event loop for local
files.
+        KIO::StatJob *job = KIO::mostLocalUrl(url, KIO::HideProgressInfo);
+        if (!job->exec()) {
+            return;
+        }
+        localUrl = job->mostLocalUrl();
     }
-
-    const QUrl localUrl = job->mostLocalUrl();
     if (!localUrl.isLocalFile()) {
         return;
     }
@@ -3229,7 +3237,10 @@

     QString dropText;
     if (!urls.isEmpty()) {
-        // might invalidate mimeData thanks to job->exec()
+        // Beware: extractDroppedText() and setupCdToUrlAction() may run a
nested event
+        // loop (job->exec()) for non-local URLs. On Wayland that can destroy
the data
+        // offer behind mimeData, so KIO::drop() below would use a dangling
pointer.
+        // They therefore skip the stat job for local files.
         dropText = extractDroppedText(urls);

         // If our target is local we will open a popup - otherwise the
fallback kicks

-- 
You are receiving this mail because:
You are watching all bug changes.

Reply via email to