summaryrefslogtreecommitdiffstats
path: root/Modules/posixmodule.c
diff options
context:
space:
mode:
authorVictor Stinner <vstinner@python.org>2020-03-24 17:22:10 (GMT)
committerGitHub <noreply@github.com>2020-03-24 17:22:10 (GMT)
commitf5c7cabb2be4e42a5975ba8aac8bb458c8d9d6d7 (patch)
tree3fcf2f5173005198c8a959fc03195220e74ab53f /Modules/posixmodule.c
parent4b3252cb764807fdb3a661b458d43e4af55cf4df (diff)
downloadcpython-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.c47
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. */