summaryrefslogtreecommitdiff
path: root/hesiod
diff options
context:
space:
mode:
Diffstat (limited to 'hesiod')
-rw-r--r--hesiod/Versions2
-rw-r--r--hesiod/nss_hesiod/hesiod-grp.c41
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);