diff options
author | Pádraig Brady <P@draigBrady.com> | 2009-04-08 10:43:15 +0100 |
---|---|---|
committer | Pádraig Brady <P@draigBrady.com> | 2009-04-09 14:07:29 +0100 |
commit | bf87a2c8ea4487ca4448c9fe42a9c9858400acbd (patch) | |
tree | 74ecdd17b278c53f6cfcaee0bac7e2e1ee03559e /gl/lib | |
parent | 148ddb3232e6319479222d4f7dee49b2c44ce21a (diff) | |
download | coreutils-bf87a2c8ea4487ca4448c9fe42a9c9858400acbd.tar.xz |
id: fix infinite loop on some systems
Steven Parkes reported that `id -G $USER` went into an infinite loop
on Darwin systems for users in more than 10 groups:
http://bugs.gentoo.org/show_bug.cgi?id=264007
* gl/lib/mgetgroups.c (mgetgroups): Work around buggy getgrouplist
implementations that don't update the required size correctly,
by doubling the result buffer and retrying. Also return the
parameter updated by getgrouplist rather than its return value,
as the documentation doesn't actually state the number of groups
stored is returned by getgrouplist.
* tests/misc/id-groups: Add test to exercise this logic
* tests/Makefile.am: Reference new test
* NEWS: Mention the fix
* THANKS: Update
Diffstat (limited to 'gl/lib')
-rw-r--r-- | gl/lib/mgetgroups.c | 10 |
1 files changed, 9 insertions, 1 deletions
diff --git a/gl/lib/mgetgroups.c b/gl/lib/mgetgroups.c index e697013ef..736dd87f3 100644 --- a/gl/lib/mgetgroups.c +++ b/gl/lib/mgetgroups.c @@ -81,10 +81,16 @@ mgetgroups (char const *username, gid_t gid, GETGROUPS_T **groups) while (1) { GETGROUPS_T *h; + int last_n_groups = max_n_groups; /* getgrouplist updates max_n_groups to num required. */ ng = getgrouplist (username, gid, g, &max_n_groups); + /* Some systems (like Darwin) have a bug where they + never increase max_n_groups. */ + if (ng < 0 && last_n_groups == max_n_groups) + max_n_groups *= 2; + if ((h = realloc_groupbuf (g, max_n_groups)) == NULL) { int saved_errno = errno; @@ -97,7 +103,9 @@ mgetgroups (char const *username, gid_t gid, GETGROUPS_T **groups) if (0 <= ng) { *groups = g; - return ng; + /* On success some systems just return 0 from getgrouplist, + so return max_n_groups rather than ng. */ + return max_n_groups; } } } |