You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@apr.apache.org by jo...@apache.org on 2023/10/24 14:18:52 UTC

svn commit: r1913264 - /apr/apr/trunk/dbm/apr_dbm_lmdb.c

Author: jorton
Date: Tue Oct 24 14:18:52 2023
New Revision: 1913264

URL: http://svn.apache.org/viewvc?rev=1913264&view=rev
Log:
* dbm/apr_dbm_lmdb.c: Improve error handling throughout to avoid
  double-free on error paths.

Submitted by: Lubos Uhliarik <luhliari redhat.com>
Github: closes #49

Modified:
    apr/apr/trunk/dbm/apr_dbm_lmdb.c

Modified: apr/apr/trunk/dbm/apr_dbm_lmdb.c
URL: http://svn.apache.org/viewvc/apr/apr/trunk/dbm/apr_dbm_lmdb.c?rev=1913264&r1=1913263&r2=1913264&view=diff
==============================================================================
--- apr/apr/trunk/dbm/apr_dbm_lmdb.c (original)
+++ apr/apr/trunk/dbm/apr_dbm_lmdb.c Tue Oct 24 14:18:52 2023
@@ -115,30 +115,42 @@ static apr_status_t vt_lmdb_open(apr_dbm
         int dberr;
         file.txn = NULL;
         file.cursor = NULL;
+        file.env = NULL;
 
-        if ((dberr = mdb_env_create(&file.env)) == 0) {
-            /* Default to 2GB map size which limits the total database
-             * size to something reasonable. */
-            if ((dberr = mdb_env_set_mapsize(file.env, UINT32_MAX)) == 0) {
-                if ((dberr = mdb_env_open(file.env, pathname, dbmode | DEFAULT_ENV_FLAGS, apr_posix_perms2mode(perm))) == 0) {
-                    if ((dberr = mdb_txn_begin(file.env, NULL, dbmode, &file.txn)) == 0) {
-                        if ((dberr = mdb_dbi_open(file.txn, NULL, dbi_open_flags, &file.dbi)) != 0) {
-                            /* close the env handler */
-                            mdb_env_close(file.env);
-                        }
-                    }
+        dberr = mdb_env_create(&file.env);
+        if (dberr == 0) {
+            /*   Default to 2GB map size which limits the total database
+             *   size to something reasonable. */
+            dberr = mdb_env_set_mapsize(file.env, UINT32_MAX);
+        }
+
+        if (dberr == 0) {
+            dberr = mdb_env_open(file.env, pathname, dbmode | DEFAULT_ENV_FLAGS, apr_posix_perms2mode(perm));
+        }
+
+        if (dberr == 0) {
+            dberr = mdb_txn_begin(file.env, NULL, dbmode, &file.txn);
+        }
+
+        if (dberr == 0) {
+            dberr = mdb_dbi_open(file.txn, NULL, dbi_open_flags, &file.dbi);
+
+            /* if mode == APR_DBM_RWTRUNC, drop database */
+            if ((dberr == 0) && truncate) {
+                dberr = mdb_drop(file.txn, file.dbi, 0);
+                if (dberr != 0) {
+                    mdb_dbi_close(file.env, file.dbi);
                 }
             }
         }
 
-        if (truncate) {
-            if ((dberr = mdb_drop(file.txn, file.dbi, 0)) != 0) {
+        if (dberr != 0) {
+            /* close the env handler */
+            if (file.env) 
                 mdb_env_close(file.env);
-            }
-        }
 
-        if (dberr != 0)
             return db2s(dberr);
+        }
     }
 
     /* we have an open database... return it */
@@ -156,14 +168,16 @@ static void vt_lmdb_close(apr_dbm_t *dbm
 {
     real_file_t *f = dbm->file;
 
-    if (f->cursor) {
-        mdb_cursor_close(f->cursor);
-        f->cursor = NULL;
-    }
-
+    /* try to commit all transactions that haven't been commited yet on close */
     if (f->txn) {
        mdb_txn_commit(f->txn);
        f->txn = NULL;
+       f->cursor = NULL;
+    }
+
+    if (f->cursor) {
+        mdb_cursor_close(f->cursor);
+        f->cursor = NULL;
     }
 
     mdb_dbi_close(f->env, f->dbi);
@@ -216,9 +230,14 @@ static apr_status_t vt_lmdb_store(apr_db
 
     if ((rv = mdb_put(f->txn, f->dbi, &ckey, &cvalue, 0)) == 0) {
         /* commit transaction */
-        if (((rv = mdb_txn_commit(f->txn)) == MDB_SUCCESS)
-            && ((rv = mdb_txn_begin(f->env, NULL, 0, &f->txn)) == MDB_SUCCESS)) {
+        if ((rv = mdb_txn_commit(f->txn)) == MDB_SUCCESS) {
             f->cursor = NULL;
+            rv = mdb_txn_begin(f->env, NULL, 0, &f->txn);
+        }
+
+        /* if mdb_txn_commit OR mdb_txn_begin fails ... */
+        if (rv != MDB_SUCCESS) {
+            f->txn = NULL;
         }
     }
 
@@ -237,9 +256,14 @@ static apr_status_t vt_lmdb_del(apr_dbm_
 
     if ((rv = mdb_del(f->txn, f->dbi, &ckey, NULL)) == 0) {
         /* commit transaction */
-        if (((rv = mdb_txn_commit(f->txn)) == MDB_SUCCESS)
-            && ((rv = mdb_txn_begin(f->env, NULL, 0, &f->txn)) == MDB_SUCCESS)) {
+        if ((rv = mdb_txn_commit(f->txn)) == MDB_SUCCESS) {
             f->cursor = NULL;
+            rv = mdb_txn_begin(f->env, NULL, 0, &f->txn);
+        }
+
+        /* if mdb_txn_commit OR mdb_txn_begin fails ... */
+        if (rv != MDB_SUCCESS) {
+            f->txn = NULL;
         }
     }
 
@@ -281,6 +305,10 @@ static apr_status_t vt_lmdb_firstkey(apr
             dberr = 0;
         }
     }
+    else {
+        /* clear first if mdb_cursor_open fails */
+        memset(&first, 0, sizeof(first));
+    }
 
     pkey->dptr = first.mv_data;
     pkey->dsize = first.mv_size;