[utilities/krusader] app/BookMan: BookMan: Fix use-after-free problems when accessing asynchronously deleted bookmarks

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

BookMan: Fix use-after-free problems when accessing asynchronously deleted bookmarks

Previously, if a bookmark (or bookmark folder) was deleted in the background
(e.g. via the file watcher detecting changes to the XML file) while
the bookmark menu was actively open, right-clicking the now-deleted
item referenced a dangling raw pointer, causing an abrupt termination.

By storing a `QPointer` in the action's `QVariant` data and checking
its validity in the event filter, Krusader is able to safely ignore
clicks on objects that have been destroyed in the background.

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

M  +8    -5    app/BookMan/krbookmarkhandler.cpp
M  +0    -2    app/BookMan/krbookmarkhandler.h

https://invent.kde.org/utilities/krusader/-/commit/a8395f60142cd044e83c65b5d4cec813911f5e79

diff --git a/app/BookMan/krbookmarkhandler.cpp b/app/BookMan/krbookmarkhandler.cpp
index 70cbd5f91..010aca6cf 100644
--- a/app/BookMan/krbookmarkhandler.cpp
+++ b/app/BookMan/krbookmarkhandler.cpp
@@ -449,8 +449,7 @@ void KrBookmarkHandler::buildMenu(KrBookmark *parent, QMenu *menu, int depth)
         newMenu->setIcon(Icon(bm->iconName()));
         newMenu->setTitle(bm->text());
         QAction *menuAction = menu->addMenu(newMenu);
-        QVariant v;
-        v.setValue(bm);
+        QVariant v = QVariant::fromValue(QPointer<KrBookmark>(bm));
         menuAction->setData(v);
 
         buildMenu(bm, newMenu, depth + 1);
@@ -779,9 +778,13 @@ bool KrBookmarkHandler::eventFilter(QObject *obj, QEvent *ev)
                 if (bm != nullptr) {
                     rightClicked(menu, bm);
                     return true;
-                } else if (act && act->data().canConvert<KrBookmark *>()) {
-                    bm = act->data().value<KrBookmark *>();
-                    rightClicked(menu, bm);
+                } else if (act && act->data().canConvert<QPointer<KrBookmark>>()) {
+                    QPointer<KrBookmark> bmPtr = act->data().value<QPointer<KrBookmark>>();
+                    // Safely check if the object still exists
+                    if (bmPtr) {
+                        rightClicked(menu, bmPtr.data());
+                    }
+                    // If bmPtr is null, the object was deleted in the background; therefore, ignore the click
                 }
             }
             break;
diff --git a/app/BookMan/krbookmarkhandler.h b/app/BookMan/krbookmarkhandler.h
index 12abd0674..8d79e6846 100644
--- a/app/BookMan/krbookmarkhandler.h
+++ b/app/BookMan/krbookmarkhandler.h
@@ -88,6 +88,4 @@ private:
     QMenu *_dummyMenu; ///< A dummy menu to properly init actions
 };
 
-Q_DECLARE_METATYPE(KrBookmark *)
-
 #endif // KRBOOKMARK_HANDLER_H
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.