diff options
author | Victor Stinner <vstinner@python.org> | 2020-03-24 17:22:10 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-03-24 17:22:10 (GMT) |
commit | f5c7cabb2be4e42a5975ba8aac8bb458c8d9d6d7 (patch) | |
tree | 3fcf2f5173005198c8a959fc03195220e74ab53f /Modules/posixmodule.c | |
parent | 4b3252cb764807fdb3a661b458d43e4af55cf4df (diff) | |
download | cpython-f5c7cabb2be4e42a5975ba8aac8bb458c8d9d6d7.zip cpython-f5c7cabb2be4e42a5975ba8aac8bb458c8d9d6d7.tar.gz cpython-f5c7cabb2be4e42a5975ba8aac8bb458c8d9d6d7.tar.bz2 |
bpo-40014: Fix os.getgrouplist() (GH-19126)
Fix os.getgrouplist(): if getgrouplist() function fails because the
group list is too small, retry with a larger group list.
On failure, the glibc implementation of getgrouplist() sets ngroups
to the total number of groups. For other implementations, double the
group list size.
Diffstat (limited to 'Modules/posixmodule.c')
-rw-r--r-- | Modules/posixmodule.c | 47 |
1 files changed, 25 insertions, 22 deletions
diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index e489b74..9ab136b 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -6991,37 +6991,40 @@ posix_getgrouplist(PyObject *self, PyObject *args) return NULL; #endif + while (1) { #ifdef __APPLE__ - groups = PyMem_New(int, ngroups); + groups = PyMem_New(int, ngroups); #else - groups = PyMem_New(gid_t, ngroups); + groups = PyMem_New(gid_t, ngroups); #endif - if (groups == NULL) - return PyErr_NoMemory(); + if (groups == NULL) { + return PyErr_NoMemory(); + } -#ifdef __APPLE__ - while (getgrouplist(user, basegid, groups, &ngroups)) { - /* On macOS, getgrouplist() returns a non-zero value without setting - errno if the group list is too small. Double the list size and call - it again in this case. */ + int old_ngroups = ngroups; + if (getgrouplist(user, basegid, groups, &ngroups) != -1) { + /* Success */ + break; + } + + /* getgrouplist() fails if the group list is too small */ PyMem_Free(groups); - if (ngroups > INT_MAX / 2) { - return PyErr_NoMemory(); + if (ngroups > old_ngroups) { + /* If the group list is too small, the glibc implementation of + getgrouplist() sets ngroups to the total number of groups and + returns -1. */ } - ngroups *= 2; - - groups = PyMem_New(int, ngroups); - if (groups == NULL) { - return PyErr_NoMemory(); + else { + /* Double the group list size */ + if (ngroups > INT_MAX / 2) { + return PyErr_NoMemory(); + } + ngroups *= 2; } + + /* Retry getgrouplist() with a larger group list */ } -#else - if (getgrouplist(user, basegid, groups, &ngroups) == -1) { - PyMem_Del(groups); - return posix_error(); - } -#endif #ifdef _Py_MEMORY_SANITIZER /* Clang memory sanitizer libc intercepts don't know getgrouplist. */ |