summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorNicolas Werner <nicolas.werner@hotmail.de>2020-07-30 18:13:19 +0200
committerNicolas Werner <nicolas.werner@hotmail.de>2020-07-30 18:13:19 +0200
commit7f3d97517f334cbc9b07100d20acb612a3293bfd (patch)
tree6f84ee2c9799d26e1faec5b66158c1420c4c2894 /src
parentAdd workaround for duplicate syncs (diff)
downloadnheko-7f3d97517f334cbc9b07100d20acb612a3293bfd.tar.xz
Fix double free by closing cursor at the right time
Diffstat (limited to 'src')
-rw-r--r--src/Cache.cpp59
1 files changed, 33 insertions, 26 deletions
diff --git a/src/Cache.cpp b/src/Cache.cpp
index 628062a1..0c692d07 100644
--- a/src/Cache.cpp
+++ b/src/Cache.cpp
@@ -2199,27 +2199,31 @@ Cache::firstPendingMessage(const std::string &room_id)
         auto txn     = lmdb::txn::begin(env_);
         auto pending = getPendingMessagesDb(txn, room_id);
 
-        auto pendingCursor = lmdb::cursor::open(txn, pending);
-        lmdb::val tsIgnored, pendingTxn;
-        while (pendingCursor.get(tsIgnored, pendingTxn, MDB_NEXT)) {
-                auto eventsDb = getEventsDb(txn, room_id);
-                lmdb::val event;
-                if (!lmdb::dbi_get(txn, eventsDb, pendingTxn, event)) {
-                        lmdb::dbi_del(txn, pending, tsIgnored, pendingTxn);
-                        continue;
-                }
+        {
+                auto pendingCursor = lmdb::cursor::open(txn, pending);
+                lmdb::val tsIgnored, pendingTxn;
+                while (pendingCursor.get(tsIgnored, pendingTxn, MDB_NEXT)) {
+                        auto eventsDb = getEventsDb(txn, room_id);
+                        lmdb::val event;
+                        if (!lmdb::dbi_get(txn, eventsDb, pendingTxn, event)) {
+                                lmdb::dbi_del(txn, pending, tsIgnored, pendingTxn);
+                                continue;
+                        }
 
-                try {
-                        mtx::events::collections::TimelineEvent te;
-                        mtx::events::collections::from_json(
-                          json::parse(std::string_view(event.data(), event.size())), te);
+                        try {
+                                mtx::events::collections::TimelineEvent te;
+                                mtx::events::collections::from_json(
+                                  json::parse(std::string_view(event.data(), event.size())), te);
 
-                        txn.commit();
-                        return te;
-                } catch (std::exception &e) {
-                        nhlog::db()->error("Failed to parse message from cache {}", e.what());
-                        lmdb::dbi_del(txn, pending, tsIgnored, pendingTxn);
-                        continue;
+                                pendingCursor.close();
+                                txn.commit();
+                                return te;
+                        } catch (std::exception &e) {
+                                nhlog::db()->error("Failed to parse message from cache {}",
+                                                   e.what());
+                                lmdb::dbi_del(txn, pending, tsIgnored, pendingTxn);
+                                continue;
+                        }
                 }
         }
 
@@ -2231,13 +2235,16 @@ Cache::firstPendingMessage(const std::string &room_id)
 void
 Cache::removePendingStatus(const std::string &room_id, const std::string &txn_id)
 {
-        auto txn           = lmdb::txn::begin(env_);
-        auto pending       = getPendingMessagesDb(txn, room_id);
-        auto pendingCursor = lmdb::cursor::open(txn, pending);
-        lmdb::val tsIgnored, pendingTxn;
-        while (pendingCursor.get(tsIgnored, pendingTxn, MDB_NEXT)) {
-                if (std::string_view(pendingTxn.data(), pendingTxn.size()) == txn_id)
-                        lmdb::cursor_del(pendingCursor);
+        auto txn     = lmdb::txn::begin(env_);
+        auto pending = getPendingMessagesDb(txn, room_id);
+
+        {
+                auto pendingCursor = lmdb::cursor::open(txn, pending);
+                lmdb::val tsIgnored, pendingTxn;
+                while (pendingCursor.get(tsIgnored, pendingTxn, MDB_NEXT)) {
+                        if (std::string_view(pendingTxn.data(), pendingTxn.size()) == txn_id)
+                                lmdb::cursor_del(pendingCursor);
+                }
         }
 
         txn.commit();