8000 bpo-40014: Fix os.getgrouplist() (GH-19126) · python/cpython@f5c7cab · GitHub
[go: up one dir, main page]

Skip to content
8000

Commit f5c7cab

Browse files
authored
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.
1 parent 4b3252c commit f5c7cab

File tree

2 files changed

+29
-25
lines changed

2 files changed

+29
-25
lines changed
Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1-
Fix ``os.getgrouplist()``: on macOS, the ``getgrouplist()`` function returns a
2-
non-zero value without setting ``errno`` if the group list is too small. Double
3-
the list size and call it again in this case.
1+
Fix ``os.getgrouplist()``: if ``getgrouplist()`` function fails because the
2+
group list is too small, retry with a larger group list. On failure, the glibc
3+
implementation of ``getgrouplist()`` sets ``ngroups`` to the total number of
4+
groups. For other implementations, double the group list size.

Modules/posixmodule.c

Lines changed: 25 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -6991,37 +6991,40 @@ posix_getgrouplist(PyObject *self, PyObject *args)
69916991
return NULL;
69926992
#endif
69936993

6994+
while (1) {
69946995
#ifdef __APPLE__
6995-
groups = PyMem_New(int, ngroups);
6996+
groups = PyMem_New(int, ngroups);
69966997
#else
6997-
groups = PyMem_New(gid_t, ngroups);
6998+
groups = PyMem_New(gid_t, ngroups);
69986999
#endif
6999-
if (groups == NULL)
7000-
return PyErr_NoMemory();
7000+
if (groups == NULL) {
7001+
return PyErr_NoMemory();
7002+
}
70017003

7002-
#ifdef __APPLE__
7003-
while (getgrouplist(user, basegid, groups, &ngroups)) {
7004-
/* On macOS, getgrouplist() returns a non-zero value without setting
7005-
errno if the group list is too small. Double the list size and call
7006-
it again in this case. */
7004+
int old_ngroups = ngroups;
7005+
if (getgrouplist(user, basegid, groups, &ngroups) != -1) {
7006+
/* Success */
7007+
break;
7008+
}
7009+
7010+
/* getgrouplist() fails if the group list is too small */
70077011
PyMem_Free(groups);
70087012

7009-
if (ngroups > INT_MAX / 2) {
7010-
return PyErr_NoMemory();
7013+
if (ngroups > old_ngroups) {
7014+
/* If the group list is too small, the glibc implementation of
7015+
getgrouplist() sets ngroups to the total number of groups and
7016+
returns -1. */
70117017
}
7012-
ngroups *= 2;
7013-
7014-
groups = PyMem_New(int, ngroups);
7015-
if (groups == NULL) {
7016-
return PyErr_NoMemory();
7018+
else {
7019+
/* Double the group list size */
7020+
if (ngroups > INT_MAX / 2) {
7021+
return PyErr_NoMemory();
7022+
}
7023+
ngroups *= 2;
70177024
}
7025+
7026+
/* Retry getgrouplist() with a larger group list */
70187027
}
7019-
#else
7020-
if (getgrouplist(user, basegid, groups, &ngroups) == -1) {
7021-
PyMem_Del(groups);
7022-
return posix_error();
7023-
}
7024-
#endif
70257028

70267029
#ifdef _Py_MEMORY_SANITIZER
70277030
/* Clang memory sanitizer libc intercepts don't know getgrouplist. */

0 commit comments

Comments
 (0)
0