mirror of
https://github.com/python/cpython.git
synced 2025-07-23 11:15:24 +00:00
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.
This commit is contained in:
parent
5ec186b1cb
commit
c25fd3fb48
2 changed files with 57 additions and 5 deletions
|
@ -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);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue