From 22af66e3b586583b2d8493b524accfc546cddf32 Mon Sep 17 00:00:00 2001 From: Janek Bevendorff Date: Fri, 8 Nov 2019 13:34:40 +0100 Subject: [PATCH] Ensure database contents are released right away. When we lock a database, we reset the database pointer to free its resources. Since various other widgets besides the DatabaseWidget hold references to the shared pointer object, however, it cannot be guaranteed that the actual database object will be freed right away. This patch adds a releaseData() method which is called upon database lock to ensure all residual data is cleared without having to rely on the actual database object being cleaned up. --- src/core/Database.cpp | 42 +++++++++++++++++++++++++++++++++----- src/core/Database.h | 7 ++++--- src/gui/DatabaseWidget.cpp | 2 ++ 3 files changed, 43 insertions(+), 8 deletions(-) diff --git a/src/core/Database.cpp b/src/core/Database.cpp index eb01f7314..e62124d0a 100644 --- a/src/core/Database.cpp +++ b/src/core/Database.cpp @@ -72,11 +72,7 @@ Database::Database(const QString& filePath) Database::~Database() { - s_uuidMap.remove(m_uuid); - - if (m_modified) { - emit databaseDiscarded(); - } + releaseData(); } QUuid Database::uuid() const @@ -378,6 +374,42 @@ bool Database::import(const QString& xmlExportPath, QString* error) return true; } +/** + * Release all stored group, entry, and meta data of this database. + * + * Call this method to ensure all data is cleared even if valid + * pointers to this Database object are still being held. + * + * A previously reparented root group will not be freed. + */ +void Database::releaseData() +{ + s_uuidMap.remove(m_uuid); + m_uuid = QUuid(); + + if (m_modified) { + emit databaseDiscarded(); + } + + m_data = DatabaseData(); + + if (m_rootGroup && m_rootGroup->parent() == this) { + delete m_rootGroup; + } + if (m_metadata) { + delete m_metadata; + } + if (m_fileWatcher) { + delete m_fileWatcher; + } + + m_deletedObjects.clear(); + m_commonUsernames.clear(); + + m_initialized = false; + m_modified = false; +} + /** * Remove the old backup and replace it with a new one * backups are named .old. diff --git a/src/core/Database.h b/src/core/Database.h index 7f504cc55..afb89271e 100644 --- a/src/core/Database.h +++ b/src/core/Database.h @@ -29,7 +29,6 @@ #include "crypto/kdf/Kdf.h" #include "format/KeePass2.h" #include "keys/CompositeKey.h" - class Entry; enum class EntryReferenceType; class FileWatcher; @@ -76,6 +75,8 @@ public: bool extract(QByteArray&, QString* error = nullptr); bool import(const QString& xmlExportPath, QString* error = nullptr); + void releaseData(); + bool isInitialized() const; void setInitialized(bool initialized); bool isModified() const; @@ -182,9 +183,9 @@ private: bool restoreDatabase(const QString& filePath); bool performSave(const QString& filePath, QString* error, bool atomic, bool backup); - Metadata* const m_metadata; + QPointer const m_metadata; DatabaseData m_data; - Group* m_rootGroup; + QPointer m_rootGroup; QList m_deletedObjects; QPointer m_timer; QPointer m_fileWatcher; diff --git a/src/gui/DatabaseWidget.cpp b/src/gui/DatabaseWidget.cpp index 54f2a2f47..29942571c 100644 --- a/src/gui/DatabaseWidget.cpp +++ b/src/gui/DatabaseWidget.cpp @@ -418,6 +418,8 @@ void DatabaseWidget::replaceDatabase(QSharedPointer db) // Keep the instance active till the end of this function Q_UNUSED(oldDb); #endif + + oldDb->releaseData(); } void DatabaseWidget::cloneEntry()