[Python-checkins] bpo-40014: Fix os.getgrouplist() (GH-19126)

Miss Islington (bot) webhook-mailer at python.org
Tue Mar 24 13:39:24 EDT 2020


https://github.com/python/cpython/commit/5753fc69977bd9f70ecb4d466bda650efccf9e0a
commit: 5753fc69977bd9f70ecb4d466bda650efccf9e0a
branch: 3.7
author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com>
committer: GitHub <noreply at github.com>
date: 2020-03-24T10:39:15-07:00
summary:

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.
(cherry picked from commit f5c7cabb2be4e42a5975ba8aac8bb458c8d9d6d7)

Co-authored-by: Victor Stinner <vstinner at python.org>

files:
M Misc/NEWS.d/next/Library/2020-03-23-17-52-00.bpo-40014.Ya70VG.rst
M Modules/posixmodule.c

diff --git a/Misc/NEWS.d/next/Library/2020-03-23-17-52-00.bpo-40014.Ya70VG.rst b/Misc/NEWS.d/next/Library/2020-03-23-17-52-00.bpo-40014.Ya70VG.rst
index 58f14fa9a72d0..e9b36c211324b 100644
--- a/Misc/NEWS.d/next/Library/2020-03-23-17-52-00.bpo-40014.Ya70VG.rst
+++ b/Misc/NEWS.d/next/Library/2020-03-23-17-52-00.bpo-40014.Ya70VG.rst
@@ -1,3 +1,4 @@
-Fix ``os.getgrouplist()``: on macOS, the ``getgrouplist()`` function 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.
+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.
diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c
index 8d456730a3827..87ef2a9e0d22e 100644
--- a/Modules/posixmodule.c
+++ b/Modules/posixmodule.c
@@ -6170,37 +6170,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. */



More information about the Python-checkins mailing list