Commit f5046598 authored by Gregory P. Smith's avatar Gregory P. Smith

bugfix: disallow use of DB_TXN after commit() or abort(), prevents a

        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.
parent 90bf6dc4
......@@ -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):
......
......@@ -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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment