summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjlemon <jlemon@FreeBSD.org>2001-03-19 19:10:06 +0000
committerjlemon <jlemon@FreeBSD.org>2001-03-19 19:10:06 +0000
commitb7db4c94c39d3b8f980a3c3f3ce1166ce5c3004e (patch)
tree11eade290d26f8295a18604584895a81c44ad608
parent5070a55a811bdaef9f6ed3c09aa7e24c47dd3f34 (diff)
downloadFreeBSD-src-b7db4c94c39d3b8f980a3c3f3ce1166ce5c3004e.zip
FreeBSD-src-b7db4c94c39d3b8f980a3c3f3ce1166ce5c3004e.tar.gz
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.
-rw-r--r--include/glob.h3
-rw-r--r--lib/libc/gen/glob.317
-rw-r--r--lib/libc/gen/glob.c81
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 ?
OpenPOWER on IntegriCloud