Issue #17557: Fix os.getgroups() to work with the modified behavior of
getgroups(2) on OS X 10.8.  Original patch by Mateusz Lenik.
diff --git a/Misc/ACKS b/Misc/ACKS
index aaa8dd4..54fa661f 100644
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -721,6 +721,7 @@
 Luke Kenneth Casson Leighton
 Tshepang Lekhonkhobe
 Marc-André Lemburg
+Mateusz Lenik
 John Lenton
 Kostyantyn Leschenko
 Christopher Tur Lesniewski-Laas
diff --git a/Misc/NEWS b/Misc/NEWS
index 825f6b3..f0cbca2 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -59,6 +59,9 @@
 Library
 -------
 
+- Issue #17557: Fix os.getgroups() to work with the modified behavior of
+  getgroups(2) on OS X 10.8.  Original patch by Mateusz Lenik.
+
 - Issue #18599: Fix name attribute of _sha1.sha1() object. It now returns
   'SHA1' instead of 'SHA'.
 
diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c
index 56903c4..32c85b8 100644
--- a/Modules/posixmodule.c
+++ b/Modules/posixmodule.c
@@ -6331,6 +6331,34 @@
     gid_t* alt_grouplist = grouplist;
     int n;
 
+#ifdef __APPLE__
+    /* Issue #17557: As of OS X 10.8, getgroups(2) no longer raises EINVAL if
+     * there are more groups than can fit in grouplist.  Therefore, on OS X
+     * always first call getgroups with length 0 to get the actual number
+     * of groups.
+     */
+    n = getgroups(0, NULL);
+    if (n < 0) {
+        return posix_error();
+    } else if (n <= MAX_GROUPS) {
+        /* groups will fit in existing array */
+        alt_grouplist = grouplist;
+    } else {
+        alt_grouplist = PyMem_Malloc(n * sizeof(gid_t));
+        if (alt_grouplist == NULL) {
+            errno = EINVAL;
+            return posix_error();
+        }
+    }
+
+    n = getgroups(n, alt_grouplist);
+    if (n == -1) {
+        if (alt_grouplist != grouplist) {
+            PyMem_Free(alt_grouplist);
+        }
+        return posix_error();
+    }
+#else
     n = getgroups(MAX_GROUPS, grouplist);
     if (n < 0) {
         if (errno == EINVAL) {
@@ -6357,6 +6385,8 @@
             return posix_error();
         }
     }
+#endif
+
     result = PyList_New(n);
     if (result != NULL) {
         int i;