diff options
-rw-r--r-- | ChangeLog.txt | 2 | ||||
-rw-r--r-- | ports/darwin/guts/getgrouplist.c | 54 | ||||
-rw-r--r-- | ports/linux/guts/getgrouplist.c | 54 | ||||
-rw-r--r-- | ports/uids_generic/guts/getgrent.c | 26 | ||||
-rw-r--r-- | ports/uids_generic/guts/getgrgid.c | 26 | ||||
-rw-r--r-- | ports/uids_generic/guts/getgrnam.c | 25 |
6 files changed, 148 insertions, 39 deletions
diff --git a/ChangeLog.txt b/ChangeLog.txt index 73a12d4..033fdcf 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -1,6 +1,8 @@ 2018-01-16: * (seebs) rework the LINKAT case significantly but now it's actually probably right. + * (<zboszor@pr.hu>) handle extremely long group names + in getgrnam and similar functions. 2017-12-22: * (seebs) handle the pathological case of LINKAT with diff --git a/ports/darwin/guts/getgrouplist.c b/ports/darwin/guts/getgrouplist.c index 85fccc9..c5950bd 100644 --- a/ports/darwin/guts/getgrouplist.c +++ b/ports/darwin/guts/getgrouplist.c @@ -9,23 +9,47 @@ int found = 0; int found_group = 0; - char buf[PSEUDO_PWD_MAX]; - struct group grp, *gbuf = &grp; - - setgrent(); - while ((rc = wrap_getgrent_r(gbuf, buf, PSEUDO_PWD_MAX, &gbuf)) == 0) { - int i = 0; - for (i = 0; gbuf->gr_mem[i]; ++i) { - if (!strcmp(gbuf->gr_mem[i], name)) { - if (found < *ngroups) - groups[found] = gbuf->gr_gid; - ++found; - if ((int) gbuf->gr_gid == basegid) - found_group = 1; + size_t buflen = PSEUDO_PWD_MAX; + char *buf = NULL; + struct group grp; + + rc = ERANGE; + + do { + struct group *gbuf = &grp; + char *new_buf = buf; + + if (rc == ERANGE) + new_buf = realloc(buf, buflen); + + if (!new_buf) { + rc = ENOMEM; + break; + } + + buf = new_buf; + + found = 0; + found_group = 0; + setgrent(); + while ((rc = wrap_getgrent_r(gbuf, buf, buflen, &gbuf)) == 0) { + int i = 0; + for (i = 0; gbuf->gr_mem[i]; ++i) { + if (!strcmp(gbuf->gr_mem[i], name)) { + if (found < *ngroups) + groups[found] = gbuf->gr_gid; + ++found; + if ((int) gbuf->gr_gid == basegid) + found_group = 1; + } } } - } - endgrent(); + endgrent(); + + if (rc == ERANGE) + buflen = buflen << 1; + } while (rc == ERANGE); + free(buf); if (!found_group) { if (found < *ngroups) groups[found] = basegid; diff --git a/ports/linux/guts/getgrouplist.c b/ports/linux/guts/getgrouplist.c index 3489ec9..8b16e47 100644 --- a/ports/linux/guts/getgrouplist.c +++ b/ports/linux/guts/getgrouplist.c @@ -9,23 +9,47 @@ int found = 0; int found_group = 0; - char buf[PSEUDO_PWD_MAX]; - struct group grp, *gbuf = &grp; - - setgrent(); - while ((rc = wrap_getgrent_r(gbuf, buf, PSEUDO_PWD_MAX, &gbuf)) == 0) { - int i = 0; - for (i = 0; gbuf->gr_mem[i]; ++i) { - if (!strcmp(gbuf->gr_mem[i], user)) { - if (found < *ngroups) - groups[found] = gbuf->gr_gid; - ++found; - if (gbuf->gr_gid == group) - found_group = 1; + size_t buflen = PSEUDO_PWD_MAX; + char *buf = NULL; + struct group grp; + + rc = ERANGE; + + do { + struct group *gbuf = &grp; + char *new_buf = buf; + + if (rc == ERANGE) + new_buf = realloc(buf, buflen); + + if (!new_buf) { + rc = ENOMEM; + break; + } + + buf = new_buf; + + found = 0; + found_group = 0; + setgrent(); + while ((rc = wrap_getgrent_r(gbuf, buf, buflen, &gbuf)) == 0) { + int i = 0; + for (i = 0; gbuf->gr_mem[i]; ++i) { + if (!strcmp(gbuf->gr_mem[i], user)) { + if (found < *ngroups) + groups[found] = gbuf->gr_gid; + ++found; + if (gbuf->gr_gid == group) + found_group = 1; + } } } - } - endgrent(); + endgrent(); + + if (rc == ERANGE) + buflen = buflen << 1; + } while (rc == ERANGE); + free(buf); if (!found_group) { if (found < *ngroups) groups[found] = group; diff --git a/ports/uids_generic/guts/getgrent.c b/ports/uids_generic/guts/getgrent.c index e8e07f5..d6592e6 100644 --- a/ports/uids_generic/guts/getgrent.c +++ b/ports/uids_generic/guts/getgrent.c @@ -7,10 +7,30 @@ * struct group * rc = NULL; */ static struct group grp; - static char grbuf[PSEUDO_PWD_MAX]; - int r_rc; + static size_t grbuflen = PSEUDO_PWD_MAX; + static char *grbuf = NULL; + int r_rc = ERANGE; + + do { + char *new_grbuf = grbuf; + + if (r_rc == ERANGE) + new_grbuf = realloc(grbuf, grbuflen); + + if (!new_grbuf) { + r_rc = ENOMEM; + break; + } + + grbuf = new_grbuf; + + r_rc = wrap_getgrent_r(&grp, grbuf, grbuflen, &rc); + + if (r_rc == ERANGE) + grbuflen = grbuflen << 1; + + } while (r_rc == ERANGE); - r_rc = wrap_getgrent_r(&grp, grbuf, PSEUDO_PWD_MAX, &rc); /* different error return conventions */ if (r_rc != 0) { errno = r_rc; diff --git a/ports/uids_generic/guts/getgrgid.c b/ports/uids_generic/guts/getgrgid.c index c1824e7..0d3dafb 100644 --- a/ports/uids_generic/guts/getgrgid.c +++ b/ports/uids_generic/guts/getgrgid.c @@ -7,10 +7,30 @@ * struct group * rc = NULL; */ static struct group grp; - static char grbuf[PSEUDO_PWD_MAX]; - int r_rc; + static size_t grbuflen = PSEUDO_PWD_MAX; + static char *grbuf = NULL; + int r_rc = ERANGE; + + do { + char *new_grbuf = grbuf; + + if (r_rc == ERANGE) + new_grbuf = realloc(grbuf, grbuflen); + + if (!new_grbuf) { + r_rc = ENOMEM; + break; + } + + grbuf = new_grbuf; + + r_rc = wrap_getgrgid_r(gid, &grp, grbuf, grbuflen, &rc); + + if (r_rc == ERANGE) + grbuflen = grbuflen << 1; + + } while (r_rc == ERANGE); - r_rc = wrap_getgrgid_r(gid, &grp, grbuf, PSEUDO_PWD_MAX, &rc); /* different error return conventions */ if (r_rc != 0) { errno = r_rc; diff --git a/ports/uids_generic/guts/getgrnam.c b/ports/uids_generic/guts/getgrnam.c index 0e26444..19006ad 100644 --- a/ports/uids_generic/guts/getgrnam.c +++ b/ports/uids_generic/guts/getgrnam.c @@ -8,10 +8,29 @@ */ static struct group grp; - static char grbuf[PSEUDO_PWD_MAX]; - int r_rc; + static size_t grbufsz = PSEUDO_PWD_MAX; + static char *grbuf = NULL; + int r_rc = ERANGE; + + do { + char *new_grbuf = grbuf; + + if (r_rc != 0) + new_grbuf = realloc(grbuf, grbufsz); + + if (!new_grbuf) { + r_rc = ENOMEM; + break; + } + + grbuf = new_grbuf; + + r_rc = wrap_getgrnam_r(name, &grp, grbuf, grbufsz, &rc); + + if (r_rc == ERANGE) + grbufsz = grbufsz << 1; + } while (r_rc == ERANGE); - r_rc = wrap_getgrnam_r(name, &grp, grbuf, PSEUDO_PWD_MAX, &rc); /* different error return conventions */ if (r_rc != 0) { errno = r_rc; |