Commit dce1059
fix(fdosecrets): handle Secret Service requests during database load
A SearchItems call arriving while a database is still being opened crashed
the application. Reading the KDBX4 payload spins a nested event loop, and
Service::onDatabaseTabOpened has inserted the new Collection into
m_collections before Collection::reloadBackend has finished populating it.
In that window the backend database is not locked but m_exposedGroup is
still null, so Collection::searchItems dereferences a null group via the
UUID/path fast paths or EntrySearcher (Group::groupsRecursive with
this == nullptr).
The half-loaded state was also observable as inconsistent state to clients:
the Locked property reported false while SearchItems returned empty, which
a client interprets as "the entry isn't there" and behaves accordingly.
Introduce collectionLocked() as the predicate the public DBus API uses
(Locked, ensureUnlocked, label, SearchItems, and the collectionLockChanged
signal payload). It is true when the database is locked or while
m_exposedGroup is not yet established, so during the populate window
clients consistently see Locked=true and SearchItems empty rather than the
inconsistent mix. backendLocked() keeps its prior meaning (database locked,
uninitialised, or absent) and is used by the bootstrap path in
reloadBackend and by signal-handler guards that run only when
m_exposedGroup is already set.
cleanupConnections() now also clears m_exposedGroup and m_entryToItem.
Without that, after a database reload the collection would still appear
searchable through stale signal wiring, and the UUID/path shortcuts in
searchItems would consult a map pointing at removed Item objects.
KeePassXC has an "unlock before search" setting that prompts the user to
unlock a database whenever SearchItems finds no unlocked collection. With
the consistency fix above, a half-loaded collection counts as locked, so
the populate window now also satisfies that "no unlocked collection"
condition. The prompt would then open for a database already on its way
to being unlocked, with no actually-locked database to offer - an empty
dialog the user cannot act on. Service::searchItems therefore also
requires that at least one DatabaseWidget actually be locked before
opening the prompt. During the populate window SearchItems returns empty
results; populate completes on its own and a follow-up call from the
client returns real data.
Test Plan:
- Build and run testfdosecrets and testentrysearcher with
WITH_XC_FDOSECRETS=ON and WITH_TESTS=ON.
- Manual: with unlockBeforeSearch=on and an AutoOpen child database,
SearchItems calls during the load window no longer crash, no empty
unlock dialog appears, and a retry once populate completes returns
real data.
- Original crash locally reproduced with gdb --args keepassxc.
Co-Authored-By: Codex GPT-5.5 (xhigh) <noreply@openai.com>
Co-Authored-By: Claude Opus 4.7 (1M context) (xhigh) <noreply@anthropic.com>1 parent 7c7ca45 commit dce1059
3 files changed
Lines changed: 35 additions & 8 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
79 | 79 | | |
80 | 80 | | |
81 | 81 | | |
82 | | - | |
| 82 | + | |
83 | 83 | | |
84 | 84 | | |
85 | 85 | | |
| |||
107 | 107 | | |
108 | 108 | | |
109 | 109 | | |
110 | | - | |
| 110 | + | |
111 | 111 | | |
112 | 112 | | |
113 | 113 | | |
| |||
130 | 130 | | |
131 | 131 | | |
132 | 132 | | |
133 | | - | |
| 133 | + | |
134 | 134 | | |
135 | 135 | | |
136 | 136 | | |
| |||
159 | 159 | | |
160 | 160 | | |
161 | 161 | | |
162 | | - | |
| 162 | + | |
163 | 163 | | |
164 | 164 | | |
165 | 165 | | |
| |||
219 | 219 | | |
220 | 220 | | |
221 | 221 | | |
222 | | - | |
| 222 | + | |
223 | 223 | | |
224 | | - | |
| 224 | + | |
225 | 225 | | |
226 | 226 | | |
227 | 227 | | |
| |||
395 | 395 | | |
396 | 396 | | |
397 | 397 | | |
398 | | - | |
| 398 | + | |
399 | 399 | | |
400 | 400 | | |
401 | 401 | | |
| |||
606 | 606 | | |
607 | 607 | | |
608 | 608 | | |
| 609 | + | |
609 | 610 | | |
| 611 | + | |
610 | 612 | | |
611 | 613 | | |
612 | 614 | | |
| |||
621 | 623 | | |
622 | 624 | | |
623 | 625 | | |
| 626 | + | |
624 | 627 | | |
625 | 628 | | |
626 | 629 | | |
| 630 | + | |
| 631 | + | |
| 632 | + | |
| 633 | + | |
| 634 | + | |
| 635 | + | |
| 636 | + | |
| 637 | + | |
| 638 | + | |
627 | 639 | | |
628 | 640 | | |
629 | 641 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
145 | 145 | | |
146 | 146 | | |
147 | 147 | | |
| 148 | + | |
148 | 149 | | |
149 | 150 | | |
150 | 151 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
275 | 275 | | |
276 | 276 | | |
277 | 277 | | |
278 | | - | |
| 278 | + | |
| 279 | + | |
| 280 | + | |
| 281 | + | |
| 282 | + | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
| 288 | + | |
| 289 | + | |
| 290 | + | |
| 291 | + | |
| 292 | + | |
279 | 293 | | |
280 | 294 | | |
281 | 295 | | |
| |||
0 commit comments