Mercurial > hg > octave-nkf > gnulib-hg
changeset 12382:642c575d5700
mgetgroups: add xgetgroups, and avoid ENOSYS failures
ENOSYS implies that there are no supplemental groups, so we can
treat it the same as a return of 0 from getgroups rather than
exposing failure to the user. This in turn fixes a crash in
coreutils' id, which freed an uninitialized pointer.
* lib/mgetgroups.h (xgetgroups): New prototype.
* lib/mgetgroups.c (xgetgroups): New wrapper.
(mgetgroups): Handle ENOSYS.
* modules/mgetgroups (Depends-on): Add realloc.
Reported by Scott Harrison <scott.gnu.2009@scottrix.co.uk>.
Signed-off-by: Eric Blake <ebb9@byu.net>
author | Eric Blake <ebb9@byu.net> |
---|---|
date | Fri, 04 Dec 2009 08:26:23 -0700 |
parents | e63e3a5265e5 |
children | a22f69c2029c |
files | ChangeLog lib/mgetgroups.c lib/mgetgroups.h modules/mgetgroups |
diffstat | 4 files changed, 36 insertions(+), 4 deletions(-) [+] |
line wrap: on
line diff
--- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,12 @@ 2009-12-04 Eric Blake <ebb9@byu.net> + mgetgroups: add xgetgroups, and avoid ENOSYS failures + * lib/mgetgroups.h (xgetgroups): New prototype. + * lib/mgetgroups.c (xgetgroups): New wrapper. + (mgetgroups): Handle ENOSYS. + * modules/mgetgroups (Depends-on): Add realloc. + Reported by Scott Harrison <scott.gnu.2009@scottrix.co.uk>. + mgetgroups: avoid argument promotion issues with -1 * lib/mgetgroups.c (mgetgroups): A cast is required when checking for invalid gid_t.
--- a/lib/mgetgroups.c +++ b/lib/mgetgroups.c @@ -116,13 +116,24 @@ max_n_groups = (username ? getugroups (0, NULL, username, gid) - : getgroups (0, NULL) + (gid != (gid_t) -1)); + : getgroups (0, NULL)); - /* If we failed to count groups with NULL for a buffer, - try again with a non-NULL one, just in case. */ + /* If we failed to count groups because there is no supplemental + group support, then return an array containing just GID. + Otherwise, we fail for the same reason. */ if (max_n_groups < 0) - max_n_groups = 5; + { + if (errno == ENOSYS && (g = realloc_groupbuf (NULL, 1))) + { + *groups = g; + *g = gid; + return gid != (gid_t) -1; + } + return -1; + } + if (!username && gid != (gid_t) -1) + max_n_groups++; g = realloc_groupbuf (NULL, max_n_groups); if (g == NULL) return -1; @@ -133,6 +144,7 @@ if (ng < 0) { + /* Failure is unexpected, but handle it anyway. */ int saved_errno = errno; free (g); errno = saved_errno; @@ -147,3 +159,14 @@ *groups = g; return ng; } + +/* Like mgetgroups, but call xalloc_die on allocation failure. */ + +int +xgetgroups (char const *username, gid_t gid, gid_t **groups) +{ + int result = mgetgroups (username, gid, groups); + if (result == -1 && errno == ENOMEM) + xalloc_die (); + return result; +}