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

Skip to content

Commit a7befda

Browse files
committed
Fixes SF bug # 778421
* Fixed a bug in the compatibility interface set_location() method where it would not properly search to the next nearest key when used on BTree databases. [SF bug id 788421] * Fixed a bug in the compatibility interface set_location() method where it could crash when looking up keys in a hash or recno format database due to an incorrect free().
1 parent 904de5b commit a7befda

4 files changed

Lines changed: 39 additions & 6 deletions

File tree

Lib/bsddb/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ def has_key(self, key):
244244
def set_location(self, key):
245245
self._checkOpen()
246246
self._checkCursor()
247-
return self.dbc.set(key)
247+
return self.dbc.set_range(key)
248248

249249
def next(self):
250250
self._checkOpen()

Lib/bsddb/test/test_basics.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -385,7 +385,12 @@ def test03_SimpleCursorStuff(self, get_raises_error=0, set_raises_error=0):
385385
rec = c.set_range('011',dlen=0,doff=0)
386386
if verbose:
387387
print "searched (partial) for '011', found: ", rec
388-
if rec[1] != '': set.fail('expected empty data portion')
388+
if rec[1] != '': self.fail('expected empty data portion')
389+
390+
ev = c.set_range('empty value')
391+
if verbose:
392+
print "search for 'empty value' returned", ev
393+
if ev[1] != '': self.fail('empty value lookup failed')
389394

390395
c.set('0499')
391396
c.delete()

Lib/bsddb/test/test_compat.py

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,10 @@ def test03_rnopen(self):
4949

5050
assert getTest[1] == 'quick', 'data mismatch!'
5151

52+
rv = f.set_location(3)
53+
if rv != (3, 'brown'):
54+
self.fail('recno database set_location failed: '+repr(rv))
55+
5256
f[25] = 'twenty-five'
5357
f.close()
5458
del f
@@ -83,7 +87,6 @@ def test04_n_flag(self):
8387
f.close()
8488

8589

86-
8790
def do_bthash_test(self, factory, what):
8891
if verbose:
8992
print '\nTesting: ', what
@@ -103,13 +106,16 @@ def do_bthash_test(self, factory, what):
103106
f['b'] = 'van'
104107
f['c'] = 'Rossum'
105108
f['d'] = 'invented'
109+
# 'e' intentionally left out
106110
f['f'] = 'Python'
107111
if verbose:
108112
print '%s %s %s' % (f['a'], f['b'], f['c'])
109113

110114
if verbose:
111115
print 'key ordering...'
112-
f.set_location(f.first()[0])
116+
start = f.set_location(f.first()[0])
117+
if start != ('0', ''):
118+
self.fail("incorrect first() result: "+repr(start))
113119
while 1:
114120
try:
115121
rec = f.next()
@@ -122,6 +128,20 @@ def do_bthash_test(self, factory, what):
122128

123129
assert f.has_key('f'), 'Error, missing key!'
124130

131+
# test that set_location() returns the next nearest key, value
132+
# on btree databases and raises KeyError on others.
133+
if factory == btopen:
134+
e = f.set_location('e')
135+
if e != ('f', 'Python'):
136+
self.fail('wrong key,value returned: '+repr(e))
137+
else:
138+
try:
139+
e = f.set_location('e')
140+
except KeyError:
141+
pass
142+
else:
143+
self.fail("set_location on non-existant key did not raise KeyError")
144+
125145
f.sync()
126146
f.close()
127147
# truth test

Modules/_bsddb.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@
9797
#error "eek! DBVER can't handle minor versions > 9"
9898
#endif
9999

100-
#define PY_BSDDB_VERSION "4.2.4"
100+
#define PY_BSDDB_VERSION "4.2.5"
101101
static char *rcs_id = "$Id$";
102102

103103

@@ -2940,7 +2940,15 @@ DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
29402940
data.data, data.size);
29412941
break;
29422942
}
2943-
FREE_DBT(key);
2943+
if (_DB_get_type(self->mydb) == DB_BTREE) {
2944+
/* the only time a malloced key is returned is when we
2945+
* call this on a BTree database because it performs
2946+
* partial matching and needs to return the real key.
2947+
* All others leave key untouched [where calling free()
2948+
* on it would often segfault].
2949+
*/
2950+
FREE_DBT(key);
2951+
}
29442952
FREE_DBT(data);
29452953
}
29462954

0 commit comments

Comments
 (0)