Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. =================================================================== RCS file: /ftp/cvs/cvsroot/src/lib/libc/gen/glob.c,v rcsdiff: /ftp/cvs/cvsroot/src/lib/libc/gen/glob.c,v: warning: Unknown phrases like `commitid ...;' are present. retrieving revision 1.22.4.1 retrieving revision 1.23.4.1.2.1 diff -u -p -r1.22.4.1 -r1.23.4.1.2.1 --- src/lib/libc/gen/glob.c 2008/06/23 04:29:31 1.22.4.1 +++ src/lib/libc/gen/glob.c 2011/04/24 15:41:23 1.23.4.1.2.1 @@ -1,4 +1,4 @@ -/* $NetBSD: glob.c,v 1.22.4.1 2008/06/23 04:29:31 wrstuden Exp $ */ +/* $NetBSD: glob.c,v 1.23.4.1.2.1 2011/04/24 15:41:23 riz Exp $ */ /* * Copyright (c) 1989, 1993 @@ -37,7 +37,7 @@ #if 0 static char sccsid[] = "@(#)glob.c 8.3 (Berkeley) 10/13/93"; #else -__RCSID("$NetBSD: glob.c,v 1.22.4.1 2008/06/23 04:29:31 wrstuden Exp $"); +__RCSID("$NetBSD: glob.c,v 1.23.4.1.2.1 2011/04/24 15:41:23 riz Exp $"); #endif #endif /* LIBC_SCCS and not lint */ @@ -87,10 +87,18 @@ __RCSID("$NetBSD: glob.c,v 1.22.4.1 2008 #define NO_GETPW_R #endif -#if !defined(ARG_MAX) -#include -#define ARG_MAX _POSIX_ARG_MAX -#endif +#define GLOB_LIMIT_STRING 65536 /* number of readdirs */ +#define GLOB_LIMIT_STAT 128 /* number of stat system calls */ +#define GLOB_LIMIT_READDIR 16384 /* total buffer size of path strings */ +#define GLOB_LIMIT_PATH 1024 /* number of path elements */ +#define GLOB_LIMIT_BRACE 128 /* Number of brace calls */ + +struct glob_limit { + size_t l_string; + size_t l_stat; + size_t l_readdir; + size_t l_brace; +}; /* * XXX: For NetBSD 1.4.x compatibility. (kill me l8r) @@ -155,17 +163,18 @@ static int g_lstat(Char *, __gl_stat_t static DIR *g_opendir(Char *, glob_t *); static Char *g_strchr(const Char *, int); static int g_stat(Char *, __gl_stat_t *, glob_t *); -static int glob0(const Char *, glob_t *); -static int glob1(Char *, glob_t *, size_t *); -static int glob2(Char *, Char *, Char *, Char *, glob_t *, - size_t *); -static int glob3(Char *, Char *, Char *, Char *, Char *, glob_t *, - size_t *); -static int globextend(const Char *, glob_t *, size_t *); +static int glob0(const Char *, glob_t *, struct glob_limit *); +static int glob1(Char *, glob_t *, struct glob_limit *); +static int glob2(Char *, Char *, Char *, const Char *, glob_t *, + struct glob_limit *); +static int glob3(Char *, Char *, Char *, const Char *, const Char *, + glob_t *, struct glob_limit *); +static int globextend(const Char *, glob_t *, struct glob_limit *); static const Char *globtilde(const Char *, Char *, size_t, glob_t *); -static int globexp1(const Char *, glob_t *); -static int globexp2(const Char *, const Char *, glob_t *, int *); -static int match(Char *, Char *, Char *); +static int globexp1(const Char *, glob_t *, struct glob_limit *); +static int globexp2(const Char *, const Char *, glob_t *, int *, + struct glob_limit *); +static int match(const Char *, const Char *, const Char *); #ifdef DEBUG static void qprintf(const char *, Char *); #endif @@ -177,6 +186,7 @@ glob(const char *pattern, int flags, int const u_char *patnext; int c; Char *bufnext, *bufend, patbuf[MAXPATHLEN+1]; + struct glob_limit limit = { 0, 0, 0, 0 }; _DIAGASSERT(pattern != NULL); @@ -212,9 +222,9 @@ glob(const char *pattern, int flags, int *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); } /* @@ -223,7 +233,7 @@ glob(const char *pattern, int flags, int * characters */ static int -globexp1(const Char *pattern, glob_t *pglob) +globexp1(const Char *pattern, glob_t *pglob, struct glob_limit *limit) { const Char* ptr = pattern; int rv; @@ -231,15 +241,21 @@ globexp1(const Char *pattern, glob_t *pg _DIAGASSERT(pattern != NULL); _DIAGASSERT(pglob != NULL); + if ((pglob->gl_flags & GLOB_LIMIT) && + limit->l_brace++ >= GLOB_LIMIT_BRACE) { + errno = 0; + return GLOB_NOSPACE; + } + /* 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(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); } @@ -249,7 +265,8 @@ globexp1(const Char *pattern, glob_t *pg * If it fails then it tries to glob the rest of the pattern and returns. */ static int -globexp2(const Char *ptr, const Char *pattern, glob_t *pglob, int *rv) +globexp2(const Char *ptr, const Char *pattern, glob_t *pglob, int *rv, + struct glob_limit *limit) { int i; Char *lm, *ls; @@ -294,7 +311,7 @@ globexp2(const Char *ptr, const Char *pa * we use `pattern', not `patbuf' here so that that * unbalanced braces are passed to the match */ - *rv = glob0(pattern, pglob); + *rv = glob0(pattern, pglob, limit); return 0; } @@ -341,7 +358,7 @@ globexp2(const Char *ptr, const Char *pa #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; @@ -454,13 +471,12 @@ globtilde(const Char *pattern, Char *pat * to find no matches. */ static int -glob0(const Char *pattern, glob_t *pglob) +glob0(const Char *pattern, glob_t *pglob, struct glob_limit *limit) { const Char *qpatnext; int c, error; __gl_size_t oldpathc; Char *bufnext, patbuf[MAXPATHLEN+1]; - size_t limit = 0; _DIAGASSERT(pattern != NULL); _DIAGASSERT(pglob != NULL); @@ -523,7 +539,7 @@ glob0(const Char *pattern, glob_t *pglob qprintf("glob0:", patbuf); #endif - if ((error = glob1(patbuf, pglob, &limit)) != 0) + if ((error = glob1(patbuf, pglob, limit)) != 0) return error; if (pglob->gl_pathc == oldpathc) { @@ -537,7 +553,7 @@ glob0(const Char *pattern, glob_t *pglob if ((pglob->gl_flags & GLOB_NOCHECK) || ((pglob->gl_flags & (GLOB_NOMAGIC|GLOB_MAGCHAR)) == GLOB_NOMAGIC)) { - return globextend(pattern, pglob, &limit); + return globextend(pattern, pglob, limit); } else { return GLOB_NOMATCH; } @@ -561,7 +577,7 @@ compare(const void *p, const void *q) } static int -glob1(Char *pattern, glob_t *pglob, size_t *limit) +glob1(Char *pattern, glob_t *pglob, struct glob_limit *limit) { Char pathbuf[MAXPATHLEN+1]; @@ -586,11 +602,12 @@ glob1(Char *pattern, glob_t *pglob, size * meta characters. */ static int -glob2(Char *pathbuf, Char *pathend, Char *pathlim, Char *pattern, glob_t *pglob, - size_t *limit) +glob2(Char *pathbuf, Char *pathend, Char *pathlim, const Char *pattern, + glob_t *pglob, struct glob_limit *limit) { __gl_stat_t sb; - Char *p, *q; + const Char *p; + Char *q; int anymeta; Char *pend; ptrdiff_t diff; @@ -610,6 +627,13 @@ glob2(Char *pathbuf, Char *pathend, Char if (g_lstat(pathbuf, &sb, pglob)) return 0; + if ((pglob->gl_flags & GLOB_LIMIT) && + limit->l_stat++ >= GLOB_LIMIT_STAT) { + errno = 0; + *pathend++ = SEP; + *pathend = EOS; + return GLOB_NOSPACE; + } if (((pglob->gl_flags & GLOB_MARK) && pathend[-1] != SEP) && (S_ISDIR(sb.st_mode) || (S_ISLNK(sb.st_mode) && @@ -670,8 +694,8 @@ glob2(Char *pathbuf, Char *pathend, Char } static int -glob3(Char *pathbuf, Char *pathend, Char *pathlim, Char *pattern, - Char *restpattern, glob_t *pglob, size_t *limit) +glob3(Char *pathbuf, Char *pathend, Char *pathlim, const Char *pattern, + const Char *restpattern, glob_t *pglob, struct glob_limit *limit) { struct dirent *dp; DIR *dirp; @@ -726,6 +750,14 @@ glob3(Char *pathbuf, Char *pathend, Char u_char *sc; Char *dc; + if ((pglob->gl_flags & GLOB_LIMIT) && + limit->l_readdir++ >= GLOB_LIMIT_READDIR) { + errno = 0; + *pathend++ = SEP; + *pathend = EOS; + return GLOB_NOSPACE; + } + /* * Initial DOT must be matched literally, unless we have * GLOB_PERIOD set. @@ -772,7 +804,8 @@ glob3(Char *pathbuf, Char *pathend, Char *pathend = EOS; continue; } - error = glob2(pathbuf, --dc, pathlim, restpattern, pglob, limit); + error = glob2(pathbuf, --dc, pathlim, restpattern, pglob, + limit); if (error) break; } @@ -807,7 +840,7 @@ glob3(Char *pathbuf, Char *pathend, Char * gl_pathv points to (gl_offs + gl_pathc + 1) items. */ static int -globextend(const Char *path, glob_t *pglob, size_t *limit) +globextend(const Char *path, glob_t *pglob, struct glob_limit *limit) { char **pathv; size_t i, newsize, len; @@ -818,6 +851,9 @@ globextend(const Char *path, glob_t *pgl _DIAGASSERT(pglob != NULL); newsize = sizeof(*pathv) * (2 + pglob->gl_pathc + pglob->gl_offs); + if ((pglob->gl_flags & GLOB_LIMIT) && + newsize > GLOB_LIMIT_PATH * sizeof(*pathv)) + goto nospace; pathv = pglob->gl_pathv ? realloc(pglob->gl_pathv, newsize) : malloc(newsize); if (pathv == NULL) @@ -834,7 +870,7 @@ globextend(const Char *path, glob_t *pgl for (p = path; *p++;) continue; len = (size_t)(p - path); - *limit += len; + limit->l_string += len; if ((copy = malloc(len)) != NULL) { if (g_Ctoc(path, copy, len)) { free(copy); @@ -844,12 +880,14 @@ globextend(const Char *path, glob_t *pgl } pathv[pglob->gl_offs + pglob->gl_pathc] = NULL; - if ((pglob->gl_flags & GLOB_LIMIT) && (newsize + *limit) >= ARG_MAX) { - errno = 0; - return GLOB_NOSPACE; - } + if ((pglob->gl_flags & GLOB_LIMIT) && + (newsize + limit->l_string) >= GLOB_LIMIT_STRING) + goto nospace; return copy == NULL ? GLOB_NOSPACE : 0; +nospace: + errno = 0; + return GLOB_NOSPACE; } @@ -858,7 +896,7 @@ globextend(const Char *path, glob_t *pgl * pattern causes a recursion level. */ static int -match(Char *name, Char *pat, Char *patend) +match(const Char *name, const Char *pat, const Char *patend) { int ok, negate_range; Char c, k;