mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 13:41: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 @@ def test07_TxnTruncate(self): | ||||||
|         assert num == 0, "truncate on empty DB returned nonzero (%s)" % `num` |         assert num == 0, "truncate on empty DB returned nonzero (%s)" % `num` | ||||||
|         txn.commit() |         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): | class BTreeTransactionTestCase(BasicTransactionTestCase): | ||||||
|  |  | ||||||
|  | @ -85,7 +85,7 @@ | ||||||
| /* 40 = 4.0, 33 = 3.3; this will break if the second number is > 9 */ | /* 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 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$"; | static char *rcs_id = "$Id$"; | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -465,6 +465,7 @@ static int makeDBError(int err) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (errObj != NULL) { |     if (errObj != NULL) { | ||||||
|  |         /* FIXME this needs proper bounds checking on errTxt */ | ||||||
|         strcpy(errTxt, db_strerror(err)); |         strcpy(errTxt, db_strerror(err)); | ||||||
|         if (_db_errmsg[0]) { |         if (_db_errmsg[0]) { | ||||||
|             strcat(errTxt, " -- "); |             strcat(errTxt, " -- "); | ||||||
|  | @ -3722,15 +3723,23 @@ static PyObject* | ||||||
| DBTxn_commit(DBTxnObject* self, PyObject* args) | DBTxn_commit(DBTxnObject* self, PyObject* args) | ||||||
| { | { | ||||||
|     int flags=0, err; |     int flags=0, err; | ||||||
|  |     DB_TXN *txn; | ||||||
| 
 | 
 | ||||||
|     if (!PyArg_ParseTuple(args, "|i:commit", &flags)) |     if (!PyArg_ParseTuple(args, "|i:commit", &flags)) | ||||||
|         return NULL; |         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; |     MYDB_BEGIN_ALLOW_THREADS; | ||||||
| #if (DBVER >= 40) | #if (DBVER >= 40) | ||||||
|     err = self->txn->commit(self->txn, flags); |     err = txn->commit(txn, flags); | ||||||
| #else | #else | ||||||
|     err = txn_commit(self->txn, flags); |     err = txn_commit(txn, flags); | ||||||
| #endif | #endif | ||||||
|     MYDB_END_ALLOW_THREADS; |     MYDB_END_ALLOW_THREADS; | ||||||
|     RETURN_IF_ERR(); |     RETURN_IF_ERR(); | ||||||
|  | @ -3754,6 +3763,11 @@ DBTxn_prepare(DBTxnObject* self, PyObject* args) | ||||||
|         return NULL; |         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; |     MYDB_BEGIN_ALLOW_THREADS; | ||||||
| #if (DBVER >= 40) | #if (DBVER >= 40) | ||||||
|     err = self->txn->prepare(self->txn, (u_int8_t*)gid); |     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")) |     if (!PyArg_ParseTuple(args, ":prepare")) | ||||||
|         return NULL; |         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; |     MYDB_BEGIN_ALLOW_THREADS; | ||||||
|     err = txn_prepare(self->txn); |     err = txn_prepare(self->txn); | ||||||
|     MYDB_END_ALLOW_THREADS; |     MYDB_END_ALLOW_THREADS; | ||||||
|  | @ -3782,15 +3801,23 @@ static PyObject* | ||||||
| DBTxn_abort(DBTxnObject* self, PyObject* args) | DBTxn_abort(DBTxnObject* self, PyObject* args) | ||||||
| { | { | ||||||
|     int err; |     int err; | ||||||
|  |     DB_TXN *txn; | ||||||
| 
 | 
 | ||||||
|     if (!PyArg_ParseTuple(args, ":abort")) |     if (!PyArg_ParseTuple(args, ":abort")) | ||||||
|         return NULL; |         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; |     MYDB_BEGIN_ALLOW_THREADS; | ||||||
| #if (DBVER >= 40) | #if (DBVER >= 40) | ||||||
|     err = self->txn->abort(self->txn); |     err = txn->abort(txn); | ||||||
| #else | #else | ||||||
|     err = txn_abort(self->txn); |     err = txn_abort(txn); | ||||||
| #endif | #endif | ||||||
|     MYDB_END_ALLOW_THREADS; |     MYDB_END_ALLOW_THREADS; | ||||||
|     RETURN_IF_ERR(); |     RETURN_IF_ERR(); | ||||||
|  | @ -3806,6 +3833,11 @@ DBTxn_id(DBTxnObject* self, PyObject* args) | ||||||
|     if (!PyArg_ParseTuple(args, ":id")) |     if (!PyArg_ParseTuple(args, ":id")) | ||||||
|         return NULL; |         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; |     MYDB_BEGIN_ALLOW_THREADS; | ||||||
| #if (DBVER >= 40) | #if (DBVER >= 40) | ||||||
|     id = self->txn->id(self->txn); |     id = self->txn->id(self->txn); | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Gregory P. Smith
						Gregory P. Smith