[utilities/krusader] app/BookMan: BookMan: Solve 'After adding the same bookmark multiple times, only one instance is displayed and later Krusader ends abruptly'

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

BookMan: Solve 'After adding the same bookmark multiple times, only one instance is displayed and later Krusader ends abruptly'

Solve a mismatch between the `krbookmarks.xml` format (which allows
multiple bookmarks to use the same display name) and KActionCollection
(which uses string names in order to identify pointers).

Now, the `importFromFileBookmark` function checks the `seenBookmarks`
QSet. If an action name has already been claimed during the current
parsing pass, it automatically generates a unique internal suffix
(e.g. `_2`, `_3`).

This allows Krusader to safely allocate distinct KrBookmark pointers
for every entry in the XML file, preserving user data and avoiding
use-after-free and double-free problems.

FIXED: [ 524076 ] After adding the same bookmark multiple times, only one instance is displayed and later Krusader ends abruptly
BUG: 524076

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

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

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

diff --git a/app/BookMan/krbookmarkhandler.cpp b/app/BookMan/krbookmarkhandler.cpp
index 6e96da792..807ab5462 100644
--- a/app/BookMan/krbookmarkhandler.cpp
+++ b/app/BookMan/krbookmarkhandler.cpp
@@ -274,20 +274,38 @@ bool KrBookmarkHandler::importFromFileBookmark(QDomElement &e, KrBookmark *paren
     if (e.hasAttribute("icon")) {
         iconName = e.attribute("icon");
     }
-    // ok: got name and url, let's add a bookmark
-    KrBookmark *bm = KrBookmark::getExistingBookmark(path + name, _collection);
-    if (!bm) {
-        bm = new KrBookmark(name, QUrl(url), _collection, iconName, path + name);
-    } else {
-        bm->setURL(QUrl(url));
-        bm->setIconName(iconName);
+    // ok: got name and url, let's add a bookmark safely allowing duplicates
+    KrBookmark *bm = nullptr;
+    QString baseActionName = path + name;
+    QString actionName = baseActionName;
+    int suffix = 1;
+
+    // Loop to find an unused internal action name. This allows having
+    // multiple bookmarks with the exact same display name
+    // to exist as distinct pointers
+    while (true) {
+        bm = KrBookmark::getExistingBookmark(actionName, _collection);
+        if (!bm) {
+            // No bookmark exists with this internal actionName.
+            // Create a new bookmark safely
+            bm = new KrBookmark(name, QUrl(url), _collection, iconName, actionName);
+            break;
+        } else if (!seenBookmarks.contains(bm)) {
+            // We have found an existing one that hasn't been added to
+            // the tree yet in this pass. Reuse it
+            bm->setURL(QUrl(url));
+            bm->setIconName(iconName);
+            break;
+        }
+        // This pointer was already used (it's a duplicate name in the XML).
+        // Increment the suffix and check for (or create) a unique internal action name
+        suffix++;
+        actionName = baseActionName + "_" + QString::number(suffix);
     }
 
-    // Prevent duplicated pointers in the tree (in order to stop double-frees)
-    if (!seenBookmarks.contains(bm)) {
-        parent->children().append(bm);
-        seenBookmarks.insert(bm);
-    }
+    // Append it to the tree and record it in the guard set
+    parent->children().append(bm);
+    seenBookmarks.insert(bm);
 
     return true;
 }
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.