Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit c25fd3f

Browse files
committed
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.
1 parent 5ec186b commit c25fd3f

2 files changed

Lines changed: 57 additions & 5 deletions

File tree

Lib/bsddb/test/test_basics.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -604,6 +604,26 @@ def test07_TxnTruncate(self):
604604
assert num == 0, "truncate on empty DB returned nonzero (%s)" % `num`
605605
txn.commit()
606606

607+
#----------------------------------------
608+
609+
def test08_TxnLateUse(self):
610+
txn = self.env.txn_begin()
611+
txn.abort()
612+
try:
613+
txn.abort()
614+
except db.DBError, e:
615+
pass
616+
else:
617+
raise RuntimeError, "DBTxn.abort() called after DB_TXN no longer valid w/o an exception"
618+
619+
txn = self.env.txn_begin()
620+
txn.commit()
621+
try:
622+
txn.commit()
623+
except db.DBError, e:
624+
pass
625+
else:
626+
raise RuntimeError, "DBTxn.commit() called after DB_TXN no longer valid w/o an exception"
607627

608628

609629
class BTreeTransactionTestCase(BasicTransactionTestCase):

Modules/_bsddb.c

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@
8585
/* 40 = 4.0, 33 = 3.3; this will break if the second number is > 9 */
8686
#define DBVER (DB_VERSION_MAJOR * 10 + DB_VERSION_MINOR)
8787

88-
#define PY_BSDDB_VERSION "4.1.1"
88+
#define PY_BSDDB_VERSION "4.1.2"
8989
static char *rcs_id = "$Id$";
9090

9191

@@ -465,6 +465,7 @@ static int makeDBError(int err)
465465
}
466466

467467
if (errObj != NULL) {
468+
/* FIXME this needs proper bounds checking on errTxt */
468469
strcpy(errTxt, db_strerror(err));
469470
if (_db_errmsg[0]) {
470471
strcat(errTxt, " -- ");
@@ -3722,15 +3723,23 @@ static PyObject*
37223723
DBTxn_commit(DBTxnObject* self, PyObject* args)
37233724
{
37243725
int flags=0, err;
3726+
DB_TXN *txn;
37253727

37263728
if (!PyArg_ParseTuple(args, "|i:commit", &flags))
37273729
return NULL;
37283730

3731+
if (!self->txn) {
3732+
PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
3733+
"DBTxn must not be used after txn_commit or txn_abort"));
3734+
return NULL;
3735+
}
3736+
txn = self->txn;
3737+
self->txn = NULL; /* this DB_TXN is no longer valid after this call */
37293738
MYDB_BEGIN_ALLOW_THREADS;
37303739
#if (DBVER >= 40)
3731-
err = self->txn->commit(self->txn, flags);
3740+
err = txn->commit(txn, flags);
37323741
#else
3733-
err = txn_commit(self->txn, flags);
3742+
err = txn_commit(txn, flags);
37343743
#endif
37353744
MYDB_END_ALLOW_THREADS;
37363745
RETURN_IF_ERR();
@@ -3754,6 +3763,11 @@ DBTxn_prepare(DBTxnObject* self, PyObject* args)
37543763
return NULL;
37553764
}
37563765

3766+
if (!self->txn) {
3767+
PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
3768+
"DBTxn must not be used after txn_commit or txn_abort"));
3769+
return NULL;
3770+
}
37573771
MYDB_BEGIN_ALLOW_THREADS;
37583772
#if (DBVER >= 40)
37593773
err = self->txn->prepare(self->txn, (u_int8_t*)gid);
@@ -3769,6 +3783,11 @@ DBTxn_prepare(DBTxnObject* self, PyObject* args)
37693783
if (!PyArg_ParseTuple(args, ":prepare"))
37703784
return NULL;
37713785

3786+
if (!self->txn) {
3787+
PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
3788+
"DBTxn must not be used after txn_commit or txn_abort"));
3789+
return NULL;
3790+
}
37723791
MYDB_BEGIN_ALLOW_THREADS;
37733792
err = txn_prepare(self->txn);
37743793
MYDB_END_ALLOW_THREADS;
@@ -3782,15 +3801,23 @@ static PyObject*
37823801
DBTxn_abort(DBTxnObject* self, PyObject* args)
37833802
{
37843803
int err;
3804+
DB_TXN *txn;
37853805

37863806
if (!PyArg_ParseTuple(args, ":abort"))
37873807
return NULL;
37883808

3809+
if (!self->txn) {
3810+
PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
3811+
"DBTxn must not be used after txn_commit or txn_abort"));
3812+
return NULL;
3813+
}
3814+
txn = self->txn;
3815+
self->txn = NULL; /* this DB_TXN is no longer valid after this call */
37893816
MYDB_BEGIN_ALLOW_THREADS;
37903817
#if (DBVER >= 40)
3791-
err = self->txn->abort(self->txn);
3818+
err = txn->abort(txn);
37923819
#else
3793-
err = txn_abort(self->txn);
3820+
err = txn_abort(txn);
37943821
#endif
37953822
MYDB_END_ALLOW_THREADS;
37963823
RETURN_IF_ERR();
@@ -3806,6 +3833,11 @@ DBTxn_id(DBTxnObject* self, PyObject* args)
38063833
if (!PyArg_ParseTuple(args, ":id"))
38073834
return NULL;
38083835

3836+
if (!self->txn) {
3837+
PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
3838+
"DBTxn must not be used after txn_commit or txn_abort"));
3839+
return NULL;
3840+
}
38093841
MYDB_BEGIN_ALLOW_THREADS;
38103842
#if (DBVER >= 40)
38113843
id = self->txn->id(self->txn);

0 commit comments

Comments
 (0)