diff options
Diffstat (limited to 'hesiod')
-rw-r--r-- | hesiod/Versions | 2 | ||||
-rw-r--r-- | hesiod/nss_hesiod/hesiod-grp.c | 41 |
2 files changed, 35 insertions, 8 deletions
diff --git a/hesiod/Versions b/hesiod/Versions index c51dee9c50..180befb5b3 100644 --- a/hesiod/Versions +++ b/hesiod/Versions @@ -8,7 +8,7 @@ libnss_hesiod { _nss_hesiod_getservbyname_r; } GLIBC_2.2 { - _nss_hesiod_initgroups; + _nss_hesiod_initgroups_dyn; _nss_hesiod_getservbyport_r; _nss_hesiod_setprotoent; _nss_hesiod_endprotoent; _nss_hesiod_getprotobyname_r; _nss_hesiod_getprotobynumber_r; diff --git a/hesiod/nss_hesiod/hesiod-grp.c b/hesiod/nss_hesiod/hesiod-grp.c index 2d5b96b7f9..a89ed4edaf 100644 --- a/hesiod/nss_hesiod/hesiod-grp.c +++ b/hesiod/nss_hesiod/hesiod-grp.c @@ -164,14 +164,14 @@ internal_gid_from_group (void *context, const char *groupname, gid_t *group) } enum nss_status -_nss_hesiod_initgroups (const char *user, gid_t group, long int *start, - long int *size, gid_t *groups, long int limit, - int *errnop) +_nss_hesiod_initgroups_dyn (const char *user, gid_t group, long int *start, + long int *size, gid_t **groupsp, int *errnop) { enum nss_status status = NSS_STATUS_SUCCESS; char **list = NULL; char *p; void *context; + gid_t *groups = *groupsp; context = _nss_hesiod_init (); if (context == NULL) @@ -185,11 +185,24 @@ _nss_hesiod_initgroups (const char *user, gid_t group, long int *start, return errno == ENOENT ? NSS_STATUS_NOTFOUND : NSS_STATUS_UNAVAIL; } - if (!internal_gid_in_list (groups, group, *start) && *start < limit) - groups[(*start)++] = group; + if (!internal_gid_in_list (groups, group, *start)) + { + if (__builtin_expect (*start == *size, 0)) + { + /* Need a bigger buffer. */ + gid_t *newgroups; + newgroups = realloc (groups, 2 * *size * sizeof (*groups)); + if (newgroups == NULL) + goto done; + *groupsp = groups = newgroups; + *size *= 2; + } + + groups[(*start)++] = group; + } p = *list; - while (*p != '\0' && *start < limit) + while (*p != '\0') { char *endp; char *q; @@ -214,12 +227,26 @@ _nss_hesiod_initgroups (const char *user, gid_t group, long int *start, if (status == NSS_STATUS_SUCCESS && !internal_gid_in_list (groups, group, *start)) - groups[(*start)++] = group; + { + if (__builtin_expect (*start == *size, 0)) + { + /* Need a bigger buffer. */ + gid_t *newgroups; + newgroups = realloc (groups, 2 * *size * sizeof (*groups)); + if (newgroups == NULL) + goto done; + *groupsp = groups = newgroups; + *size *= 2; + } + + groups[(*start)++] = group; + } } p = q; } + done: hesiod_free_list (context, list); hesiod_end (context); |