[Python-checkins] python/dist/src/Modules _bsddb.c, 1.17.6.7, 1.17.6.8

greg at users.sourceforge.net greg at users.sourceforge.net
Mon Dec 20 00:59:54 CET 2004


Update of /cvsroot/python/python/dist/src/Modules
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv24117/Modules

Modified Files:
      Tag: release23-maint
	_bsddb.c 
Log Message:
* closes SF bug/patch 967763
  - fixes various memory leaks found by valgrind and a follup closer
    code inspection of the bsddb module.  (merges r1.32 of _bsddb.c
    and an associated test case)
  - also merges the one line r1.37 _bsddb.c fix that fixes a leak on
    the rare DBEnv creation failed error path.


Index: _bsddb.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Modules/_bsddb.c,v
retrieving revision 1.17.6.7
retrieving revision 1.17.6.8
diff -u -d -r1.17.6.7 -r1.17.6.8
--- _bsddb.c	19 Dec 2004 23:27:48 -0000	1.17.6.7
+++ _bsddb.c	19 Dec 2004 23:59:51 -0000	1.17.6.8
@@ -93,7 +93,7 @@
 /* 40 = 4.0, 33 = 3.3; this will break if the second number is > 9 */
 #define DBVER (DB_VERSION_MAJOR * 10 + DB_VERSION_MINOR)
 
-#define PY_BSDDB_VERSION "4.2.0.2"
+#define PY_BSDDB_VERSION "4.2.0.5"
 static char *rcs_id = "$Id$";
 
 
@@ -287,7 +287,7 @@
 #define CLEAR_DBT(dbt)              (memset(&(dbt), 0, sizeof(dbt)))
 
 #define FREE_DBT(dbt)               if ((dbt.flags & (DB_DBT_MALLOC|DB_DBT_REALLOC)) && \
-                                         dbt.data != NULL) { free(dbt.data); }
+                                         dbt.data != NULL) { free(dbt.data); dbt.data = NULL; }
 
 
 static int makeDBError(int err);
@@ -320,7 +320,7 @@
     }
     else if (!PyArg_Parse(obj, "s#", &dbt->data, &dbt->size)) {
         PyErr_SetString(PyExc_TypeError,
-                        "Key and Data values must be of type string or None.");
+                        "Data values must be of type string or None.");
         return 0;
     }
     return 1;
@@ -330,7 +330,7 @@
 /* Recno and Queue DBs can have integer keys.  This function figures out
    what's been given, verifies that it's allowed, and then makes the DBT.
 
-   Caller should call FREE_DBT(key) when done. */
+   Caller MUST call FREE_DBT(key) when done. */
 static int
 make_key_dbt(DBObject* self, PyObject* keyobj, DBT* key, int* pflags)
 {
@@ -830,7 +830,7 @@
 static void
 DBEnv_dealloc(DBEnvObject* self)
 {
-    if (!self->closed) {
+    if (self->db_env) {
         MYDB_BEGIN_ALLOW_THREADS;
         self->db_env->close(self->db_env, 0);
         MYDB_END_ALLOW_THREADS;
@@ -1269,11 +1269,15 @@
     CHECK_DB_NOT_CLOSED(self);
     if (!make_key_dbt(self, keyobj, &key, NULL))
         return NULL;
-    if (!checkTxnObj(txnobj, &txn))
+    if (!checkTxnObj(txnobj, &txn)) {
+        FREE_DBT(key);
         return NULL;
+    }
 
-    if (-1 == _DB_delete(self, txn, &key, 0))
+    if (-1 == _DB_delete(self, txn, &key, 0)) {
+        FREE_DBT(key);
         return NULL;
+    }
 
     FREE_DBT(key);
     RETURN_NONE();
@@ -1319,16 +1323,20 @@
     CHECK_DB_NOT_CLOSED(self);
     if (!make_key_dbt(self, keyobj, &key, &flags))
         return NULL;
-    if (!checkTxnObj(txnobj, &txn))
+    if (!checkTxnObj(txnobj, &txn)) {
+        FREE_DBT(key);
         return NULL;
+    }
 
     CLEAR_DBT(data);
     if (CHECK_DBFLAG(self, DB_THREAD)) {
         /* Tell BerkeleyDB to malloc the return value (thread safe) */
         data.flags = DB_DBT_MALLOC;
     }
-    if (!add_partial_dbt(&data, dlen, doff))
+    if (!add_partial_dbt(&data, dlen, doff)) {
+        FREE_DBT(key);
         return NULL;
+    }
 
     MYDB_BEGIN_ALLOW_THREADS;
     err = self->db->get(self->db, txn, &key, &data, flags);
@@ -1350,9 +1358,9 @@
                                    data.size);
         else /* return just the data */
             retval = PyString_FromStringAndSize((char*)data.data, data.size);
-        FREE_DBT(key);
         FREE_DBT(data);
     }
+    FREE_DBT(key);
 
     RETURN_IF_ERR();
     return retval;
@@ -1377,8 +1385,10 @@
     CHECK_DB_NOT_CLOSED(self);
     if (!make_key_dbt(self, keyobj, &key, &flags))
         return NULL;
-    if (!checkTxnObj(txnobj, &txn))
+    if (!checkTxnObj(txnobj, &txn)) {
+        FREE_DBT(key);
         return NULL;
+    }
     CLEAR_DBT(data);
 
     /* We don't allocate any memory, forcing a ENOMEM error and thus
@@ -1420,10 +1430,12 @@
     CHECK_DB_NOT_CLOSED(self);
     if (!make_key_dbt(self, keyobj, &key, NULL))
         return NULL;
-    if (!make_dbt(dataobj, &data))
-        return NULL;
-    if (!checkTxnObj(txnobj, &txn))
+    if ( !make_dbt(dataobj, &data) ||
+         !checkTxnObj(txnobj, &txn) )
+    {
+        FREE_DBT(key);
         return NULL;
+    }
 
     flags |= DB_GET_BOTH;
 
@@ -1690,10 +1702,15 @@
         return NULL;
 
     CHECK_DB_NOT_CLOSED(self);
-    if (!make_key_dbt(self, keyobj, &key, NULL)) return NULL;
-    if (!make_dbt(dataobj, &data)) return NULL;
-    if (!add_partial_dbt(&data, dlen, doff)) return NULL;
-    if (!checkTxnObj(txnobj, &txn)) return NULL;
+    if (!make_key_dbt(self, keyobj, &key, NULL))
+        return NULL;
+    if ( !make_dbt(dataobj, &data) ||
+         !add_partial_dbt(&data, dlen, doff) ||
+         !checkTxnObj(txnobj, &txn) )
+    {
+        FREE_DBT(key);
+        return NULL;
+    }
 
     if (-1 == _DB_put(self, txn, &key, &data, flags)) {
         FREE_DBT(key);
@@ -2361,8 +2378,10 @@
     CHECK_DB_NOT_CLOSED(self);
     if (!make_key_dbt(self, keyobj, &key, NULL))
         return NULL;
-    if (!checkTxnObj(txnobj, &txn))
+    if (!checkTxnObj(txnobj, &txn)) {
+        FREE_DBT(key);
         return NULL;
+    }
 
     /* This causes ENOMEM to be returned when the db has the key because
        it has a record but can't allocate a buffer for the data.  This saves
@@ -2663,21 +2682,24 @@
 
     if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
         return NULL;
-    if (dataobj && !make_dbt(dataobj, &data))
-        return NULL;
-    if (!add_partial_dbt(&data, dlen, doff))
+    if ( (dataobj && !make_dbt(dataobj, &data)) ||
+         (!add_partial_dbt(&data, dlen, doff)) )
+    {
+        FREE_DBT(key);
         return NULL;
+    }
 
     if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
         data.flags = DB_DBT_MALLOC;
-        key.flags = DB_DBT_MALLOC;
+        if (!(key.flags & DB_DBT_REALLOC)) {
+            key.flags |= DB_DBT_MALLOC;
+        }
     }
 
     MYDB_BEGIN_ALLOW_THREADS;
     err = self->dbc->c_get(self->dbc, &key, &data, flags);
     MYDB_END_ALLOW_THREADS;
 
-
     if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.getReturnsNone) {
         Py_INCREF(Py_None);
         retval = Py_None;
@@ -2702,9 +2724,9 @@
                                    data.data, data.size);
             break;
         }
-        FREE_DBT(key);
         FREE_DBT(data);
     }
+    FREE_DBT(key);
     return retval;
 }
 
@@ -2781,9 +2803,12 @@
 
     if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
         return NULL;
-    if (!make_dbt(dataobj, &data))
+    if (!make_dbt(dataobj, &data) ||
+        !add_partial_dbt(&data, dlen, doff) )
+    {
+        FREE_DBT(key);
         return NULL;
-    if (!add_partial_dbt(&data, dlen, doff)) return NULL;
+    }
 
     MYDB_BEGIN_ALLOW_THREADS;
     err = self->dbc->c_put(self->dbc, &key, &data, flags);
@@ -2819,8 +2844,10 @@
         /* Tell BerkeleyDB to malloc the return value (thread safe) */
         data.flags = DB_DBT_MALLOC;
     }
-    if (!add_partial_dbt(&data, dlen, doff))
+    if (!add_partial_dbt(&data, dlen, doff)) {
+        FREE_DBT(key);
         return NULL;
+    }
 
     MYDB_BEGIN_ALLOW_THREADS;
     err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET);
@@ -2849,9 +2876,9 @@
                                    data.data, data.size);
             break;
         }
-        FREE_DBT(key);
         FREE_DBT(data);
     }
+    FREE_DBT(key);
 
     return retval;
 }
@@ -2877,13 +2904,18 @@
         return NULL;
 
     CLEAR_DBT(data);
+    if (!add_partial_dbt(&data, dlen, doff)) {
+        FREE_DBT(key);
+        return NULL;
+    }
     if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
         /* Tell BerkeleyDB to malloc the return value (thread safe) */
-        data.flags = DB_DBT_MALLOC;
-        key.flags = DB_DBT_MALLOC;
+        data.flags |= DB_DBT_MALLOC;
+        /* only BTREE databases will return anything in the key */
+        if (!(key.flags & DB_DBT_REALLOC) && _DB_get_type(self->mydb) == DB_BTREE) {
+            key.flags |= DB_DBT_MALLOC;
+        }
     }
-    if (!add_partial_dbt(&data, dlen, doff))
-        return NULL;
     MYDB_BEGIN_ALLOW_THREADS;
     err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
     MYDB_END_ALLOW_THREADS;
@@ -2911,17 +2943,14 @@
                                    data.data, data.size);
             break;
         }
-        if (_DB_get_type(self->mydb) == DB_BTREE) {
-            /* the only time a malloced key is returned is when we
-             * call this on a BTree database because it performs
-             * partial matching and needs to return the real key.
-             * All others leave key untouched [where calling free()
-             * on it would often segfault].
-             */
-            FREE_DBT(key);
-        }
+        FREE_DBT(key);
         FREE_DBT(data);
     }
+    /* the only time REALLOC should be set is if we used an integer
+     * key that make_dbt_key malloc'd for us.  always free these. */
+    if (key.flags & DB_DBT_REALLOC) {
+        FREE_DBT(key);
+    }
 
     return retval;
 }
@@ -2937,8 +2966,10 @@
     /* the caller did this:  CHECK_CURSOR_NOT_CLOSED(self); */
     if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
         return NULL;
-    if (!make_dbt(dataobj, &data))
+    if (!make_dbt(dataobj, &data)) {
+        FREE_DBT(key);
         return NULL;
+    }
 
     MYDB_BEGIN_ALLOW_THREADS;
     err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
@@ -3042,8 +3073,10 @@
         /* Tell BerkeleyDB to malloc the return value (thread safe) */
         data.flags = DB_DBT_MALLOC;
     }
-    if (!add_partial_dbt(&data, dlen, doff))
+    if (!add_partial_dbt(&data, dlen, doff)) {
+        FREE_DBT(key);
         return NULL;
+    }
 
     MYDB_BEGIN_ALLOW_THREADS;
     err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
@@ -3058,9 +3091,9 @@
     else {  /* Can only be used for BTrees, so no need to return int key */
         retval = Py_BuildValue("s#s#", key.data, key.size,
                                data.data, data.size);
-        FREE_DBT(key);
         FREE_DBT(data);
     }
+    FREE_DBT(key);
 
     return retval;
 }



More information about the Python-checkins mailing list