mirror of
				https://github.com/python/cpython.git
				synced 2025-11-03 23:21:29 +00:00 
			
		
		
		
	Fix a double free when positioning a database cursor to a non-existant
string key (and probably a few other situations with string keys). This was reported with a patch as pybsddb sourceforge bug 1708868 by jjjhhhlll at gmail.
This commit is contained in:
		
							parent
							
								
									392505391e
								
							
						
					
					
						commit
						10bed54ae2
					
				
					 2 changed files with 33 additions and 1 deletions
				
			
		| 
						 | 
					@ -53,6 +53,26 @@ def test03_repr_closed_db(self):
 | 
				
			||||||
        rp = repr(db)
 | 
					        rp = repr(db)
 | 
				
			||||||
        self.assertEquals(rp, "{}")
 | 
					        self.assertEquals(rp, "{}")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # http://sourceforge.net/tracker/index.php?func=detail&aid=1708868&group_id=13900&atid=313900
 | 
				
			||||||
 | 
					    #
 | 
				
			||||||
 | 
					    # See the bug report for details.
 | 
				
			||||||
 | 
					    #
 | 
				
			||||||
 | 
					    # The problem was that make_key_dbt() was not allocating a copy of
 | 
				
			||||||
 | 
					    # string keys but FREE_DBT() was always being told to free it when the
 | 
				
			||||||
 | 
					    # database was opened with DB_THREAD.
 | 
				
			||||||
 | 
					    def test04_double_free_make_key_dbt(self):
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            db1 = db.DB()
 | 
				
			||||||
 | 
					            db1.open(self.filename, None, db.DB_BTREE,
 | 
				
			||||||
 | 
					                     db.DB_CREATE | db.DB_THREAD)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            curs = db1.cursor()
 | 
				
			||||||
 | 
					            t = curs.get("/foo", db.DB_SET)
 | 
				
			||||||
 | 
					            # double free happened during exit from DBC_get
 | 
				
			||||||
 | 
					        finally:
 | 
				
			||||||
 | 
					            db1.close()
 | 
				
			||||||
 | 
					            os.unlink(self.filename)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#----------------------------------------------------------------------
 | 
					#----------------------------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -328,7 +328,19 @@ make_key_dbt(DBObject* self, PyObject* keyobj, DBT* key, int* pflags)
 | 
				
			||||||
            return 0;
 | 
					            return 0;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        key->data = PyString_AS_STRING(keyobj);
 | 
					        /*
 | 
				
			||||||
 | 
					         * NOTE(gps): I don't like doing a data copy here, it seems
 | 
				
			||||||
 | 
					         * wasteful.  But without a clean way to tell FREE_DBT if it
 | 
				
			||||||
 | 
					         * should free key->data or not we have to.  Other places in
 | 
				
			||||||
 | 
					         * the code check for DB_THREAD and forceably set DBT_MALLOC
 | 
				
			||||||
 | 
					         * when we otherwise would leave flags 0 to indicate that.
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
 | 
					        key->data = strdup(PyString_AS_STRING(keyobj));
 | 
				
			||||||
 | 
					        if (key->data == NULL) {
 | 
				
			||||||
 | 
					            PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
 | 
				
			||||||
 | 
					            return 0;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        key->flags = DB_DBT_REALLOC;
 | 
				
			||||||
        key->size = PyString_GET_SIZE(keyobj);
 | 
					        key->size = PyString_GET_SIZE(keyobj);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue