[Python-checkins] bpo-33383: Fix crash in get() of the dbm.ndbm database object. (#6630)

Serhiy Storchaka webhook-mailer at python.org
Sun Apr 29 05:38:13 EDT 2018


https://github.com/python/cpython/commit/2e38cc39330bd7f3003652869b644110a97a78d8
commit: 2e38cc39330bd7f3003652869b644110a97a78d8
branch: master
author: Serhiy Storchaka <storchaka at gmail.com>
committer: GitHub <noreply at github.com>
date: 2018-04-29T12:38:06+03:00
summary:

bpo-33383: Fix crash in get() of the dbm.ndbm database object. (#6630)

files:
A Misc/NEWS.d/next/Library/2018-04-29-11-15-38.bpo-33383.g32YWn.rst
M Lib/test/test_dbm.py
M Lib/test/test_dbm_dumb.py
M Lib/test/test_dbm_gnu.py
M Lib/test/test_dbm_ndbm.py
M Modules/_dbmmodule.c
M Modules/clinic/_dbmmodule.c.h

diff --git a/Lib/test/test_dbm.py b/Lib/test/test_dbm.py
index f0a428deaf09..fb8980780f1d 100644
--- a/Lib/test/test_dbm.py
+++ b/Lib/test/test_dbm.py
@@ -86,12 +86,21 @@ def test_anydbm_modification(self):
         f = dbm.open(_fname, 'c')
         self._dict['g'] = f[b'g'] = b"indented"
         self.read_helper(f)
+        # setdefault() works as in the dict interface
+        self.assertEqual(f.setdefault(b'xxx', b'foo'), b'foo')
+        self.assertEqual(f[b'xxx'], b'foo')
         f.close()
 
     def test_anydbm_read(self):
         self.init_db()
         f = dbm.open(_fname, 'r')
         self.read_helper(f)
+        # get() works as in the dict interface
+        self.assertEqual(f.get(b'a'), self._dict['a'])
+        self.assertEqual(f.get(b'xxx', b'foo'), b'foo')
+        self.assertIsNone(f.get(b'xxx'))
+        with self.assertRaises(KeyError):
+            f[b'xxx']
         f.close()
 
     def test_anydbm_keys(self):
diff --git a/Lib/test/test_dbm_dumb.py b/Lib/test/test_dbm_dumb.py
index 652a355d990b..58b9d1746568 100644
--- a/Lib/test/test_dbm_dumb.py
+++ b/Lib/test/test_dbm_dumb.py
@@ -73,6 +73,9 @@ def test_dumbdbm_modification(self):
         f = dumbdbm.open(_fname, 'w')
         self._dict[b'g'] = f[b'g'] = b"indented"
         self.read_helper(f)
+        # setdefault() works as in the dict interface
+        self.assertEqual(f.setdefault(b'xxx', b'foo'), b'foo')
+        self.assertEqual(f[b'xxx'], b'foo')
         f.close()
 
     def test_dumbdbm_read(self):
@@ -85,6 +88,12 @@ def test_dumbdbm_read(self):
         with self.assertRaisesRegex(ValueError,
                                    'The database is opened for reading only'):
             del f[b'a']
+        # get() works as in the dict interface
+        self.assertEqual(f.get(b'a'), self._dict[b'a'])
+        self.assertEqual(f.get(b'xxx', b'foo'), b'foo')
+        self.assertIsNone(f.get(b'xxx'))
+        with self.assertRaises(KeyError):
+            f[b'xxx']
         f.close()
 
     def test_dumbdbm_keys(self):
diff --git a/Lib/test/test_dbm_gnu.py b/Lib/test/test_dbm_gnu.py
index d96df9284806..463d34341155 100644
--- a/Lib/test/test_dbm_gnu.py
+++ b/Lib/test/test_dbm_gnu.py
@@ -32,9 +32,12 @@ def test_key_methods(self):
             self.assertIn(key, key_set)
             key_set.remove(key)
             key = self.g.nextkey(key)
-        self.assertRaises(KeyError, lambda: self.g['xxx'])
         # get() and setdefault() work as in the dict interface
+        self.assertEqual(self.g.get(b'a'), b'b')
+        self.assertIsNone(self.g.get(b'xxx'))
         self.assertEqual(self.g.get(b'xxx', b'foo'), b'foo')
+        with self.assertRaises(KeyError):
+            self.g['xxx']
         self.assertEqual(self.g.setdefault(b'xxx', b'foo'), b'foo')
         self.assertEqual(self.g[b'xxx'], b'foo')
 
diff --git a/Lib/test/test_dbm_ndbm.py b/Lib/test/test_dbm_ndbm.py
index fb7d0e8281e3..f921167ca463 100644
--- a/Lib/test/test_dbm_ndbm.py
+++ b/Lib/test/test_dbm_ndbm.py
@@ -18,7 +18,7 @@ def tearDown(self):
 
     def test_keys(self):
         self.d = dbm.ndbm.open(self.filename, 'c')
-        self.assertTrue(self.d.keys() == [])
+        self.assertEqual(self.d.keys(), [])
         self.d['a'] = 'b'
         self.d[b'bytes'] = b'data'
         self.d['12345678910'] = '019237410982340912840198242'
@@ -26,6 +26,14 @@ def test_keys(self):
         self.assertIn('a', self.d)
         self.assertIn(b'a', self.d)
         self.assertEqual(self.d[b'bytes'], b'data')
+        # get() and setdefault() work as in the dict interface
+        self.assertEqual(self.d.get(b'a'), b'b')
+        self.assertIsNone(self.d.get(b'xxx'))
+        self.assertEqual(self.d.get(b'xxx', b'foo'), b'foo')
+        with self.assertRaises(KeyError):
+            self.d['xxx']
+        self.assertEqual(self.d.setdefault(b'xxx', b'foo'), b'foo')
+        self.assertEqual(self.d[b'xxx'], b'foo')
         self.d.close()
 
     def test_modes(self):
diff --git a/Misc/NEWS.d/next/Library/2018-04-29-11-15-38.bpo-33383.g32YWn.rst b/Misc/NEWS.d/next/Library/2018-04-29-11-15-38.bpo-33383.g32YWn.rst
new file mode 100644
index 000000000000..7b65baac97bf
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2018-04-29-11-15-38.bpo-33383.g32YWn.rst
@@ -0,0 +1,2 @@
+Fixed crash in the get() method of the :mod:`dbm.ndbm` database object when
+it is called with a single argument.
diff --git a/Modules/_dbmmodule.c b/Modules/_dbmmodule.c
index 8afd92cf3ca8..65761d83d380 100644
--- a/Modules/_dbmmodule.c
+++ b/Modules/_dbmmodule.c
@@ -274,7 +274,7 @@ static PySequenceMethods dbm_as_sequence = {
 _dbm.dbm.get
 
     key: str(accept={str, robuffer}, zeroes=True)
-    default: object(c_default="NULL") = b''
+    default: object = None
     /
 
 Return the value for key if present, otherwise default.
@@ -283,7 +283,7 @@ Return the value for key if present, otherwise default.
 static PyObject *
 _dbm_dbm_get_impl(dbmobject *self, const char *key,
                   Py_ssize_clean_t key_length, PyObject *default_value)
-/*[clinic end generated code: output=b44f95eba8203d93 input=a3a279957f85eb6d]*/
+/*[clinic end generated code: output=b44f95eba8203d93 input=b788eba0ffad2e91]*/
 /*[clinic end generated code: output=4f5c0e523eaf1251 input=9402c0af8582dc69]*/
 {
     datum dbm_key, val;
diff --git a/Modules/clinic/_dbmmodule.c.h b/Modules/clinic/_dbmmodule.c.h
index 0f831c9eec72..574cc5ee174b 100644
--- a/Modules/clinic/_dbmmodule.c.h
+++ b/Modules/clinic/_dbmmodule.c.h
@@ -39,7 +39,7 @@ _dbm_dbm_keys(dbmobject *self, PyObject *Py_UNUSED(ignored))
 }
 
 PyDoc_STRVAR(_dbm_dbm_get__doc__,
-"get($self, key, default=b\'\', /)\n"
+"get($self, key, default=None, /)\n"
 "--\n"
 "\n"
 "Return the value for key if present, otherwise default.");
@@ -57,7 +57,7 @@ _dbm_dbm_get(dbmobject *self, PyObject *const *args, Py_ssize_t nargs)
     PyObject *return_value = NULL;
     const char *key;
     Py_ssize_clean_t key_length;
-    PyObject *default_value = NULL;
+    PyObject *default_value = Py_None;
 
     if (!_PyArg_ParseStack(args, nargs, "s#|O:get",
         &key, &key_length, &default_value)) {
@@ -141,4 +141,4 @@ dbmopen(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
 exit:
     return return_value;
 }
-/*[clinic end generated code: output=5c858b4080a011a4 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=1cba297bc8d7c2c2 input=a9049054013a1b77]*/



More information about the Python-checkins mailing list