diff --git a/misc/getusershell.c b/misc/getusershell.c index fc2c43b..a5d861e 100644 --- a/misc/getusershell.c +++ b/misc/getusershell.c @@ -31,6 +31,7 @@ static char sccsid[] = "@(#)getusershell.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ +#include #include #include #include @@ -99,6 +100,7 @@ initshells (void) FILE *fp; struct stat64 statb; size_t flen; + off64_t max_shells; free(shells); shells = NULL; @@ -114,12 +116,13 @@ initshells (void) okshells[1] = _PATH_CSHELL; return (char **) okshells; } - if (statb.st_size > ~(size_t)0 / sizeof (char *) * 3) + max_shells = (statb.st_size / 3) + 2; + if (max_shells > ~(size_t)0 / sizeof (char *)) goto init_okshells; flen = statb.st_size + 3; if ((strings = malloc(flen)) == NULL) goto init_okshells; - shells = malloc(statb.st_size / 3 * sizeof (char *)); + shells = malloc(max_shells * sizeof (char *)); if (shells == NULL) { free(strings); strings = NULL; @@ -130,13 +133,16 @@ initshells (void) while (fgets_unlocked(cp, flen - (cp - strings), fp) != NULL) { while (*cp != '#' && *cp != '/' && *cp != '\0') cp++; - if (*cp == '#' || *cp == '\0' || cp[1] == '\0') + /* Reject non-absolute paths, or anything too short. */ + if (cp[0] != '/' || cp[1] == '\0' || isspace(cp[1])) continue; *sp++ = cp; while (!isspace(*cp) && *cp != '#' && *cp != '\0') cp++; + assert (cp < strings + flen); *cp++ = '\0'; } + assert (sp < shells + max_shells); *sp = NULL; (void)fclose(fp); return (shells);