Module Name: src Committed By: riz Date: Sun Apr 24 15:41:10 UTC 2011
Modified Files: src/lib/libc/gen [netbsd-5]: glob.c Log Message: Pull up following revision(s) (requested by spz in ticket #1597): lib/libc/gen/glob.c: revision 1.28 lib/libc/gen/glob.c: revision 1.29 prevent resource DoS from brace expansion (from Maksymilian Arciemowicz) remove stray printf. To generate a diff of this commit: cvs rdiff -u -r1.23.4.1 -r1.23.4.2 src/lib/libc/gen/glob.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/lib/libc/gen/glob.c diff -u src/lib/libc/gen/glob.c:1.23.4.1 src/lib/libc/gen/glob.c:1.23.4.2 --- src/lib/libc/gen/glob.c:1.23.4.1 Mon Jul 19 18:14:08 2010 +++ src/lib/libc/gen/glob.c Sun Apr 24 15:41:10 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: glob.c,v 1.23.4.1 2010/07/19 18:14:08 riz Exp $ */ +/* $NetBSD: glob.c,v 1.23.4.2 2011/04/24 15:41:10 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.23.4.1 2010/07/19 18:14:08 riz Exp $"); +__RCSID("$NetBSD: glob.c,v 1.23.4.2 2011/04/24 15:41:10 riz Exp $"); #endif #endif /* LIBC_SCCS and not lint */ @@ -87,13 +87,18 @@ #define NO_GETPW_R #endif -#define GLOB_LIMIT_MALLOC 65536 -#define GLOB_LIMIT_STAT 128 -#define GLOB_LIMIT_READDIR 16384 - -#define GLOB_INDEX_MALLOC 0 -#define GLOB_INDEX_STAT 1 -#define GLOB_INDEX_READDIR 2 +#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) @@ -158,18 +163,18 @@ 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 *, size_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 *, size_t *); +static int globexp1(const Char *, glob_t *, struct glob_limit *); static int globexp2(const Char *, const Char *, glob_t *, int *, - size_t *); -static int match(Char *, Char *, Char *); + struct glob_limit *); +static int match(const Char *, const Char *, const Char *); #ifdef DEBUG static void qprintf(const char *, Char *); #endif @@ -181,8 +186,7 @@ const u_char *patnext; int c; Char *bufnext, *bufend, patbuf[MAXPATHLEN+1]; - /* 0 = malloc(), 1 = stat(), 2 = readdir() */ - size_t limit[] = { 0, 0, 0 }; + struct glob_limit limit = { 0, 0, 0, 0 }; _DIAGASSERT(pattern != NULL); @@ -218,9 +222,9 @@ *bufnext = EOS; if (flags & GLOB_BRACE) - return globexp1(patbuf, pglob, limit); + return globexp1(patbuf, pglob, &limit); else - return glob0(patbuf, pglob, limit); + return glob0(patbuf, pglob, &limit); } /* @@ -229,7 +233,7 @@ * characters */ static int -globexp1(const Char *pattern, glob_t *pglob, size_t *limit) +globexp1(const Char *pattern, glob_t *pglob, struct glob_limit *limit) { const Char* ptr = pattern; int rv; @@ -237,6 +241,12 @@ _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, limit); @@ -256,7 +266,7 @@ */ static int globexp2(const Char *ptr, const Char *pattern, glob_t *pglob, int *rv, - size_t *limit) + struct glob_limit *limit) { int i; Char *lm, *ls; @@ -461,7 +471,7 @@ * to find no matches. */ static int -glob0(const Char *pattern, glob_t *pglob, size_t *limit) +glob0(const Char *pattern, glob_t *pglob, struct glob_limit *limit) { const Char *qpatnext; int c, error; @@ -567,7 +577,7 @@ } 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]; @@ -592,11 +602,12 @@ * 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; @@ -617,7 +628,7 @@ return 0; if ((pglob->gl_flags & GLOB_LIMIT) && - limit[GLOB_INDEX_STAT]++ >= GLOB_LIMIT_STAT) { + limit->l_stat++ >= GLOB_LIMIT_STAT) { errno = 0; *pathend++ = SEP; *pathend = EOS; @@ -683,8 +694,8 @@ } 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; @@ -740,7 +751,7 @@ Char *dc; if ((pglob->gl_flags & GLOB_LIMIT) && - limit[GLOB_INDEX_READDIR]++ >= GLOB_LIMIT_READDIR) { + limit->l_readdir++ >= GLOB_LIMIT_READDIR) { errno = 0; *pathend++ = SEP; *pathend = EOS; @@ -829,7 +840,7 @@ * 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; @@ -840,6 +851,9 @@ _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) @@ -856,7 +870,7 @@ for (p = path; *p++;) continue; len = (size_t)(p - path); - limit[GLOB_INDEX_MALLOC] += len; + limit->l_string += len; if ((copy = malloc(len)) != NULL) { if (g_Ctoc(path, copy, len)) { free(copy); @@ -867,12 +881,13 @@ pathv[pglob->gl_offs + pglob->gl_pathc] = NULL; if ((pglob->gl_flags & GLOB_LIMIT) && - (newsize + limit[GLOB_INDEX_MALLOC]) >= GLOB_LIMIT_MALLOC) { - errno = 0; - return GLOB_NOSPACE; - } + (newsize + limit->l_string) >= GLOB_LIMIT_STRING) + goto nospace; return copy == NULL ? GLOB_NOSPACE : 0; +nospace: + errno = 0; + return GLOB_NOSPACE; } @@ -881,7 +896,7 @@ * 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;