diff --git a/Lib/bsddb/test/test_lock.py b/Lib/bsddb/test/test_lock.py index eee12a4128d..9b9ce7b4c91 100644 --- a/Lib/bsddb/test/test_lock.py +++ b/Lib/bsddb/test/test_lock.py @@ -97,11 +97,7 @@ class LockingTestCase(unittest.TestCase): for t in threads: t.join() - def _DISABLED_test03_lock_timeout(self): - # Disabled as this test crashes the python interpreter built in - # debug mode with: - # Fatal Python error: UNREF invalid object - # the error occurs as marked below. + def test03_lock_timeout(self): self.env.set_timeout(0, db.DB_SET_LOCK_TIMEOUT) self.env.set_timeout(0, db.DB_SET_TXN_TIMEOUT) self.env.set_timeout(123456, db.DB_SET_LOCK_TIMEOUT) @@ -128,8 +124,6 @@ class LockingTestCase(unittest.TestCase): self.assertNotEqual(anID, anID2) lock = self.env.lock_get(anID, "shared lock", db.DB_LOCK_WRITE) start_time=time.time() - # FIXME: I see the UNREF crash as the interpreter trys to exit - # from this call to lock_get. self.assertRaises(db.DBLockNotGrantedError, self.env.lock_get,anID2, "shared lock", db.DB_LOCK_READ) end_time=time.time() diff --git a/Misc/NEWS b/Misc/NEWS index f11293dc81c..954f2b6e9ce 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -36,6 +36,9 @@ Extension Modules - bsddb module updated to version 4.6.4. +- issue2858: Fix potential memory corruption when bsddb.db.DBEnv.lock_get + and other bsddb.db object constructors raised an exception. + - Fixed #2870: cmathmodule.c compile error Library diff --git a/Modules/_bsddb.c b/Modules/_bsddb.c index 04c7155ea1c..f5e95664302 100644 --- a/Modules/_bsddb.c +++ b/Modules/_bsddb.c @@ -903,7 +903,7 @@ newDBObject(DBEnvObject* arg, int flags) Py_DECREF(self->myenvobj); self->myenvobj = NULL; } - PyObject_Del(self); + Py_DECREF(self); self = NULL; } return self; @@ -1010,7 +1010,7 @@ newDBEnvObject(int flags) err = db_env_create(&self->db_env, flags); MYDB_END_ALLOW_THREADS; if (makeDBError(err)) { - PyObject_Del(self); + Py_DECREF(self); self = NULL; } else { @@ -1050,20 +1050,27 @@ static DBTxnObject* newDBTxnObject(DBEnvObject* myenv, DBTxnObject *parent, DB_TXN *txn, int flags) { int err; - DB_TXN *parent_txn=NULL; + DB_TXN *parent_txn = NULL; DBTxnObject* self = PyObject_New(DBTxnObject, &DBTxn_Type); if (self == NULL) return NULL; self->in_weakreflist = NULL; + self->children_txns = NULL; + self->children_dbs = NULL; + self->children_cursors = NULL; + self->children_sequences = NULL; + self->flag_prepare = 0; + self->parent_txn = NULL; + self->env = NULL; if (parent && ((PyObject *)parent!=Py_None)) { - parent_txn=parent->txn; + parent_txn = parent->txn; } if (txn) { - self->txn=txn; + self->txn = txn; } else { MYDB_BEGIN_ALLOW_THREADS; #if (DBVER >= 40) @@ -1074,29 +1081,24 @@ newDBTxnObject(DBEnvObject* myenv, DBTxnObject *parent, DB_TXN *txn, int flags) MYDB_END_ALLOW_THREADS; if (makeDBError(err)) { - PyObject_Del(self); + Py_DECREF(self); return NULL; } } - if (parent_txn) { /* Can't use 'parent' because could be 'parent==Py_None' */ - self->parent_txn=parent; + /* Can't use 'parent' because could be 'parent==Py_None' */ + if (parent_txn) { + self->parent_txn = parent; Py_INCREF(parent); self->env = NULL; - INSERT_IN_DOUBLE_LINKED_LIST(parent->children_txns,self); + INSERT_IN_DOUBLE_LINKED_LIST(parent->children_txns, self); } else { - self->parent_txn=NULL; + self->parent_txn = NULL; Py_INCREF(myenv); self->env = myenv; - INSERT_IN_DOUBLE_LINKED_LIST(myenv->children_txns,self); + INSERT_IN_DOUBLE_LINKED_LIST(myenv->children_txns, self); } - self->children_txns=NULL; - self->children_dbs=NULL; - self->children_cursors=NULL; - self->children_sequences=NULL; - self->flag_prepare=0; - return self; } @@ -1151,7 +1153,7 @@ newDBLockObject(DBEnvObject* myenv, u_int32_t locker, DBT* obj, #endif MYDB_END_ALLOW_THREADS; if (makeDBError(err)) { - PyObject_Del(self); + Py_DECREF(self); self = NULL; } @@ -1183,7 +1185,7 @@ newDBSequenceObject(DBObject* mydb, int flags) self->mydb = mydb; INSERT_IN_DOUBLE_LINKED_LIST(self->mydb->children_sequences,self); - self->txn=NULL; + self->txn = NULL; self->in_weakreflist = NULL; @@ -1191,8 +1193,7 @@ newDBSequenceObject(DBObject* mydb, int flags) err = db_sequence_create(&self->sequence, self->mydb->db, flags); MYDB_END_ALLOW_THREADS; if (makeDBError(err)) { - Py_DECREF(self->mydb); - PyObject_Del(self); + Py_DECREF(self); self = NULL; }