]> granicus.if.org Git - python/commitdiff
bpo-33383: Fix crash in get() of the dbm.ndbm database object. (#6630)
authorSerhiy Storchaka <storchaka@gmail.com>
Sun, 29 Apr 2018 09:38:06 +0000 (12:38 +0300)
committerGitHub <noreply@github.com>
Sun, 29 Apr 2018 09:38:06 +0000 (12:38 +0300)
Lib/test/test_dbm.py
Lib/test/test_dbm_dumb.py
Lib/test/test_dbm_gnu.py
Lib/test/test_dbm_ndbm.py
Misc/NEWS.d/next/Library/2018-04-29-11-15-38.bpo-33383.g32YWn.rst [new file with mode: 0644]
Modules/_dbmmodule.c
Modules/clinic/_dbmmodule.c.h

index f0a428deaf099475ac3475f46eeba4dd1c062c53..fb8980780f1d7985b630e618cc4af5ae8fc34bcc 100644 (file)
@@ -86,12 +86,21 @@ class AnyDBMTestCase:
         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):
index 652a355d990b8dca8ba61a0e0544f1b7c5d2085a..58b9d1746568957c57dbbd8c7d339b6440296067 100644 (file)
@@ -73,6 +73,9 @@ class DumbDBMTestCase(unittest.TestCase):
         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 @@ class DumbDBMTestCase(unittest.TestCase):
         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):
index d96df92848063cbc2a8cf0d122bb9e7c6347f7c5..463d343411558c985e140a29c7ddc814d0d0d241 100644 (file)
@@ -32,9 +32,12 @@ class TestGdbm(unittest.TestCase):
             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')
 
index fb7d0e8281e32dc162c5495207ca5b3521a2062f..f921167ca463465f3696e99e54b21048e8ce361b 100644 (file)
@@ -18,7 +18,7 @@ class DbmTestCase(unittest.TestCase):
 
     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 @@ class DbmTestCase(unittest.TestCase):
         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 (file)
index 0000000..7b65baa
--- /dev/null
@@ -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.
index 8afd92cf3ca8688c4876238089b4474c769b96a0..65761d83d380f71ef344ff136331b6a767c6dba9 100644 (file)
@@ -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;
index 0f831c9eec722c3d560d6f8b67ad8779f5e1cbe3..574cc5ee174b7b0c8eb48e657337d790608938f2 100644 (file)
@@ -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]*/