From: millert Date: Sat, 12 Apr 1997 19:05:48 +0000 (+0000) Subject: Different fix for buffer overflow. From Keith Bostic X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=26d037cbd83b08e97eda369945e45e3d3bbca213;p=openbsd Different fix for buffer overflow. From Keith Bostic --- diff --git a/lib/libc/gen/glob.c b/lib/libc/gen/glob.c index 21abf96c730..ce5874bc023 100644 --- a/lib/libc/gen/glob.c +++ b/lib/libc/gen/glob.c @@ -35,7 +35,11 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static char rcsid[] = "$OpenBSD: glob.c,v 1.4 1996/10/27 17:46:40 deraadt Exp $"; +#if 0 +static char sccsid[] = "@(#)glob.c 8.3 (Berkeley) 10/13/93"; +#else +static char rcsid[] = "$OpenBSD: glob.c,v 1.5 1997/04/12 19:05:48 millert Exp $"; +#endif #endif /* LIBC_SCCS and not lint */ /* @@ -58,7 +62,7 @@ static char rcsid[] = "$OpenBSD: glob.c,v 1.4 1996/10/27 17:46:40 deraadt Exp $" * GLOB_TILDE: * expand ~user/foo to the /home/dir/of/user/foo * GLOB_BRACE: - * expand {1,2}{a,b} to 1a 1b 2a 2b + * expand {1,2}{a,b} to 1a 1b 2a 2b * gl_matchc: * Number of matches in the current invocation of glob. */ @@ -140,7 +144,7 @@ static int glob1 __P((Char *, glob_t *)); static int glob2 __P((Char *, Char *, Char *, glob_t *)); static int glob3 __P((Char *, Char *, Char *, Char *, glob_t *)); static int globextend __P((const Char *, glob_t *)); -static const Char * globtilde __P((const Char *, Char *, glob_t *)); +static const Char * globtilde __P((const Char *, Char *, size_t, glob_t *)); static int globexp1 __P((const Char *, glob_t *)); static int globexp2 __P((const Char *, const Char *, glob_t *, int *)); static int match __P((Char *, Char *, Char *)); @@ -173,7 +177,7 @@ glob(pattern, flags, errfunc, pglob) bufend = bufnext + MAXPATHLEN; if (flags & GLOB_QUOTE) { /* Protect the quoted characters. */ - while (bufnext < bufend && (c = *patnext++) != EOS) + while (bufnext < bufend && (c = *patnext++) != EOS) if (c == QUOTE) { if ((c = *patnext++) == EOS) { c = QUOTE; @@ -184,8 +188,8 @@ glob(pattern, flags, errfunc, pglob) else *bufnext++ = c; } - else - while (bufnext < bufend && (c = *patnext++) != EOS) + else + while (bufnext < bufend && (c = *patnext++) != EOS) *bufnext++ = c; *bufnext = EOS; @@ -246,7 +250,7 @@ static int globexp2(ptr, pattern, pglob, rv) for (pm = pe++; *pe != RBRACKET && *pe != EOS; pe++) continue; if (*pe == EOS) { - /* + /* * We could not find a matching RBRACKET. * Ignore and just look for RBRACE */ @@ -274,7 +278,7 @@ static int globexp2(ptr, pattern, pglob, rv) for (pl = pm++; *pm != RBRACKET && *pm != EOS; pm++) continue; if (*pm == EOS) { - /* + /* * We could not find a matching RBRACKET. * Ignore and just look for RBRACE */ @@ -299,7 +303,7 @@ static int globexp2(ptr, pattern, pglob, rv) /* Append the current string */ for (lm = ls; (pl < pm); *lm++ = *pl++) continue; - /* + /* * Append the rest of the pattern after the * closing brace */ @@ -330,29 +334,31 @@ static int globexp2(ptr, pattern, pglob, rv) * expand tilde from the passwd file. */ static const Char * -globtilde(pattern, patbuf, pglob) +globtilde(pattern, patbuf, patbuf_len, pglob) const Char *pattern; Char *patbuf; + size_t patbuf_len; glob_t *pglob; { struct passwd *pwd; char *h; const Char *p; - Char *b; + Char *b, *eb; if (*pattern != TILDE || !(pglob->gl_flags & GLOB_TILDE)) return pattern; /* Copy up to the end of the string or / */ - for (p = pattern + 1, h = (char *) patbuf; *p && *p != SLASH; - *h++ = *p++) + eb = &patbuf[patbuf_len - 1]; + for (p = pattern + 1, h = (char *) patbuf; + h < (char *)eb && *p && *p != SLASH; *h++ = *p++) continue; *h = EOS; if (((char *) patbuf)[0] == EOS) { - /* - * handle a plain ~ or ~/ by expanding $HOME + /* + * handle a plain ~ or ~/ by expanding $HOME * first and then trying the password file */ if (issetugid() != 0 || (h = getenv("HOME")) == NULL) { @@ -360,9 +366,6 @@ globtilde(pattern, patbuf, pglob) return pattern; else h = pwd->pw_dir; - } else { - if (strlen(h) >= MAXPATHLEN-1) - return pattern; } } else { @@ -376,16 +379,17 @@ globtilde(pattern, patbuf, pglob) } /* Copy the home directory */ - for (b = patbuf; *h; *b++ = *h++) + for (b = patbuf; b < eb && *h; *b++ = *h++) continue; - + /* Append the rest of the pattern */ - while ((*b++ = *p++) != EOS) + while (b < eb && (*b++ = *p++) != EOS) continue; + *b = EOS; return patbuf; } - + /* * The main glob() routine: compiles the pattern (optionally processing @@ -403,7 +407,8 @@ glob0(pattern, pglob) int c, err, oldpathc; Char *bufnext, patbuf[MAXPATHLEN+1]; - qpatnext = globtilde(pattern, patbuf, pglob); + qpatnext = globtilde(pattern, patbuf, sizeof(patbuf) / sizeof(Char), + pglob); oldpathc = pglob->gl_pathc; bufnext = patbuf; @@ -443,7 +448,7 @@ glob0(pattern, pglob) break; case STAR: pglob->gl_flags |= GLOB_MAGCHAR; - /* collapse adjacent stars to one, + /* collapse adjacent stars to one, * to avoid exponential behavior */ if (bufnext == patbuf || bufnext[-1] != M_ALL) @@ -463,17 +468,17 @@ glob0(pattern, pglob) return(err); /* - * If there was no match we are going to append the pattern + * If there was no match we are going to append the pattern * if GLOB_NOCHECK was specified or if GLOB_NOMAGIC was specified * and the pattern did not contain any magic characters * GLOB_NOMAGIC is there just for compatibility with csh. */ - if (pglob->gl_pathc == oldpathc && - ((pglob->gl_flags & GLOB_NOCHECK) || + if (pglob->gl_pathc == oldpathc && + ((pglob->gl_flags & GLOB_NOCHECK) || ((pglob->gl_flags & GLOB_NOMAGIC) && !(pglob->gl_flags & GLOB_MAGCHAR)))) return(globextend(pattern, pglob)); - else if (!(pglob->gl_flags & GLOB_NOSORT)) + else if (!(pglob->gl_flags & GLOB_NOSORT)) qsort(pglob->gl_pathv + pglob->gl_offs + oldpathc, pglob->gl_pathc - oldpathc, sizeof(char *), compare); return(0); @@ -522,7 +527,7 @@ glob2(pathbuf, pathend, pattern, pglob) *pathend = EOS; if (g_lstat(pathbuf, &sb, pglob)) return(0); - + if (((pglob->gl_flags & GLOB_MARK) && pathend[-1] != SEP) && (S_ISDIR(sb.st_mode) || (S_ISLNK(sb.st_mode) && @@ -575,7 +580,7 @@ glob3(pathbuf, pathend, pattern, restpattern, pglob) *pathend = EOS; errno = 0; - + if ((dirp = g_opendir(pathbuf, pglob)) == NULL) { /* TODO: don't call for ENOENT or ENOTDIR? */ if (pglob->gl_errfunc) { @@ -601,7 +606,7 @@ glob3(pathbuf, pathend, pattern, restpattern, pglob) /* Initial DOT must be matched literally. */ if (dp->d_name[0] == DOT && *pattern != DOT) continue; - for (sc = (u_char *) dp->d_name, dc = pathend; + for (sc = (u_char *) dp->d_name, dc = pathend; (*dc++ = *sc++) != EOS;) continue; if (!match(pathend, pattern, restpattern)) { @@ -647,7 +652,7 @@ globextend(path, pglob) const Char *p; newsize = sizeof(*pathv) * (2 + pglob->gl_pathc + pglob->gl_offs); - pathv = pglob->gl_pathv ? + pathv = pglob->gl_pathv ? realloc((char *)pglob->gl_pathv, newsize) : malloc(newsize); if (pathv == NULL) @@ -671,7 +676,6 @@ globextend(path, pglob) return(copy == NULL ? GLOB_NOSPACE : 0); } - /* * pattern matching function for filenames. Each occurrence of the * * pattern causes a recursion level. @@ -689,7 +693,7 @@ match(name, pat, patend) case M_ALL: if (pat == patend) return(1); - do + do if (match(name, pat, patend)) return(1); while (*name++ != EOS); @@ -828,7 +832,7 @@ g_Ctoc(str, buf) } #ifdef DEBUG -static void +static void qprintf(str, s) const char *str; register Char *s;