[utilities/krusader] app/BookMan: BookMan: Fix premature deletions in deleteBookmark() and clearBookmarks()

Toni Asensi Esteve <[email protected]>
Newsgroups gmane.comp.kde.cvs
Message-ID <[email protected]>
Git commit 95458c05a2f6b304124b24afd9ceafe2cc3ee558 by Toni Asensi Esteve.
Committed on 16/08/2026 at 22:14.
Pushed by asensi into branch 'master'.

BookMan: Fix premature deletions in deleteBookmark() and clearBookmarks()

Fix use-after-free crashes during bookmark deletion by
replacing synchronous `delete bm;` with `bm->deleteLater()`
in `deleteBookmark()` and `clearBookmarks()`. This prevents
use-after-free problems (caught by AddressSanitizer) caused by
deleting the QAction while Qt's context menu event loop
is still actively evaluating the user's click.

Revision: https://invent.kde.org/utilities/krusader/-/merge_requests/193

M  +12   -6    app/BookMan/krbookmarkhandler.cpp

https://invent.kde.org/utilities/krusader/-/commit/95458c05a2f6b304124b24afd9ceafe2cc3ee558

diff --git a/app/BookMan/krbookmarkhandler.cpp b/app/BookMan/krbookmarkhandler.cpp
index e0794949b..66836e140 100644
--- a/app/BookMan/krbookmarkhandler.cpp
+++ b/app/BookMan/krbookmarkhandler.cpp
@@ -142,9 +142,15 @@ void KrBookmarkHandler::deleteBookmark(KrBookmark *bm)
     removeReferences(_root, bm);
 
     const auto widgets = bm->associatedObjects();
-    for (QObject *w : widgets)
-        qobject_cast<QWidget *>(w)->removeAction(bm);
-    delete bm;
+    for (QObject *w : widgets) {
+        if (QWidget *widget = qobject_cast<QWidget *>(w)) {
+            widget->removeAction(bm);
+        }
+    }
+
+    // Perform a safe asynchronous deletion (it prevents deleting the action
+    // while Qt's context menu event loop is still actively evaluating it)
+    bm->deleteLater();
 
     exportToFile();
 }
@@ -567,9 +573,9 @@ void KrBookmarkHandler::clearBookmarks(KrBookmark *root, bool removeBookmarks)
 
         if (bm->isFolder()) {
             clearBookmarks(bm, removeBookmarks);
-            delete bm;
+            bm->deleteLater();
         } else if (bm->isSeparator()) {
-            delete bm;
+            bm->deleteLater();
         } else if (removeBookmarks) {
             const auto widgets = bm->associatedObjects();
             for (QObject *w : widgets) {
@@ -577,7 +583,7 @@ void KrBookmarkHandler::clearBookmarks(KrBookmark *root, bool removeBookmarks)
                     widget->removeAction(bm);
                 }
             }
-            delete bm;
+            bm->deleteLater();
         }
     }
 }
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.