This is version 2 of the patch file.

Apply by doing:
	cd /usr/src
	patch -p0 < 025_glob.patch

And rebuild libc by doing:
	cd /usr/src/include
	cp glob.h /usr/include
	cd /usr/src/lib/libc
	make obj
	make depend
	make -DNOMAN
	make -DNOMAN install

The -DNOMAN hack prevents rebuilding of all the manual pages; this may
speed the patch installation up for some users.  Skip the -DNOMAN hack
if it does not bother you.

Index: include/glob.h
===================================================================
RCS file: /cvs/src/include/glob.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- include/glob.h	1998/01/31 17:06:26	1.4
+++ include/glob.h	2001/03/18 17:18:58	1.5
@@ -1,4 +1,4 @@
-/*	$OpenBSD: glob.h,v 1.4 1998/01/31 17:06:26 millert Exp $	*/
+/*	$OpenBSD: glob.h,v 1.5 2001/03/18 17:18:58 deraadt Exp $	*/
 /*	$NetBSD: glob.h,v 1.5 1994/10/26 00:55:56 cgd Exp $	*/
 
 /*
@@ -82,6 +82,7 @@
 #define	GLOB_QUOTE	0x0400	/* Quote special chars with \. */
 #define	GLOB_TILDE	0x0800	/* Expand tilde names from the passwd file. */
 #define	GLOB_NOESCAPE	0x1000	/* Disable backslash escaping. */
+#define GLOB_LIMIT	0x2000	/* Limit pattern match output to ARG_MAX */
 #endif
 
 /* Error values returned by glob(3) */
Index: lib/libc/gen/glob.c
===================================================================
RCS file: /cvs/src/lib/libc/gen/glob.c,v
retrieving revision 1.8
retrieving revision 1.16
diff -u -r1.8 -r1.16
--- lib/libc/gen/glob.c	1998/08/14 21:39:30	1.8
+++ lib/libc/gen/glob.c	2001/04/05 18:36:12	1.16
@@ -38,7 +38,7 @@
 #if 0
 static char sccsid[] = "@(#)glob.c	8.3 (Berkeley) 10/13/93";
 #else
-static char rcsid[] = "$OpenBSD: glob.c,v 1.8 1998/08/14 21:39:30 deraadt Exp $";
+static char rcsid[] = "$OpenBSD: glob.c,v 1.16 2001/04/05 18:36:12 deraadt Exp $";
 #endif
 #endif /* LIBC_SCCS and not lint */
 
@@ -131,20 +131,20 @@
 
 
 static int	 compare __P((const void *, const void *));
-static void	 g_Ctoc __P((const Char *, char *));
+static int	 g_Ctoc __P((const Char *, char *, u_int));
 static int	 g_lstat __P((Char *, struct stat *, glob_t *));
 static DIR	*g_opendir __P((Char *, glob_t *));
 static Char	*g_strchr __P((Char *, int));
-#ifdef notdef
-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 const Char *	globtilde __P((const Char *, Char *, size_t, glob_t *));
+static int	 glob1 __P((Char *, Char *, glob_t *, size_t *));
+static int	 glob2 __P((Char *, Char *, Char *, Char *, Char *, Char *,
+		    glob_t *, size_t *));
+static int	 glob3 __P((Char *, Char *, Char *, Char *, Char *, Char *,
+		    Char *, Char *, glob_t *, size_t *));
+static int	 globextend __P((const Char *, glob_t *, size_t *));
+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	 match __P((Char *, Char *, Char *));
@@ -160,7 +160,7 @@
 {
 	const u_char *patnext;
 	int c;
-	Char *bufnext, *bufend, patbuf[MAXPATHLEN+1];
+	Char *bufnext, *bufend, patbuf[MAXPATHLEN];
 
 	patnext = (u_char *) pattern;
 	if (!(flags & GLOB_APPEND)) {
@@ -174,10 +174,10 @@
 	pglob->gl_matchc = 0;
 
 	bufnext = patbuf;
-	bufend = bufnext + MAXPATHLEN;
+	bufend = bufnext + MAXPATHLEN - 1;
 	if (flags & GLOB_NOESCAPE)
-	    while (bufnext < bufend && (c = *patnext++) != EOS)
-		    *bufnext++ = c;
+		while (bufnext < bufend && (c = *patnext++) != EOS)
+			*bufnext++ = c;
 	else {
 		/* Protect the quoted characters. */
 		while (bufnext < bufend && (c = *patnext++) != EOS)
@@ -187,8 +187,7 @@
 					--patnext;
 				}
 				*bufnext++ = c | M_PROTECT;
-			}
-			else
+			} else
 				*bufnext++ = c;
 	}
 	*bufnext = EOS;
@@ -204,7 +203,8 @@
  * invoke the standard globbing routine to glob the rest of the magic
  * characters
  */
-static int globexp1(pattern, pglob)
+static int
+globexp1(pattern, pglob)
 	const Char *pattern;
 	glob_t *pglob;
 {
@@ -228,7 +228,8 @@
  * 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)
 	const Char *ptr, *pattern;
 	glob_t *pglob;
 	int *rv;
@@ -236,11 +237,12 @@
 	int     i;
 	Char   *lm, *ls;
 	const Char *pe, *pm, *pl;
-	Char    patbuf[MAXPATHLEN + 1];
+	Char    patbuf[MAXPATHLEN];
 
 	/* copy part up to the brace */
 	for (lm = patbuf, pm = pattern; pm != ptr; *lm++ = *pm++)
-		continue;
+		;
+	*lm = EOS;
 	ls = lm;
 
 	/* Find the balanced brace */
@@ -248,7 +250,7 @@
 		if (*pe == LBRACKET) {
 			/* Ignore everything between [] */
 			for (pm = pe++; *pe != RBRACKET && *pe != EOS; pe++)
-				continue;
+				;
 			if (*pe == EOS) {
 				/*
 				 * We could not find a matching RBRACKET.
@@ -256,8 +258,7 @@
 				 */
 				pe = pm;
 			}
-		}
-		else if (*pe == LBRACE)
+		} else if (*pe == LBRACE)
 			i++;
 		else if (*pe == RBRACE) {
 			if (i == 0)
@@ -271,12 +272,12 @@
 		return 0;
 	}
 
-	for (i = 0, pl = pm = ptr; pm <= pe; pm++)
+	for (i = 0, pl = pm = ptr; pm <= pe; pm++) {
 		switch (*pm) {
 		case LBRACKET:
 			/* Ignore everything between [] */
 			for (pl = pm++; *pm != RBRACKET && *pm != EOS; pm++)
-				continue;
+				;
 			if (*pm == EOS) {
 				/*
 				 * We could not find a matching RBRACKET.
@@ -292,8 +293,8 @@
 
 		case RBRACE:
 			if (i) {
-			    i--;
-			    break;
+				i--;
+				break;
 			}
 			/* FALLTHROUGH */
 		case COMMA:
@@ -302,13 +303,14 @@
 			else {
 				/* Append the current string */
 				for (lm = ls; (pl < pm); *lm++ = *pl++)
-					continue;
+					;
+
 				/*
 				 * Append the rest of the pattern after the
 				 * closing brace
 				 */
-				for (pl = pe + 1; (*lm++ = *pl++) != EOS;)
-					continue;
+				for (pl = pe + 1; (*lm++ = *pl++) != EOS; )
+					;
 
 				/* Expand the current pattern */
 #ifdef DEBUG
@@ -324,6 +326,7 @@
 		default:
 			break;
 		}
+	}
 	*rv = 0;
 	return 0;
 }
@@ -352,10 +355,15 @@
 	eb = &patbuf[patbuf_len - 1];
 	for (p = pattern + 1, h = (char *) patbuf;
 	    h < (char *)eb && *p && *p != SLASH; *h++ = *p++)
-		continue;
+		;
 
 	*h = EOS;
 
+#if 0
+	if (h == (char *)eb)
+		return what;
+#endif
+
 	if (((char *) patbuf)[0] == EOS) {
 		/*
 		 * handle a plain ~ or ~/ by expanding $HOME
@@ -367,8 +375,7 @@
 			else
 				h = pwd->pw_dir;
 		}
-	}
-	else {
+	} else {
 		/*
 		 * Expand a ~user
 		 */
@@ -380,11 +387,11 @@
 
 	/* Copy the home directory */
 	for (b = patbuf; b < eb && *h; *b++ = *h++)
-		continue;
+		;
 
 	/* Append the rest of the pattern */
 	while (b < eb && (*b++ = *p++) != EOS)
-		continue;
+		;
 	*b = EOS;
 
 	return patbuf;
@@ -405,10 +412,10 @@
 {
 	const Char *qpatnext;
 	int c, err, oldpathc;
-	Char *bufnext, patbuf[MAXPATHLEN+1];
+	Char *bufnext, patbuf[MAXPATHLEN];
+	size_t limit = 0;
 
-	qpatnext = globtilde(pattern, patbuf, sizeof(patbuf) / sizeof(Char),
-	    pglob);
+	qpatnext = globtilde(pattern, patbuf, MAXPATHLEN, pglob);
 	oldpathc = pglob->gl_pathc;
 	bufnext = patbuf;
 
@@ -452,7 +459,7 @@
 			 * to avoid exponential behavior
 			 */
 			if (bufnext == patbuf || bufnext[-1] != M_ALL)
-			    *bufnext++ = M_ALL;
+				*bufnext++ = M_ALL;
 			break;
 		default:
 			*bufnext++ = CHAR(c);
@@ -464,7 +471,7 @@
 	qprintf("glob0:", patbuf);
 #endif
 
-	if ((err = glob1(patbuf, pglob)) != 0)
+	if ((err = glob1(patbuf, patbuf+MAXPATHLEN-1, pglob, &limit)) != 0)
 		return(err);
 
 	/*
@@ -477,7 +484,7 @@
 		if ((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
 			return(GLOB_NOMATCH);
 	}
@@ -495,16 +502,19 @@
 }
 
 static int
-glob1(pattern, pglob)
-	Char *pattern;
+glob1(pattern, pattern_last, pglob, limitp)
+	Char *pattern, *pattern_last;
 	glob_t *pglob;
+	size_t *limitp;
 {
-	Char pathbuf[MAXPATHLEN+1];
+	Char pathbuf[MAXPATHLEN];
 
 	/* 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+MAXPATHLEN-1,
+	    pathbuf, pathbuf+MAXPATHLEN-1,
+	    pattern, pattern_last, pglob, limitp));
 }
 
 /*
@@ -513,9 +523,12 @@
  * meta characters.
  */
 static int
-glob2(pathbuf, pathend, pattern, pglob)
-	Char *pathbuf, *pathend, *pattern;
+glob2(pathbuf, pathbuf_last, pathend, pathend_last, pattern,
+    pattern_last, pglob, limitp)
+	Char *pathbuf, *pathbuf_last, *pathend, *pathend_last;
+	Char *pattern, *pattern_last;
 	glob_t *pglob;
+	size_t *limitp;
 {
 	struct stat sb;
 	Char *p, *q;
@@ -532,15 +545,17 @@
 				return(0);
 
 			if (((pglob->gl_flags & GLOB_MARK) &&
-			    pathend[-1] != SEP) && (S_ISDIR(sb.st_mode)
-			    || (S_ISLNK(sb.st_mode) &&
+			    pathend[-1] != SEP) && (S_ISDIR(sb.st_mode) ||
+			    (S_ISLNK(sb.st_mode) &&
 			    (g_stat(pathbuf, &sb, pglob) == 0) &&
 			    S_ISDIR(sb.st_mode)))) {
+				if (pathend+1 > pathend_last)
+					return (1);
 				*pathend++ = SEP;
 				*pathend = EOS;
 			}
 			++pglob->gl_matchc;
-			return(globextend(pathbuf, pglob));
+			return(globextend(pathbuf, pglob, limitp));
 		}
 
 		/* Find end of next segment, copy tentatively to pathend. */
@@ -549,24 +564,35 @@
 		while (*p != EOS && *p != SEP) {
 			if (ismeta(*p))
 				anymeta = 1;
+			if (q+1 > pathend_last)
+				return (1);
 			*q++ = *p++;
 		}
 
 		if (!anymeta) {		/* No expansion, do next segment. */
 			pathend = q;
 			pattern = p;
-			while (*pattern == SEP)
+			while (*pattern == SEP) {
+				if (pathend+1 > pathend_last)
+					return (1);
 				*pathend++ = *pattern++;
-		} else			/* Need expansion, recurse. */
-			return(glob3(pathbuf, pathend, pattern, p, pglob));
+			}
+		} else
+			/* Need expansion, recurse. */
+			return(glob3(pathbuf, pathbuf_last, pathend,
+			    pathend_last, pattern, pattern_last,
+			    p, pattern_last, pglob, limitp));
 	}
 	/* NOTREACHED */
 }
 
 static int
-glob3(pathbuf, pathend, pattern, restpattern, pglob)
-	Char *pathbuf, *pathend, *pattern, *restpattern;
+glob3(pathbuf, pathbuf_last, pathend, pathend_last, pattern, pattern_last,
+    restpattern, restpattern_last, pglob, limitp)
+	Char *pathbuf, *pathbuf_last, *pathend, *pathend_last;
+	Char *pattern, *pattern_last, *restpattern, *restpattern_last;
 	glob_t *pglob;
+	size_t *limitp;
 {
 	register struct dirent *dp;
 	DIR *dirp;
@@ -581,16 +607,19 @@
 	 */
 	struct dirent *(*readdirfunc)();
 
+	if (pathend > pathend_last)
+		return (1);
 	*pathend = EOS;
 	errno = 0;
 
 	if ((dirp = g_opendir(pathbuf, pglob)) == NULL) {
 		/* TODO: don't call for ENOENT or ENOTDIR? */
 		if (pglob->gl_errfunc) {
-			g_Ctoc(pathbuf, buf);
+			if (g_Ctoc(pathbuf, buf, sizeof(buf)))
+				return(GLOB_ABORTED);
 			if (pglob->gl_errfunc(buf, errno) ||
 			    pglob->gl_flags & GLOB_ERR)
-				return (GLOB_ABORTED);
+				return(GLOB_ABORTED);
 		}
 		return(0);
 	}
@@ -608,15 +637,23 @@
 
 		/* Initial DOT must be matched literally. */
 		if (dp->d_name[0] == DOT && *pattern != DOT)
-			continue;
-		for (sc = (u_char *) dp->d_name, dc = pathend;
-		     (*dc++ = *sc++) != EOS;)
 			continue;
+		dc = pathend;
+		sc = (u_char *) dp->d_name;
+		while (dc < pathend_last && (*dc++ = *sc++) != EOS)
+			;
+		if (dc >= pathend_last) {
+			*dc = EOS;
+			err = 1;
+			break;
+		}
+
 		if (!match(pathend, pattern, restpattern)) {
 			*pathend = EOS;
 			continue;
 		}
-		err = glob2(pathbuf, --dc, restpattern, pglob);
+		err = glob2(pathbuf, pathbuf_last, --dc, pathend_last,
+		    restpattern, restpattern_last, pglob, limitp);
 		if (err)
 			break;
 	}
@@ -644,23 +681,25 @@
  *	gl_pathv points to (gl_offs + gl_pathc + 1) items.
  */
 static int
-globextend(path, pglob)
+globextend(path, pglob, limitp)
 	const Char *path;
 	glob_t *pglob;
+	size_t *limitp;
 {
 	register char **pathv;
 	register int i;
-	u_int newsize;
+	u_int newsize, len;
 	char *copy;
 	const Char *p;
 
 	newsize = sizeof(*pathv) * (2 + pglob->gl_pathc + pglob->gl_offs);
-	pathv = pglob->gl_pathv ?
-		    realloc((char *)pglob->gl_pathv, newsize) :
-		    malloc(newsize);
+	pathv = pglob->gl_pathv ? realloc((char *)pglob->gl_pathv, newsize) :
+	    malloc(newsize);
 	if (pathv == NULL) {
-		if (pglob->gl_pathv)
+		if (pglob->gl_pathv) {
 			free(pglob->gl_pathv);
+			pglob->gl_pathv = NULL;
+		}
 		return(GLOB_NOSPACE);
 	}
 
@@ -673,12 +712,24 @@
 	pglob->gl_pathv = pathv;
 
 	for (p = path; *p++;)
-		continue;
-	if ((copy = malloc(p - path)) != NULL) {
-		g_Ctoc(path, copy);
+		;
+	len = (size_t)(p - path);
+	*limitp += len;
+	if ((copy = malloc(len)) != NULL) {
+		if (g_Ctoc(path, copy, len)) {
+			free(copy);
+			return(GLOB_NOSPACE);
+		}
 		pathv[pglob->gl_offs + pglob->gl_pathc++] = copy;
 	}
 	pathv[pglob->gl_offs + pglob->gl_pathc] = NULL;
+
+	if ((pglob->gl_flags & GLOB_LIMIT) &&
+	    newsize + *limitp >= ARG_MAX) {
+		errno = 0;
+		return(GLOB_NOSPACE);
+	}
+
 	return(copy == NULL ? GLOB_NOSPACE : 0);
 }
 
@@ -703,7 +754,8 @@
 			do
 			    if (match(name, pat, patend))
 				    return(1);
-			while (*name++ != EOS);
+			while (*name++ != EOS)
+				;
 			return(0);
 		case M_ONE:
 			if (*name++ == EOS)
@@ -748,6 +800,7 @@
 			if (*pp)
 				free(*pp);
 		free(pglob->gl_pathv);
+		pglob->gl_pathv = NULL;
 	}
 }
 
@@ -760,8 +813,10 @@
 
 	if (!*str)
 		strcpy(buf, ".");
-	else
-		g_Ctoc(str, buf);
+	else {
+		if (g_Ctoc(str, buf, sizeof(buf)))
+			return(NULL);
+	}
 
 	if (pglob->gl_flags & GLOB_ALTDIRFUNC)
 		return((*pglob->gl_opendir)(buf));
@@ -777,7 +832,8 @@
 {
 	char buf[MAXPATHLEN];
 
-	g_Ctoc(fn, buf);
+	if (g_Ctoc(fn, buf, sizeof(buf)))
+		return(-1);
 	if (pglob->gl_flags & GLOB_ALTDIRFUNC)
 		return((*pglob->gl_lstat)(buf, sb));
 	return(lstat(buf, sb));
@@ -791,7 +847,8 @@
 {
 	char buf[MAXPATHLEN];
 
-	g_Ctoc(fn, buf);
+	if (g_Ctoc(fn, buf, sizeof(buf)))
+		return(-1);
 	if (pglob->gl_flags & GLOB_ALTDIRFUNC)
 		return((*pglob->gl_stat)(buf, sb));
 	return(stat(buf, sb));
@@ -809,33 +866,18 @@
 	return (NULL);
 }
 
-#ifdef notdef
-static Char *
-g_strcat(dst, src)
-	Char *dst;
-	const Char* src;
-{
-	Char *sdst = dst;
-
-	while (*dst++)
-		continue;
-	--dst;
-	while((*dst++ = *src++) != EOS)
-	    continue;
-
-	return (sdst);
-}
-#endif
-
-static void
-g_Ctoc(str, buf)
+static int
+g_Ctoc(str, buf, len)
 	register const Char *str;
 	char *buf;
+	u_int len;
 {
-	register char *dc;
 
-	for (dc = buf; (*dc++ = *str++) != EOS;)
-		continue;
+	while (len--) {
+		if ((*buf++ = *str++) == EOS)
+			return (0);
+	}
+	return (1);
 }
 
 #ifdef DEBUG

