From a949c9f2b090435ca63de525ee2cd1a79073f08a Mon Sep 17 00:00:00 2001 From: George Hazan Date: Sun, 25 Oct 2020 13:00:15 +0300 Subject: fixes #2569 (Miranda uses libmdbx unsafely) --- libs/libmdbx/src/mdbx.c | 3 ++ plugins/Dbx_mdbx/src/dbevents.cpp | 2 +- plugins/Dbx_mdbx/src/dbintf.cpp | 68 ++++++++++++++++++++++++++++----------- plugins/Dbx_mdbx/src/dbintf.h | 13 +++----- 4 files changed, 58 insertions(+), 28 deletions(-) diff --git a/libs/libmdbx/src/mdbx.c b/libs/libmdbx/src/mdbx.c index 2fa4734952..bb565a72b7 100644 --- a/libs/libmdbx/src/mdbx.c +++ b/libs/libmdbx/src/mdbx.c @@ -8872,6 +8872,9 @@ static void mdbx_cursors_eot(MDBX_txn *txn, unsigned merge) { MDBX_xcursor *mx; int i; + if (cursors == nullptr) + return; + for (i = txn->mt_numdbs; --i >= 0;) { for (mc = cursors[i]; mc; mc = next) { unsigned stage = mc->mc_signature; diff --git a/plugins/Dbx_mdbx/src/dbevents.cpp b/plugins/Dbx_mdbx/src/dbevents.cpp index 3114962438..75f20fac88 100644 --- a/plugins/Dbx_mdbx/src/dbevents.cpp +++ b/plugins/Dbx_mdbx/src/dbevents.cpp @@ -278,7 +278,7 @@ bool CDbxMDBX::EditEvent(MCONTACT contactID, MEVENT hDbEvent, const DBEVENTINFO return false; } - DBFlush(); + DBFlush(true); // Notify only in safe mode or on really new events if (m_safetyMode && !(dbei->flags & DBEF_TEMPORARY)) diff --git a/plugins/Dbx_mdbx/src/dbintf.cpp b/plugins/Dbx_mdbx/src/dbintf.cpp index 6626204834..a36e51a37f 100644 --- a/plugins/Dbx_mdbx/src/dbintf.cpp +++ b/plugins/Dbx_mdbx/src/dbintf.cpp @@ -40,6 +40,11 @@ CDbxMDBX::CDbxMDBX(const TCHAR *tszFileName, int iMode) : CDbxMDBX::~CDbxMDBX() { + if (m_txnWrite) { + mdbx_txn_commit(m_txnWrite); + m_txnWrite = nullptr; + } + mdbx_env_close(m_env); if (!m_bReadOnly) @@ -61,8 +66,9 @@ int CDbxMDBX::Load() { MDBX_db_flags_t defFlags = MDBX_CREATE; { - txn_ptr trnlck(StartTran()); - if (trnlck == nullptr) { + m_txnWrite = nullptr; + m_dbError = mdbx_txn_begin(m_env, nullptr, (m_bReadOnly) ? MDBX_TXN_RDONLY : MDBX_TXN_READWRITE, &m_txnWrite); + if (m_txnWrite == nullptr) { if (m_dbError == MDBX_TXN_FULL) { if (IDOK == MessageBox(NULL, TranslateT("Your database is in the obsolete format. Click OK to read the upgrade instructions or Cancel to exit"), TranslateT("Error"), MB_ICONERROR | MB_OKCANCEL)) Utils_OpenUrl("https://www.miranda-ng.org/news/unknown-profile-format"); @@ -70,20 +76,20 @@ int CDbxMDBX::Load() } return EGROKPRF_DAMAGED; } - - mdbx_dbi_open(trnlck, "global", defFlags | MDBX_INTEGERKEY, &m_dbGlobal); - mdbx_dbi_open(trnlck, "crypto", defFlags, &m_dbCrypto); - mdbx_dbi_open(trnlck, "contacts", defFlags | MDBX_INTEGERKEY, &m_dbContacts); - mdbx_dbi_open(trnlck, "modules", defFlags | MDBX_INTEGERKEY, &m_dbModules); - mdbx_dbi_open(trnlck, "events", defFlags | MDBX_INTEGERKEY, &m_dbEvents); - mdbx_dbi_open_ex(trnlck, "eventids", defFlags, &m_dbEventIds, DBEventIdKey::Compare, nullptr); - mdbx_dbi_open_ex(trnlck, "eventsrt", defFlags, &m_dbEventsSort, DBEventSortingKey::Compare, nullptr); - mdbx_dbi_open_ex(trnlck, "settings", defFlags, &m_dbSettings, DBSettingKey::Compare, nullptr); + mdbx_dbi_open(m_txnWrite, "global", defFlags | MDBX_INTEGERKEY, &m_dbGlobal); + mdbx_dbi_open(m_txnWrite, "crypto", defFlags, &m_dbCrypto); + mdbx_dbi_open(m_txnWrite, "contacts", defFlags | MDBX_INTEGERKEY, &m_dbContacts); + mdbx_dbi_open(m_txnWrite, "modules", defFlags | MDBX_INTEGERKEY, &m_dbModules); + mdbx_dbi_open(m_txnWrite, "events", defFlags | MDBX_INTEGERKEY, &m_dbEvents); + + mdbx_dbi_open_ex(m_txnWrite, "eventids", defFlags, &m_dbEventIds, DBEventIdKey::Compare, nullptr); + mdbx_dbi_open_ex(m_txnWrite, "eventsrt", defFlags, &m_dbEventsSort, DBEventSortingKey::Compare, nullptr); + mdbx_dbi_open_ex(m_txnWrite, "settings", defFlags, &m_dbSettings, DBSettingKey::Compare, nullptr); uint32_t keyVal = 1; MDBX_val key = { &keyVal, sizeof(keyVal) }, data; - if (mdbx_get(trnlck, m_dbGlobal, &key, &data) == MDBX_SUCCESS) { + if (mdbx_get(m_txnWrite, m_dbGlobal, &key, &data) == MDBX_SUCCESS) { const DBHeader *hdr = (const DBHeader*)data.iov_base; if (hdr->dwSignature != DBHEADER_SIGNATURE) return EGROKPRF_DAMAGED; @@ -96,15 +102,16 @@ int CDbxMDBX::Load() m_header.dwSignature = DBHEADER_SIGNATURE; m_header.dwVersion = DBHEADER_VERSION; data.iov_base = &m_header; data.iov_len = sizeof(m_header); - mdbx_put(trnlck, m_dbGlobal, &key, &data, MDBX_UPSERT); + mdbx_put(m_txnWrite, m_dbGlobal, &key, &data, MDBX_UPSERT); DBFlush(); } keyVal = 2; - if (mdbx_get(trnlck, m_dbGlobal, &key, &data) == MDBX_SUCCESS) + if (mdbx_get(m_txnWrite, m_dbGlobal, &key, &data) == MDBX_SUCCESS) m_ccDummy.dbc = *(const DBContact*)data.iov_base; - trnlck.commit(); + mdbx_txn_commit(m_txnWrite); + m_txnWrite = nullptr; } mdbx_txn_begin(m_env, nullptr, MDBX_TXN_RDONLY, &m_txn_ro); @@ -218,6 +225,24 @@ void CDbxMDBX::SetCacheSafetyMode(BOOL bIsSet) ///////////////////////////////////////////////////////////////////////////////////////// +MDBX_txn* CDbxMDBX::StartTran() +{ + if (m_txnWrite == nullptr) { + m_dbError = mdbx_txn_begin(m_env, nullptr, (m_bReadOnly) ? MDBX_TXN_RDONLY : MDBX_TXN_READWRITE, &m_txnWrite); + _ASSERT(m_dbError == MDBX_SUCCESS); + if (m_dbError != MDBX_SUCCESS) + return nullptr; + } + + MDBX_txn *res = 0; + m_dbError = mdbx_txn_begin(m_env, m_txnWrite, (m_bReadOnly) ? MDBX_TXN_RDONLY : MDBX_TXN_READWRITE, &res); + /* FIXME: throw an exception */ + _ASSERT(m_dbError == MDBX_SUCCESS); + return res; +} + +///////////////////////////////////////////////////////////////////////////////////////// + static void assert_func(const MDBX_env*, const char *msg, const char *function, unsigned line) MDBX_CXX17_NOEXCEPT { Netlib_Logf(nullptr, "MDBX: assertion failed (%s, %d): %s", function, line, msg); @@ -255,7 +280,7 @@ int CDbxMDBX::Map() if (rc != MDBX_SUCCESS) return EGROKPRF_CANTREAD; - MDBX_env_flags_t mode = MDBX_NOSUBDIR | MDBX_MAPASYNC | MDBX_WRITEMAP | MDBX_SAFE_NOSYNC | MDBX_COALESCE | MDBX_EXCLUSIVE; + MDBX_env_flags_t mode = MDBX_NOSUBDIR | MDBX_SAFE_NOSYNC | MDBX_COALESCE | MDBX_EXCLUSIVE; if (m_bReadOnly) mode |= MDBX_RDONLY; @@ -286,8 +311,15 @@ void CDbxMDBX::TouchFile() void CDbxMDBX::DBFlush(bool bForce) { - if (bForce) - mdbx_env_sync(m_env); + if (bForce) { + if (m_txnWrite) { + mir_cslock trnlck(m_csDbAccess); + + mdbx_txn_commit(m_txnWrite); + m_txnWrite = nullptr; + mdbx_txn_begin(m_env, nullptr, (m_bReadOnly) ? MDBX_TXN_RDONLY : MDBX_TXN_READWRITE, &m_txnWrite); + } + } else if (m_safetyMode) m_impl.m_timer.Start(50); diff --git a/plugins/Dbx_mdbx/src/dbintf.h b/plugins/Dbx_mdbx/src/dbintf.h index 9dadb8a8fc..d2c8811d8b 100644 --- a/plugins/Dbx_mdbx/src/dbintf.h +++ b/plugins/Dbx_mdbx/src/dbintf.h @@ -158,15 +158,6 @@ class CDbxMDBX : public MDatabaseCommon, public MIDatabaseChecker, public MZeroe } } m_impl; - __forceinline MDBX_txn* StartTran() - { - MDBX_txn *res = 0; - m_dbError = mdbx_txn_begin(m_env, nullptr, (m_bReadOnly) ? MDBX_TXN_RDONLY : MDBX_TXN_READWRITE, &res); - /* FIXME: throw an exception */ - _ASSERT(m_dbError == MDBX_SUCCESS); - return res; - } - bool CheckEvent(DBCachedContact *cc, const DBEvent *dbe, DBCachedContact *&cc2); bool EditEvent(MCONTACT contactID, MEVENT hDbEvent, const DBEVENTINFO *dbe, bool bNew); void FillContacts(void); @@ -174,6 +165,8 @@ class CDbxMDBX : public MDatabaseCommon, public MIDatabaseChecker, public MZeroe void TouchFile(void); void UpdateMenuItem(void); + MDBX_txn* StartTran(); + //////////////////////////////////////////////////////////////////////////// // database stuff @@ -187,6 +180,8 @@ class CDbxMDBX : public MDatabaseCommon, public MIDatabaseChecker, public MZeroe MDBX_dbi m_dbGlobal; DBHeader m_header; + MDBX_txn *m_txnWrite = nullptr; + DBCachedContact m_ccDummy; // dummy contact to serve a cache item for MCONTACT = 0 //////////////////////////////////////////////////////////////////////////// -- cgit v1.2.3