bpo-40014: Fix os.getgrouplist() on macOS (GH-19118)
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.
diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c
index ffee87c..e489b74 100644
--- a/Modules/posixmodule.c
+++ b/Modules/posixmodule.c
@@ -6999,10 +6999,29 @@
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. */
+ PyMem_Free(groups);
+
+ if (ngroups > INT_MAX / 2) {
+ return PyErr_NoMemory();
+ }
+ ngroups *= 2;
+
+ groups = PyMem_New(int, ngroups);
+ 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
/* Clang memory sanitizer libc intercepts don't know getgrouplist. */