]> git.ipfire.org Git - thirdparty/openldap.git/commitdiff
Protect freelist at end of mdb_freelist_save()
authorHallvard Furuseth <hallvard@openldap.org>
Tue, 25 Jul 2017 19:27:36 +0000 (21:27 +0200)
committerHoward Chu <hyc@openldap.org>
Sat, 10 Oct 2020 11:57:59 +0000 (12:57 +0100)
libraries/liblmdb/mdb.c

index 05273a25ab976499b7c2d7af9539adb55d513b10..8229b1fdf93768ee110d3d5cfa3ffd4600276f0a 100644 (file)
@@ -3696,11 +3696,17 @@ mdb_freelist_save(MDB_txn *txn)
                mop_len = mop[0];
        }
 
-       /* Fill in the reserved me_pghead records */
+       /* Fill in the reserved me_pghead records.  Everything is finally
+        * in place, so this will not allocate or free any DB pages.
+        */
        rc = MDB_SUCCESS;
        if (mop_len) {
                MDB_val key, data;
 
+               /* Protect DB env from any (buggy) freelist use when saving mop */
+               env->me_pghead = NULL;
+               txn->mt_dirty_room = 0;
+
                mop += mop_len;
                rc = mdb_cursor_first(&mc, &key, &data);
                for (; !rc; rc = mdb_cursor_next(&mc, &key, &data, MDB_NEXT)) {
@@ -3714,14 +3720,17 @@ mdb_freelist_save(MDB_txn *txn)
                                len = mop_len;
                                data.mv_size = (len + 1) * sizeof(MDB_ID);
                        }
+                       mop_len -= len;
                        data.mv_data = mop -= len;
                        save = mop[0];
                        mop[0] = len;
                        rc = mdb_cursor_put(&mc, &key, &data, MDB_CURRENT);
                        mop[0] = save;
-                       if (rc || !(mop_len -= len))
+                       if (rc || !mop_len)
                                break;
                }
+
+               env->me_pghead = mop - mop_len;
        }
 
        /* Restore this so we can check vs. dirty_list after mdb_page_flush() */