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