Skip to content

Commit 1b27ec6

Browse files
[3.6] bpo-33383: Fix crash in get() of the dbm.ndbm database object. (GH-6630). (GH-6633)
(cherry picked from commit 2e38cc3)
1 parent 4533494 commit 1b27ec6

File tree

7 files changed

+38
-7
lines changed

7 files changed

+38
-7
lines changed

Lib/test/test_dbm.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,12 +86,21 @@ def test_anydbm_modification(self):
8686
f = dbm.open(_fname, 'c')
8787
self._dict['g'] = f[b'g'] = b"indented"
8888
self.read_helper(f)
89+
# setdefault() works as in the dict interface
90+
self.assertEqual(f.setdefault(b'xxx', b'foo'), b'foo')
91+
self.assertEqual(f[b'xxx'], b'foo')
8992
f.close()
9093

9194
def test_anydbm_read(self):
9295
self.init_db()
9396
f = dbm.open(_fname, 'r')
9497
self.read_helper(f)
98+
# get() works as in the dict interface
99+
self.assertEqual(f.get(b'a'), self._dict['a'])
100+
self.assertEqual(f.get(b'xxx', b'foo'), b'foo')
101+
self.assertIsNone(f.get(b'xxx'))
102+
with self.assertRaises(KeyError):
103+
f[b'xxx']
95104
f.close()
96105

97106
def test_anydbm_keys(self):

Lib/test/test_dbm_dumb.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,9 @@ def test_dumbdbm_modification(self):
7474
f = dumbdbm.open(_fname, 'w')
7575
self._dict[b'g'] = f[b'g'] = b"indented"
7676
self.read_helper(f)
77+
# setdefault() works as in the dict interface
78+
self.assertEqual(f.setdefault(b'xxx', b'foo'), b'foo')
79+
self.assertEqual(f[b'xxx'], b'foo')
7780
f.close()
7881

7982
def test_dumbdbm_read(self):
@@ -86,6 +89,12 @@ def test_dumbdbm_read(self):
8689
with self.assertWarnsRegex(DeprecationWarning,
8790
'The database is opened for reading only'):
8891
del f[b'a']
92+
# get() works as in the dict interface
93+
self.assertEqual(f.get(b'b'), self._dict[b'b'])
94+
self.assertEqual(f.get(b'xxx', b'foo'), b'foo')
95+
self.assertIsNone(f.get(b'xxx'))
96+
with self.assertRaises(KeyError):
97+
f[b'xxx']
8998
f.close()
9099

91100
def test_dumbdbm_keys(self):

Lib/test/test_dbm_gnu.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,12 @@ def test_key_methods(self):
3232
self.assertIn(key, key_set)
3333
key_set.remove(key)
3434
key = self.g.nextkey(key)
35-
self.assertRaises(KeyError, lambda: self.g['xxx'])
3635
# get() and setdefault() work as in the dict interface
36+
self.assertEqual(self.g.get(b'a'), b'b')
37+
self.assertIsNone(self.g.get(b'xxx'))
3738
self.assertEqual(self.g.get(b'xxx', b'foo'), b'foo')
39+
with self.assertRaises(KeyError):
40+
self.g['xxx']
3841
self.assertEqual(self.g.setdefault(b'xxx', b'foo'), b'foo')
3942
self.assertEqual(self.g[b'xxx'], b'foo')
4043

Lib/test/test_dbm_ndbm.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,22 @@ def tearDown(self):
1818

1919
def test_keys(self):
2020
self.d = dbm.ndbm.open(self.filename, 'c')
21-
self.assertTrue(self.d.keys() == [])
21+
self.assertEqual(self.d.keys(), [])
2222
self.d['a'] = 'b'
2323
self.d[b'bytes'] = b'data'
2424
self.d['12345678910'] = '019237410982340912840198242'
2525
self.d.keys()
2626
self.assertIn('a', self.d)
2727
self.assertIn(b'a', self.d)
2828
self.assertEqual(self.d[b'bytes'], b'data')
29+
# get() and setdefault() work as in the dict interface
30+
self.assertEqual(self.d.get(b'a'), b'b')
31+
self.assertIsNone(self.d.get(b'xxx'))
32+
self.assertEqual(self.d.get(b'xxx', b'foo'), b'foo')
33+
with self.assertRaises(KeyError):
34+
self.d['xxx']
35+
self.assertEqual(self.d.setdefault(b'xxx', b'foo'), b'foo')
36+
self.assertEqual(self.d[b'xxx'], b'foo')
2937
self.d.close()
3038

3139
def test_modes(self):
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fixed crash in the get() method of the :mod:`dbm.ndbm` database object when
2+
it is called with a single argument.

Modules/_dbmmodule.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,7 @@ static PySequenceMethods dbm_as_sequence = {
275275
_dbm.dbm.get
276276
277277
key: str(accept={str, robuffer}, zeroes=True)
278-
default: object(c_default="NULL") = b''
278+
default: object = None
279279
/
280280
281281
Return the value for key if present, otherwise default.
@@ -284,7 +284,7 @@ Return the value for key if present, otherwise default.
284284
static PyObject *
285285
_dbm_dbm_get_impl(dbmobject *self, const char *key,
286286
Py_ssize_clean_t key_length, PyObject *default_value)
287-
/*[clinic end generated code: output=b44f95eba8203d93 input=a3a279957f85eb6d]*/
287+
/*[clinic end generated code: output=b44f95eba8203d93 input=b788eba0ffad2e91]*/
288288
/*[clinic end generated code: output=4f5c0e523eaf1251 input=9402c0af8582dc69]*/
289289
{
290290
datum dbm_key, val;

Modules/clinic/_dbmmodule.c.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ _dbm_dbm_keys(dbmobject *self, PyObject *Py_UNUSED(ignored))
3939
}
4040

4141
PyDoc_STRVAR(_dbm_dbm_get__doc__,
42-
"get($self, key, default=b\'\', /)\n"
42+
"get($self, key, default=None, /)\n"
4343
"--\n"
4444
"\n"
4545
"Return the value for key if present, otherwise default.");
@@ -57,7 +57,7 @@ _dbm_dbm_get(dbmobject *self, PyObject *args)
5757
PyObject *return_value = NULL;
5858
const char *key;
5959
Py_ssize_clean_t key_length;
60-
PyObject *default_value = NULL;
60+
PyObject *default_value = Py_None;
6161

6262
if (!PyArg_ParseTuple(args, "s#|O:get",
6363
&key, &key_length, &default_value)) {
@@ -141,4 +141,4 @@ dbmopen(PyObject *module, PyObject *args)
141141
exit:
142142
return return_value;
143143
}
144-
/*[clinic end generated code: output=001fabffcecb99f1 input=a9049054013a1b77]*/
144+
/*[clinic end generated code: output=919cc4337be4a5d3 input=a9049054013a1b77]*/

0 commit comments

Comments
 (0)