mirror of
				https://github.com/python/cpython.git
				synced 2025-11-04 07:31:38 +00:00 
			
		
		
		
	Fixes issue1371 and reenables those tests.
Merge r58757 and r58758 from trunk. Undoes incorrect dbtables fix and errant strdup introduced as described below: r58757 | gregory.p.smith | 2007-11-01 14:08:14 -0700 (Thu, 01 Nov 2007) | 4 lines Fix bug introduced in revision 58385. Database keys could no longer have NULL bytes in them. Replace the errant strdup with a malloc+memcpy. Adds a unit test for the correct behavior. r58758 | gregory.p.smith | 2007-11-01 14:15:36 -0700 (Thu, 01 Nov 2007) | 3 lines Undo revision 58533 58534 fixes. Those were a workaround for a problem introduced by 58385.
This commit is contained in:
		
							parent
							
								
									48decfe740
								
							
						
					
					
						commit
						568065e9d1
					
				
					 3 changed files with 52 additions and 20 deletions
				
			
		| 
						 | 
				
			
			@ -362,12 +362,11 @@ def __new_rowid(self, table, txn) :
 | 
			
		|||
        unique = 0
 | 
			
		||||
        while not unique:
 | 
			
		||||
            # Generate a random 64-bit row ID string
 | 
			
		||||
            # (note: this code has <64 bits of randomness
 | 
			
		||||
            # (note: might have <64 bits of randomness
 | 
			
		||||
            # but it's plenty for our database id needs!)
 | 
			
		||||
            # We must ensure that no null bytes are in the id value.
 | 
			
		||||
            blist = []
 | 
			
		||||
            for x in range(_rowid_str_len):
 | 
			
		||||
                blist.append(random.randint(1,255))
 | 
			
		||||
                blist.append(random.randint(0,255))
 | 
			
		||||
            newid = bytes(blist)
 | 
			
		||||
 | 
			
		||||
            # Guarantee uniqueness by adding this key to the database
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,7 +11,7 @@
 | 
			
		|||
    # For Pythons w/distutils pybsddb
 | 
			
		||||
    from bsddb3 import db, dbshelve, hashopen
 | 
			
		||||
except ImportError:
 | 
			
		||||
    # For Python 2.3
 | 
			
		||||
    # For the bundled bsddb
 | 
			
		||||
    from bsddb import db, dbshelve, hashopen
 | 
			
		||||
 | 
			
		||||
#----------------------------------------------------------------------
 | 
			
		||||
| 
						 | 
				
			
			@ -28,10 +28,10 @@ def tearDown(self):
 | 
			
		|||
            pass
 | 
			
		||||
        shutil.rmtree(self.homeDir)
 | 
			
		||||
 | 
			
		||||
##     def test01_badpointer(self):
 | 
			
		||||
##         dbs = dbshelve.open(self.filename)
 | 
			
		||||
##         dbs.close()
 | 
			
		||||
##         self.assertRaises(db.DBError, dbs.get, "foo")
 | 
			
		||||
    def test01_badpointer(self):
 | 
			
		||||
        dbs = dbshelve.open(self.filename)
 | 
			
		||||
        dbs.close()
 | 
			
		||||
        self.assertRaises(db.DBError, dbs.get, b"foo")
 | 
			
		||||
 | 
			
		||||
    def test02_db_home(self):
 | 
			
		||||
        env = db.DBEnv()
 | 
			
		||||
| 
						 | 
				
			
			@ -53,18 +53,37 @@ def test03_repr_closed_db(self):
 | 
			
		|||
    # 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)
 | 
			
		||||
    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(b"/foo", db.DB_SET)
 | 
			
		||||
##             # double free happened during exit from DBC_get
 | 
			
		||||
##         finally:
 | 
			
		||||
##             db1.close()
 | 
			
		||||
##             os.unlink(self.filename)
 | 
			
		||||
            curs = db1.cursor()
 | 
			
		||||
            t = curs.get(b"/foo", db.DB_SET)
 | 
			
		||||
            # double free happened during exit from DBC_get
 | 
			
		||||
        finally:
 | 
			
		||||
            db1.close()
 | 
			
		||||
            os.unlink(self.filename)
 | 
			
		||||
 | 
			
		||||
    def test05_key_with_null_bytes(self):
 | 
			
		||||
        try:
 | 
			
		||||
            db1 = db.DB()
 | 
			
		||||
            db1.open(self.filename, None, db.DB_HASH, db.DB_CREATE)
 | 
			
		||||
            db1[b'a'] = b'eh?'
 | 
			
		||||
            db1[b'a\x00'] = b'eh zed.'
 | 
			
		||||
            db1[b'a\x00a'] = b'eh zed eh?'
 | 
			
		||||
            db1[b'aaa'] = b'eh eh eh!'
 | 
			
		||||
            keys = db1.keys()
 | 
			
		||||
            keys.sort()
 | 
			
		||||
            self.assertEqual([b'a', b'a\x00', b'a\x00a', b'aaa'], keys)
 | 
			
		||||
            self.assertEqual(db1[b'a'], b'eh?')
 | 
			
		||||
            self.assertEqual(db1[b'a\x00'], b'eh zed.')
 | 
			
		||||
            self.assertEqual(db1[b'a\x00a'], b'eh zed eh?')
 | 
			
		||||
            self.assertEqual(db1[b'aaa'], b'eh eh eh!')
 | 
			
		||||
        finally:
 | 
			
		||||
            db1.close()
 | 
			
		||||
            os.unlink(self.filename)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#----------------------------------------------------------------------
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -439,8 +439,22 @@ make_key_dbt(DBObject* self, PyObject* keyobj, DBT* key, int* pflags,
 | 
			
		|||
        if ( !(view = _malloc_view(keyobj)) )
 | 
			
		||||
            return 0;
 | 
			
		||||
 | 
			
		||||
        key->data = view->buf;
 | 
			
		||||
        /*
 | 
			
		||||
         * 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->size = Py_SAFE_DOWNCAST(view->len, Py_ssize_t, u_int32_t);
 | 
			
		||||
        key->data = malloc(key->size);
 | 
			
		||||
        if (key->data == NULL) {
 | 
			
		||||
            PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
 | 
			
		||||
            key->size = 0;
 | 
			
		||||
            return 0;
 | 
			
		||||
        }
 | 
			
		||||
        memcpy(key->data, view->buf, key->size);
 | 
			
		||||
        key->flags = DB_DBT_REALLOC;
 | 
			
		||||
        *returned_view_p = view;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue