bpo-32494: Use gdbm_count for dbm_length if possible (GH-19814)

This commit is contained in:
Dong-hee Na 2020-05-01 21:15:35 +09:00 committed by GitHub
parent b796b3fb48
commit 8727664557
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 27 additions and 5 deletions

View File

@ -0,0 +1,2 @@
Update :mod:`dbm.gnu` to use gdbm_count if possible when calling
:func:`len`. Patch by Dong-hee Na.

View File

@ -36,7 +36,7 @@ values() methods are not supported.");
typedef struct { typedef struct {
PyObject_HEAD PyObject_HEAD
int di_size; /* -1 means recompute */ Py_ssize_t di_size; /* -1 means recompute */
GDBM_FILE di_dbm; GDBM_FILE di_dbm;
} dbmobject; } dbmobject;
@ -102,19 +102,39 @@ dbm_length(dbmobject *dp)
return -1; return -1;
} }
if (dp->di_size < 0) { 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; datum key,okey;
int size;
okey.dsize=0; okey.dsize=0;
okey.dptr=NULL; okey.dptr=NULL;
size = 0; Py_ssize_t size = 0;
for (key = gdbm_firstkey(dp->di_dbm); key.dptr; for (key = gdbm_firstkey(dp->di_dbm); key.dptr;
key = gdbm_nextkey(dp->di_dbm,okey)) { key = gdbm_nextkey(dp->di_dbm,okey)) {
size++; size++;
if(okey.dsize) free(okey.dptr); if (okey.dsize) {
free(okey.dptr);
}
okey=key; okey=key;
} }
dp->di_size = size; dp->di_size = size;
#endif
} }
return dp->di_size; return dp->di_size;
} }