Introduce the GLOB_MAXPATH flag, which allows the user to limit the

number of paths which glob(3) will return.  Remove the hardcoded limit
from the last commit, which restores the previous unbounded behavior.

Document the new flag in the manual page.
This commit is contained in:
Jonathan Lemon 2001-03-19 19:10:06 +00:00
parent c534fd78eb
commit bae8632f82
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=74469
3 changed files with 62 additions and 39 deletions

View File

@ -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 *));

View File

@ -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

View File

@ -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 ?