Skip to content

Commit 8727664

Browse files
authored
bpo-32494: Use gdbm_count for dbm_length if possible (pythonGH-19814)
1 parent b796b3f commit 8727664

File tree

2 files changed

+27
-5
lines changed

2 files changed

+27
-5
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Update :mod:`dbm.gnu` to use gdbm_count if possible when calling
2+
:func:`len`. Patch by Dong-hee Na.

Modules/_gdbmmodule.c

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ values() methods are not supported.");
3636

3737
typedef struct {
3838
PyObject_HEAD
39-
int di_size; /* -1 means recompute */
39+
Py_ssize_t di_size; /* -1 means recompute */
4040
GDBM_FILE di_dbm;
4141
} dbmobject;
4242

@@ -102,19 +102,39 @@ dbm_length(dbmobject *dp)
102102
return -1;
103103
}
104104
if (dp->di_size < 0) {
105+
#if GDBM_VERSION_MAJOR >= 1 && GDBM_VERSION_MINOR >= 11
106+
errno = 0;
107+
gdbm_count_t count;
108+
if (gdbm_count(dp->di_dbm, &count) == -1) {
109+
if (errno != 0) {
110+
PyErr_SetFromErrno(DbmError);
111+
}
112+
else {
113+
PyErr_SetString(DbmError, gdbm_strerror(gdbm_errno));
114+
}
115+
return -1;
116+
}
117+
if (count > PY_SSIZE_T_MAX) {
118+
PyErr_SetString(PyExc_OverflowError, "count exceeds PY_SSIZE_T_MAX");
119+
return -1;
120+
}
121+
dp->di_size = count;
122+
#else
105123
datum key,okey;
106-
int size;
107124
okey.dsize=0;
108125
okey.dptr=NULL;
109126

110-
size = 0;
111-
for (key=gdbm_firstkey(dp->di_dbm); key.dptr;
127+
Py_ssize_t size = 0;
128+
for (key = gdbm_firstkey(dp->di_dbm); key.dptr;
112129
key = gdbm_nextkey(dp->di_dbm,okey)) {
113130
size++;
114-
if(okey.dsize) free(okey.dptr);
131+
if (okey.dsize) {
132+
free(okey.dptr);
133+
}
115134
okey=key;
116135
}
117136
dp->di_size = size;
137+
#endif
118138
}
119139
return dp->di_size;
120140
}

0 commit comments

Comments
 (0)