mirror of
https://github.com/python/cpython.git
synced 2025-11-27 13:45:25 +00:00
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.
This commit is contained in:
parent
4b3252cb76
commit
f5c7cabb2b
2 changed files with 32 additions and 28 deletions
|
|
@ -1,3 +1,4 @@
|
||||||
Fix ``os.getgrouplist()``: on macOS, the ``getgrouplist()`` function returns a
|
Fix ``os.getgrouplist()``: if ``getgrouplist()`` function fails because the
|
||||||
non-zero value without setting ``errno`` if the group list is too small. Double
|
group list is too small, retry with a larger group list. On failure, the glibc
|
||||||
the list size and call it again in this case.
|
implementation of ``getgrouplist()`` sets ``ngroups`` to the total number of
|
||||||
|
groups. For other implementations, double the group list size.
|
||||||
|
|
|
||||||
|
|
@ -6991,37 +6991,40 @@ posix_getgrouplist(PyObject *self, PyObject *args)
|
||||||
return NULL;
|
return NULL;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
while (1) {
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
groups = PyMem_New(int, ngroups);
|
groups = PyMem_New(int, ngroups);
|
||||||
#else
|
#else
|
||||||
groups = PyMem_New(gid_t, ngroups);
|
groups = PyMem_New(gid_t, ngroups);
|
||||||
#endif
|
#endif
|
||||||
if (groups == NULL)
|
if (groups == NULL) {
|
||||||
return PyErr_NoMemory();
|
return PyErr_NoMemory();
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef __APPLE__
|
int old_ngroups = ngroups;
|
||||||
while (getgrouplist(user, basegid, groups, &ngroups)) {
|
if (getgrouplist(user, basegid, groups, &ngroups) != -1) {
|
||||||
/* On macOS, getgrouplist() returns a non-zero value without setting
|
/* Success */
|
||||||
errno if the group list is too small. Double the list size and call
|
break;
|
||||||
it again in this case. */
|
}
|
||||||
|
|
||||||
|
/* getgrouplist() fails if the group list is too small */
|
||||||
PyMem_Free(groups);
|
PyMem_Free(groups);
|
||||||
|
|
||||||
|
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. */
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* Double the group list size */
|
||||||
if (ngroups > INT_MAX / 2) {
|
if (ngroups > INT_MAX / 2) {
|
||||||
return PyErr_NoMemory();
|
return PyErr_NoMemory();
|
||||||
}
|
}
|
||||||
ngroups *= 2;
|
ngroups *= 2;
|
||||||
|
}
|
||||||
|
|
||||||
groups = PyMem_New(int, ngroups);
|
/* Retry getgrouplist() with a larger group list */
|
||||||
if (groups == NULL) {
|
|
||||||
return PyErr_NoMemory();
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
#else
|
|
||||||
if (getgrouplist(user, basegid, groups, &ngroups) == -1) {
|
|
||||||
PyMem_Del(groups);
|
|
||||||
return posix_error();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef _Py_MEMORY_SANITIZER
|
#ifdef _Py_MEMORY_SANITIZER
|
||||||
/* Clang memory sanitizer libc intercepts don't know getgrouplist. */
|
/* Clang memory sanitizer libc intercepts don't know getgrouplist. */
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue