Hi,

attached is a patch (based on the one of NetBSD) which fixes the glob
issue.  Please test the patch to be sure that everything works (it
should be).

The patch is also available here:

http://leaf.dragonflybsd.org/~matthias/libc_glob_flaw.diff

Cheers

        Matthias
diff --git a/lib/libc/gen/glob.c b/lib/libc/gen/glob.c
index 0f25c58..9a88a47 100644
--- a/lib/libc/gen/glob.c
+++ b/lib/libc/gen/glob.c
@@ -137,6 +137,14 @@ typedef char Char;
 #define        ismeta(c)       (((c)&M_QUOTE) != 0)
 
 
+#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
+
 static int      compare(const void *, const void *);
 static int      g_Ctoc(const Char *, char *, size_t);
 static int      g_lstat(const Char *, struct stat *, glob_t *);
@@ -162,6 +170,9 @@ static int   match(const Char *, const Char *, const Char 
*);
 static void     qprintf(const char *, const Char *);
 #endif
 
+/* 0 = malloc(), 1 = stat(), 2 = readdir() */
+static size_t limits[] = { 0, 0, 0 };
+
 int
 glob(const char *pattern, int flags, int (*errfunc)(const char *, int),
      glob_t *pglob)
@@ -560,6 +571,14 @@ glob2(Char *pathbuf, Char *pathend, Char *pathend_last, 
const Char *pattern,
                        if (g_lstat(pathbuf, &sb, pglob))
                                return(0);
 
+                       if ((pglob->gl_flags & GLOB_LIMIT) &&
+                           limits[GLOB_INDEX_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) &&
@@ -643,6 +662,14 @@ glob3(Char *pathbuf, Char *pathend, Char *pathend_last, 
const Char *pattern,
                size_t clen;
                mbstate_t mbs;
 
+               if ((pglob->gl_flags & GLOB_LIMIT) &&
+                   limits[GLOB_INDEX_READDIR]++ >= GLOB_LIMIT_READDIR) {
+                       errno = 0;
+                       *pathend++ = SEP;
+                       *pathend = EOS;
+                       return GLOB_NOSPACE;
+               }
+
                /* Initial DOT must be matched literally. */
                if (dp->d_name[0] == DOT && *pattern != DOT &&
                    !(pglob->gl_flags & GLOB_PERIOD))
@@ -729,6 +756,7 @@ globextend(const Char *path, glob_t *pglob, size_t *limit)
        for (p = path; *p++;)
                continue;
        len = MB_CUR_MAX * (size_t)(p - path);  /* XXX overallocation */
+       limits[GLOB_INDEX_MALLOC] += len;
        if ((copy = malloc(len)) != NULL) {
                if (g_Ctoc(path, copy, len)) {
                        free(copy);
@@ -737,6 +765,12 @@ globextend(const Char *path, glob_t *pglob, size_t *limit)
                pathv[pglob->gl_offs + pglob->gl_pathc++] = copy;
        }
        pathv[pglob->gl_offs + pglob->gl_pathc] = NULL;
+       if ((pglob->gl_flags & GLOB_LIMIT) &&
+               (newsize + limits[GLOB_INDEX_MALLOC]) >= GLOB_LIMIT_MALLOC) {
+               errno = 0;
+               return GLOB_NOSPACE;
+       }
+
        return(copy == NULL ? GLOB_NOSPACE : 0);
 }
 

Reply via email to