summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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