diff options
-rw-r--r-- | include/glob.h | 3 | ||||
-rw-r--r-- | lib/libc/gen/glob.3 | 17 | ||||
-rw-r--r-- | lib/libc/gen/glob.c | 81 |
3 files changed, 62 insertions, 39 deletions
diff --git a/include/glob.h b/include/glob.h index 34da03a..7b74d33 100644 --- a/include/glob.h +++ b/include/glob.h @@ -34,6 +34,7 @@ * SUCH DAMAGE. * * @(#)glob.h 8.1 (Berkeley) 6/2/93 + * $FreeBSD$ */ #ifndef _GLOB_H_ @@ -76,9 +77,11 @@ typedef struct { #define GLOB_NOMAGIC 0x0200 /* GLOB_NOCHECK without magic chars (csh). */ #define GLOB_QUOTE 0x0400 /* Quote special chars with \. */ #define GLOB_TILDE 0x0800 /* Expand tilde names from the passwd file. */ +#define GLOB_MAXPATH 0x1000 /* limit number of returned paths */ #define GLOB_NOSPACE (-1) /* Malloc call failed. */ #define GLOB_ABEND (-2) /* Unignored error. */ +#define GLOB_LIMIT (-3) /* Path limit was hit. */ __BEGIN_DECLS int glob __P((const char *, int, int (*)(const char *, int), glob_t *)); diff --git a/lib/libc/gen/glob.3 b/lib/libc/gen/glob.3 index c643aaa..efc413c 100644 --- a/lib/libc/gen/glob.3 +++ b/lib/libc/gen/glob.3 @@ -260,6 +260,14 @@ character, avoiding any special interpretation of the character. Expand patterns that start with .Ql ~ to user name home directories. +.It Dv GLOB_MAXPATH +Limit the total number of returned pathnames to the value provided in +.Fa gl_matchc . +If +.Fn glob +would match more pathnames, +.Dv GLOB_LIMIT +will be returned. .El .Pp If, during the search, a directory is encountered that cannot be opened @@ -376,6 +384,14 @@ The scan was stopped because an error was encountered and either was set or .Fa \*(lp*errfunc\*(rp\*(lp\*(rp returned non-zero. +.It Dv GLOB_LIMIT +The flag +.Dv GLOB_MAXPATH +was provided, and the specified limit passed to +.Fn glob +in +.Fa pglob\->gl_matchc +was reached. .El .Pp The arguments @@ -412,6 +428,7 @@ that the flags .Dv GLOB_ALTDIRFUNC , .Dv GLOB_BRACE , .Dv GLOB_MAGCHAR , +.Dv GLOB_MAXPATH , .Dv GLOB_NOMAGIC , .Dv GLOB_QUOTE , and diff --git a/lib/libc/gen/glob.c b/lib/libc/gen/glob.c index 5ed8be4..1c1d8e0 100644 --- a/lib/libc/gen/glob.c +++ b/lib/libc/gen/glob.c @@ -80,14 +80,6 @@ static char sccsid[] = "@(#)glob.c 8.3 (Berkeley) 10/13/93"; #include "collate.h" -/* - * XXX - * Arbitrarily limit the number of pathnames that glob may - * return, to prevent DoS attacks. This should probably be - * configurable by the user. - */ -#define MAX_GLOBENTRIES 16384 - #define DOLLAR '$' #define DOT '.' #define EOS '\0' @@ -147,14 +139,14 @@ static Char *g_strchr __P((Char *, int)); static Char *g_strcat __P((Char *, const Char *)); #endif static int g_stat __P((Char *, struct stat *, glob_t *)); -static int glob0 __P((const Char *, glob_t *)); -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 int glob0 __P((const Char *, glob_t *, int *)); +static int glob1 __P((Char *, glob_t *, int *)); +static int glob2 __P((Char *, Char *, Char *, glob_t *, int *)); +static int glob3 __P((Char *, Char *, Char *, Char *, glob_t *, int *)); +static int globextend __P((const Char *, glob_t *, int *)); 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 globexp1 __P((const Char *, glob_t *, int *)); +static int globexp2 __P((const Char *, const Char *, glob_t *, int *, int *)); static int match __P((Char *, Char *, Char *)); #ifdef DEBUG static void qprintf __P((const char *, Char *)); @@ -167,7 +159,7 @@ glob(pattern, flags, errfunc, pglob) glob_t *pglob; { const u_char *patnext; - int c; + int c, limit; Char *bufnext, *bufend, patbuf[MAXPATHLEN+1]; patnext = (u_char *) pattern; @@ -177,6 +169,10 @@ glob(pattern, flags, errfunc, pglob) if (!(flags & GLOB_DOOFFS)) pglob->gl_offs = 0; } + if (flags & GLOB_MAXPATH) + limit = pglob->gl_matchc; + else + limit = 0; pglob->gl_flags = flags & ~GLOB_MAGCHAR; pglob->gl_errfunc = errfunc; pglob->gl_matchc = 0; @@ -202,9 +198,9 @@ glob(pattern, flags, errfunc, pglob) *bufnext = EOS; if (flags & GLOB_BRACE) - return globexp1(patbuf, pglob); + return globexp1(patbuf, pglob, &limit); else - return glob0(patbuf, pglob); + return glob0(patbuf, pglob, &limit); } /* @@ -212,22 +208,23 @@ glob(pattern, flags, errfunc, pglob) * invoke the standard globbing routine to glob the rest of the magic * characters */ -static int globexp1(pattern, pglob) +static int globexp1(pattern, pglob, limit) const Char *pattern; glob_t *pglob; + int *limit; { const Char* ptr = pattern; int rv; /* Protect a single {}, for find(1), like csh */ if (pattern[0] == LBRACE && pattern[1] == RBRACE && pattern[2] == EOS) - return glob0(pattern, pglob); + return glob0(pattern, pglob, limit); while ((ptr = (const Char *) g_strchr((Char *) ptr, LBRACE)) != NULL) - if (!globexp2(ptr, pattern, pglob, &rv)) + if (!globexp2(ptr, pattern, pglob, &rv, limit)) return rv; - return glob0(pattern, pglob); + return glob0(pattern, pglob, limit); } @@ -236,10 +233,10 @@ static int globexp1(pattern, pglob) * If it succeeds then it invokes globexp1 with the new pattern. * If it fails then it tries to glob the rest of the pattern and returns. */ -static int globexp2(ptr, pattern, pglob, rv) +static int globexp2(ptr, pattern, pglob, rv, limit) const Char *ptr, *pattern; glob_t *pglob; - int *rv; + int *rv, *limit; { int i; Char *lm, *ls; @@ -275,7 +272,7 @@ static int globexp2(ptr, pattern, pglob, rv) /* Non matching braces; just glob the pattern */ if (i != 0 || *pe == EOS) { - *rv = glob0(patbuf, pglob); + *rv = glob0(patbuf, pglob, limit); return 0; } @@ -322,7 +319,7 @@ static int globexp2(ptr, pattern, pglob, rv) #ifdef DEBUG qprintf("globexp2:", patbuf); #endif - *rv = globexp1(patbuf, pglob); + *rv = globexp1(patbuf, pglob, limit); /* move after the comma, to the next string */ pl = pm + 1; @@ -416,9 +413,10 @@ globtilde(pattern, patbuf, patbuf_len, pglob) * to find no matches. */ static int -glob0(pattern, pglob) +glob0(pattern, pglob, limit) const Char *pattern; glob_t *pglob; + int *limit; { const Char *qpatnext; int c, err, oldpathc; @@ -481,7 +479,7 @@ glob0(pattern, pglob) qprintf("glob0:", patbuf); #endif - if ((err = glob1(patbuf, pglob)) != 0) + if ((err = glob1(patbuf, pglob, limit)) != 0) return(err); /* @@ -494,7 +492,7 @@ glob0(pattern, pglob) ((pglob->gl_flags & GLOB_NOCHECK) || ((pglob->gl_flags & GLOB_NOMAGIC) && !(pglob->gl_flags & GLOB_MAGCHAR)))) - return(globextend(pattern, pglob)); + return(globextend(pattern, pglob, limit)); else if (!(pglob->gl_flags & GLOB_NOSORT)) qsort(pglob->gl_pathv + pglob->gl_offs + oldpathc, pglob->gl_pathc - oldpathc, sizeof(char *), compare); @@ -509,16 +507,17 @@ compare(p, q) } static int -glob1(pattern, pglob) +glob1(pattern, pglob, limit) Char *pattern; glob_t *pglob; + int *limit; { Char pathbuf[MAXPATHLEN+1]; /* A null pathname is invalid -- POSIX 1003.1 sect. 2.4. */ if (*pattern == EOS) return(0); - return(glob2(pathbuf, pathbuf, pattern, pglob)); + return(glob2(pathbuf, pathbuf, pattern, pglob, limit)); } /* @@ -527,9 +526,10 @@ glob1(pattern, pglob) * meta characters. */ static int -glob2(pathbuf, pathend, pattern, pglob) +glob2(pathbuf, pathend, pattern, pglob, limit) Char *pathbuf, *pathend, *pattern; glob_t *pglob; + int *limit; { struct stat sb; Char *p, *q; @@ -554,7 +554,7 @@ glob2(pathbuf, pathend, pattern, pglob) *pathend = EOS; } ++pglob->gl_matchc; - return(globextend(pathbuf, pglob)); + return(globextend(pathbuf, pglob, limit)); } /* Find end of next segment, copy tentatively to pathend. */ @@ -572,15 +572,17 @@ glob2(pathbuf, pathend, pattern, pglob) while (*pattern == SEP) *pathend++ = *pattern++; } else /* Need expansion, recurse. */ - return(glob3(pathbuf, pathend, pattern, p, pglob)); + return(glob3(pathbuf, pathend, pattern, p, pglob, + limit)); } /* NOTREACHED */ } static int -glob3(pathbuf, pathend, pattern, restpattern, pglob) +glob3(pathbuf, pathend, pattern, restpattern, pglob, limit) Char *pathbuf, *pathend, *pattern, *restpattern; glob_t *pglob; + int *limit; { register struct dirent *dp; DIR *dirp; @@ -630,7 +632,7 @@ glob3(pathbuf, pathend, pattern, restpattern, pglob) *pathend = EOS; continue; } - err = glob2(pathbuf, --dc, restpattern, pglob); + err = glob2(pathbuf, --dc, restpattern, pglob, limit); if (err) break; } @@ -658,9 +660,10 @@ glob3(pathbuf, pathend, pattern, restpattern, pglob) * gl_pathv points to (gl_offs + gl_pathc + 1) items. */ static int -globextend(path, pglob) +globextend(path, pglob, limit) const Char *path; glob_t *pglob; + int *limit; { register char **pathv; register int i; @@ -668,8 +671,8 @@ globextend(path, pglob) char *copy; const Char *p; - if (pglob->gl_pathc > MAX_GLOBENTRIES) - return (GLOB_ABEND); + if (*limit && pglob->gl_pathc > *limit) + return (GLOB_LIMIT); newsize = sizeof(*pathv) * (2 + pglob->gl_pathc + pglob->gl_offs); pathv = pglob->gl_pathv ? |