]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-32494: Use gdbm_count for dbm_length if possible (GH-19814)
authorDong-hee Na <donghee.na92@gmail.com>
Fri, 1 May 2020 12:15:35 +0000 (21:15 +0900)
committerGitHub <noreply@github.com>
Fri, 1 May 2020 12:15:35 +0000 (14:15 +0200)
Misc/NEWS.d/next/Library/2020-04-30-22-25-08.bpo-32494.1xaU5l.rst [new file with mode: 0644]
Modules/_gdbmmodule.c

diff --git a/Misc/NEWS.d/next/Library/2020-04-30-22-25-08.bpo-32494.1xaU5l.rst b/Misc/NEWS.d/next/Library/2020-04-30-22-25-08.bpo-32494.1xaU5l.rst
new file mode 100644 (file)
index 0000000..3989700
--- /dev/null
@@ -0,0 +1,2 @@
+Update :mod:`dbm.gnu` to use gdbm_count if possible when calling
+:func:`len`. Patch by Dong-hee Na.
index 7a9649b54119b3a5f317c6004b7e6f26577035ff..dd4c6b16f745cf01ef1c3ffbb4912e07a1eaa22d 100644 (file)
@@ -36,7 +36,7 @@ values() methods are not supported.");
 
 typedef struct {
     PyObject_HEAD
-    int di_size;        /* -1 means recompute */
+    Py_ssize_t di_size;        /* -1 means recompute */
     GDBM_FILE di_dbm;
 } dbmobject;
 
@@ -102,19 +102,39 @@ dbm_length(dbmobject *dp)
         return -1;
     }
     if (dp->di_size < 0) {
+#if GDBM_VERSION_MAJOR >= 1 && GDBM_VERSION_MINOR >= 11
+        errno = 0;
+        gdbm_count_t count;
+        if (gdbm_count(dp->di_dbm, &count) == -1) {
+            if (errno != 0) {
+                PyErr_SetFromErrno(DbmError);
+            }
+            else {
+                PyErr_SetString(DbmError, gdbm_strerror(gdbm_errno));
+            }
+            return -1;
+        }
+        if (count > PY_SSIZE_T_MAX) {
+            PyErr_SetString(PyExc_OverflowError, "count exceeds PY_SSIZE_T_MAX");
+            return -1;
+        }
+        dp->di_size = count;
+#else
         datum key,okey;
-        int size;
         okey.dsize=0;
         okey.dptr=NULL;
 
-        size = 0;
-        for (key=gdbm_firstkey(dp->di_dbm); key.dptr;
+        Py_ssize_t size = 0;
+        for (key = gdbm_firstkey(dp->di_dbm); key.dptr;
              key = gdbm_nextkey(dp->di_dbm,okey)) {
             size++;
-            if(okey.dsize) free(okey.dptr);
+            if (okey.dsize) {
+                free(okey.dptr);
+            }
             okey=key;
         }
         dp->di_size = size;
+#endif
     }
     return dp->di_size;
 }