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

Skip to content

Commit 568065e

Browse files
committed
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.
1 parent 48decfe commit 568065e

3 files changed

Lines changed: 53 additions & 21 deletions

File tree

Lib/bsddb/dbtables.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -362,12 +362,11 @@ def __new_rowid(self, table, txn) :
362362
unique = 0
363363
while not unique:
364364
# Generate a random 64-bit row ID string
365-
# (note: this code has <64 bits of randomness
365+
# (note: might have <64 bits of randomness
366366
# but it's plenty for our database id needs!)
367-
# We must ensure that no null bytes are in the id value.
368367
blist = []
369368
for x in range(_rowid_str_len):
370-
blist.append(random.randint(1,255))
369+
blist.append(random.randint(0,255))
371370
newid = bytes(blist)
372371

373372
# Guarantee uniqueness by adding this key to the database

Lib/bsddb/test/test_misc.py

Lines changed: 36 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
# For Pythons w/distutils pybsddb
1212
from bsddb3 import db, dbshelve, hashopen
1313
except ImportError:
14-
# For Python 2.3
14+
# For the bundled bsddb
1515
from bsddb import db, dbshelve, hashopen
1616

1717
#----------------------------------------------------------------------
@@ -28,10 +28,10 @@ def tearDown(self):
2828
pass
2929
shutil.rmtree(self.homeDir)
3030

31-
## def test01_badpointer(self):
32-
## dbs = dbshelve.open(self.filename)
33-
## dbs.close()
34-
## self.assertRaises(db.DBError, dbs.get, "foo")
31+
def test01_badpointer(self):
32+
dbs = dbshelve.open(self.filename)
33+
dbs.close()
34+
self.assertRaises(db.DBError, dbs.get, b"foo")
3535

3636
def test02_db_home(self):
3737
env = db.DBEnv()
@@ -53,18 +53,37 @@ def test03_repr_closed_db(self):
5353
# The problem was that make_key_dbt() was not allocating a copy of
5454
# string keys but FREE_DBT() was always being told to free it when the
5555
# database was opened with DB_THREAD.
56-
## def test04_double_free_make_key_dbt(self):
57-
## try:
58-
## db1 = db.DB()
59-
## db1.open(self.filename, None, db.DB_BTREE,
60-
## db.DB_CREATE | db.DB_THREAD)
61-
62-
## curs = db1.cursor()
63-
## t = curs.get(b"/foo", db.DB_SET)
64-
## # double free happened during exit from DBC_get
65-
## finally:
66-
## db1.close()
67-
## os.unlink(self.filename)
56+
def test04_double_free_make_key_dbt(self):
57+
try:
58+
db1 = db.DB()
59+
db1.open(self.filename, None, db.DB_BTREE,
60+
db.DB_CREATE | db.DB_THREAD)
61+
62+
curs = db1.cursor()
63+
t = curs.get(b"/foo", db.DB_SET)
64+
# double free happened during exit from DBC_get
65+
finally:
66+
db1.close()
67+
os.unlink(self.filename)
68+
69+
def test05_key_with_null_bytes(self):
70+
try:
71+
db1 = db.DB()
72+
db1.open(self.filename, None, db.DB_HASH, db.DB_CREATE)
73+
db1[b'a'] = b'eh?'
74+
db1[b'a\x00'] = b'eh zed.'
75+
db1[b'a\x00a'] = b'eh zed eh?'
76+
db1[b'aaa'] = b'eh eh eh!'
77+
keys = db1.keys()
78+
keys.sort()
79+
self.assertEqual([b'a', b'a\x00', b'a\x00a', b'aaa'], keys)
80+
self.assertEqual(db1[b'a'], b'eh?')
81+
self.assertEqual(db1[b'a\x00'], b'eh zed.')
82+
self.assertEqual(db1[b'a\x00a'], b'eh zed eh?')
83+
self.assertEqual(db1[b'aaa'], b'eh eh eh!')
84+
finally:
85+
db1.close()
86+
os.unlink(self.filename)
6887

6988

7089
#----------------------------------------------------------------------

Modules/_bsddb.c

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -439,8 +439,22 @@ make_key_dbt(DBObject* self, PyObject* keyobj, DBT* key, int* pflags,
439439
if ( !(view = _malloc_view(keyobj)) )
440440
return 0;
441441

442-
key->data = view->buf;
442+
/*
443+
* NOTE(gps): I don't like doing a data copy here, it seems
444+
* wasteful. But without a clean way to tell FREE_DBT if it
445+
* should free key->data or not we have to. Other places in
446+
* the code check for DB_THREAD and forceably set DBT_MALLOC
447+
* when we otherwise would leave flags 0 to indicate that.
448+
*/
443449
key->size = Py_SAFE_DOWNCAST(view->len, Py_ssize_t, u_int32_t);
450+
key->data = malloc(key->size);
451+
if (key->data == NULL) {
452+
PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
453+
key->size = 0;
454+
return 0;
455+
}
456+
memcpy(key->data, view->buf, key->size);
457+
key->flags = DB_DBT_REALLOC;
444458
*returned_view_p = view;
445459
}
446460

0 commit comments

Comments
 (0)