]> granicus.if.org Git - python/commitdiff
bugfix: disallow use of DB_TXN after commit() or abort(), prevents a
authorGregory P. Smith <greg@mad-scientist.com>
Fri, 17 Jan 2003 07:52:59 +0000 (07:52 +0000)
committerGregory P. Smith <greg@mad-scientist.com>
Fri, 17 Jan 2003 07:52:59 +0000 (07:52 +0000)
        coredump or segmentation violation.

Sourceforge patch ID 664896:
http://sourceforge.net/tracker/index.php?func=detail&aid=664896&group_id=13900&atid=313900

The bug was reported on the pybsddb-users mailing list.

Lib/bsddb/test/test_basics.py
Modules/_bsddb.c

index 37f4d11bc4e3e5d59587a07111ebbf1f4be0c0f2..7524b35eaf6a1ad34b78de98a528707cd199f1b5 100644 (file)
@@ -604,6 +604,26 @@ class BasicTransactionTestCase(BasicTestCase):
         assert num == 0, "truncate on empty DB returned nonzero (%s)" % `num`
         txn.commit()
 
+    #----------------------------------------
+
+    def test08_TxnLateUse(self):
+        txn = self.env.txn_begin()
+        txn.abort()
+        try:
+            txn.abort()
+        except db.DBError, e:
+            pass
+        else:
+            raise RuntimeError, "DBTxn.abort() called after DB_TXN no longer valid w/o an exception"
+
+        txn = self.env.txn_begin()
+        txn.commit()
+        try:
+            txn.commit()
+        except db.DBError, e:
+            pass
+        else:
+            raise RuntimeError, "DBTxn.commit() called after DB_TXN no longer valid w/o an exception"
 
 
 class BTreeTransactionTestCase(BasicTransactionTestCase):
index 9bb339cab1c5f47c34744b4d39c216406fd68e00..8b93af387cd51c3fc416e61b64e81df80a33551f 100644 (file)
@@ -85,7 +85,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.1.1"
+#define PY_BSDDB_VERSION "4.1.2"
 static char *rcs_id = "$Id$";
 
 
@@ -465,6 +465,7 @@ static int makeDBError(int err)
     }
 
     if (errObj != NULL) {
+        /* FIXME this needs proper bounds checking on errTxt */
         strcpy(errTxt, db_strerror(err));
         if (_db_errmsg[0]) {
             strcat(errTxt, " -- ");
@@ -3722,15 +3723,23 @@ static PyObject*
 DBTxn_commit(DBTxnObject* self, PyObject* args)
 {
     int flags=0, err;
+    DB_TXN *txn;
 
     if (!PyArg_ParseTuple(args, "|i:commit", &flags))
         return NULL;
 
+    if (!self->txn) {
+        PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
+            "DBTxn must not be used after txn_commit or txn_abort"));
+        return NULL;
+    }
+    txn = self->txn;
+    self->txn = NULL;   /* this DB_TXN is no longer valid after this call */
     MYDB_BEGIN_ALLOW_THREADS;
 #if (DBVER >= 40)
-    err = self->txn->commit(self->txn, flags);
+    err = txn->commit(txn, flags);
 #else
-    err = txn_commit(self->txn, flags);
+    err = txn_commit(txn, flags);
 #endif
     MYDB_END_ALLOW_THREADS;
     RETURN_IF_ERR();
@@ -3754,6 +3763,11 @@ DBTxn_prepare(DBTxnObject* self, PyObject* args)
         return NULL;
     }
 
+    if (!self->txn) {
+        PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
+            "DBTxn must not be used after txn_commit or txn_abort"));
+        return NULL;
+    }
     MYDB_BEGIN_ALLOW_THREADS;
 #if (DBVER >= 40)
     err = self->txn->prepare(self->txn, (u_int8_t*)gid);
@@ -3769,6 +3783,11 @@ DBTxn_prepare(DBTxnObject* self, PyObject* args)
     if (!PyArg_ParseTuple(args, ":prepare"))
         return NULL;
 
+    if (!self->txn) {
+        PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
+            "DBTxn must not be used after txn_commit or txn_abort"));
+        return NULL;
+    }
     MYDB_BEGIN_ALLOW_THREADS;
     err = txn_prepare(self->txn);
     MYDB_END_ALLOW_THREADS;
@@ -3782,15 +3801,23 @@ static PyObject*
 DBTxn_abort(DBTxnObject* self, PyObject* args)
 {
     int err;
+    DB_TXN *txn;
 
     if (!PyArg_ParseTuple(args, ":abort"))
         return NULL;
 
+    if (!self->txn) {
+        PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
+            "DBTxn must not be used after txn_commit or txn_abort"));
+        return NULL;
+    }
+    txn = self->txn;
+    self->txn = NULL;   /* this DB_TXN is no longer valid after this call */
     MYDB_BEGIN_ALLOW_THREADS;
 #if (DBVER >= 40)
-    err = self->txn->abort(self->txn);
+    err = txn->abort(txn);
 #else
-    err = txn_abort(self->txn);
+    err = txn_abort(txn);
 #endif
     MYDB_END_ALLOW_THREADS;
     RETURN_IF_ERR();
@@ -3806,6 +3833,11 @@ DBTxn_id(DBTxnObject* self, PyObject* args)
     if (!PyArg_ParseTuple(args, ":id"))
         return NULL;
 
+    if (!self->txn) {
+        PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
+            "DBTxn must not be used after txn_commit or txn_abort"));
+        return NULL;
+    }
     MYDB_BEGIN_ALLOW_THREADS;
 #if (DBVER >= 40)
     id = self->txn->id(self->txn);