Author: ache
Date: Thu Jul 21 12:53:36 2016
New Revision: 303142
URL: https://svnweb.freebsd.org/changeset/base/303142

Log:
  1) GLOB_BRACE was somewhat broken. First it repeatedly calls glob0() in
  globexp1() recursive calls, but glob0() was not supposed to be called
  repeatedly in the original code. It finalize results by possible adding
  original pattern for no match case, may return GLOB_NOMATCH error and
  by sorting all things. Original pattern adding or GLOB_NOMATCH error
  can happens each time glob0() called repeatedly, and sorting happens
  for one item only, all things are never sorted. Second, f.e. "a{a"
  pattern does not match "a{a" file but match "a" file instead
  (just one example, there are many). Third, some errors (f.e. for limits
  or overflow) can be ignored by GLOB_BRACE code because it forces return (0).
  Add non-finalizing flag to glob0() and make globexp0() wrapper around
  recursively called globexp1() to finalize things like glob0() does.
  Reorganize braces code to work correctly.
  
  2) Don't allow MB_CUR_MAX * strlen overallocation hits GLOB_LIMIT_STRING
  (ARG_MAX) limit, use final string length, not malloced space for it.
  
  3) Revive DEBUG-ifdefed section.

Modified:
  head/lib/libc/gen/glob.c

Modified: head/lib/libc/gen/glob.c
==============================================================================
--- head/lib/libc/gen/glob.c    Thu Jul 21 12:50:23 2016        (r303141)
+++ head/lib/libc/gen/glob.c    Thu Jul 21 12:53:36 2016        (r303142)
@@ -128,8 +128,6 @@ struct glob_limit {
 #define        RBRACE          L'}'
 #define        COMMA           L','
 
-#ifndef DEBUG
-
 #define        M_QUOTE         0x8000000000ULL
 #define        M_PROTECT       0x4000000000ULL
 #define        M_MASK          0xffffffffffULL
@@ -137,18 +135,6 @@ struct glob_limit {
 
 typedef uint_fast64_t Char;
 
-#else
-
-#define        M_QUOTE         0x80
-#define        M_PROTECT       0x40
-#define        M_MASK          0xff
-#define        M_CHAR          0x7f
-
-typedef char Char;
-
-#endif
-
-
 #define        CHAR(c)         ((Char)((c)&M_CHAR))
 #define        META(c)         ((Char)((c)|M_QUOTE))
 #define        UNPROT(c)       ((c) & ~M_PROTECT)
@@ -171,7 +157,7 @@ static const Char *g_strchr(const Char *
 static Char    *g_strcat(Char *, const Char *);
 #endif
 static int      g_stat(Char *, struct stat *, glob_t *);
-static int      glob0(const Char *, glob_t *, struct glob_limit *);
+static int      glob0(const Char *, glob_t *, struct glob_limit *, int);
 static int      glob1(Char *, glob_t *, struct glob_limit *);
 static int      glob2(Char *, Char *, Char *, Char *, glob_t *,
     struct glob_limit *);
@@ -180,8 +166,9 @@ static int   glob3(Char *, Char *, Char *
 static int      globextend(const Char *, glob_t *, struct glob_limit *, int);
 static const Char *
                 globtilde(const Char *, Char *, size_t, glob_t *);
+static int      globexp0(const Char *, glob_t *, struct glob_limit *);
 static int      globexp1(const Char *, glob_t *, struct glob_limit *);
-static int      globexp2(const Char *, const Char *, glob_t *, int *,
+static int      globexp2(const Char *, const Char *, glob_t *,
     struct glob_limit *);
 static int      match(Char *, Char *, Char *);
 #ifdef DEBUG
@@ -260,9 +247,49 @@ glob(const char * __restrict pattern, in
        *bufnext = EOS;
 
        if (flags & GLOB_BRACE)
-           return (globexp1(patbuf, pglob, &limit));
+           return (globexp0(patbuf, pglob, &limit));
        else
-           return (glob0(patbuf, pglob, &limit));
+           return (glob0(patbuf, pglob, &limit, 1));
+}
+
+static int
+globexp0(const Char *pattern, glob_t *pglob, struct glob_limit *limit)
+{
+       int rv;
+       size_t oldpathc;
+
+       /* Protect a single {}, for find(1), like csh */
+       if (pattern[0] == LBRACE && pattern[1] == RBRACE && pattern[2] == EOS) {
+               if ((pglob->gl_flags & GLOB_LIMIT) &&
+                   limit->l_brace_cnt++ >= GLOB_LIMIT_BRACE) {
+                       errno = 0;
+                       return (GLOB_NOSPACE);
+               }
+               return (glob0(pattern, pglob, limit, 1));
+       }
+
+       oldpathc = pglob->gl_pathc;
+
+       if ((rv = globexp1(pattern, pglob, limit)) != 0)
+               return rv;
+       /*
+        * If there was no match we are going to append the pattern
+        * if GLOB_NOCHECK was specified or if GLOB_NOMAGIC was specified
+        * and the pattern did not contain any magic characters
+        * GLOB_NOMAGIC is there just for compatibility with csh.
+        */
+       if (pglob->gl_pathc == oldpathc) {
+               if (((pglob->gl_flags & GLOB_NOCHECK) ||
+                   ((pglob->gl_flags & GLOB_NOMAGIC) &&
+                       !(pglob->gl_flags & GLOB_MAGCHAR))))
+                       return (globextend(pattern, pglob, limit, 1));
+               else
+                       return (GLOB_NOMATCH);
+       }
+       if (!(pglob->gl_flags & GLOB_NOSORT))
+               qsort(pglob->gl_pathv + pglob->gl_offs + oldpathc,
+                   pglob->gl_pathc - oldpathc, sizeof(char *), compare);
+       return (0);
 }
 
 /*
@@ -273,24 +300,18 @@ glob(const char * __restrict pattern, in
 static int
 globexp1(const Char *pattern, glob_t *pglob, struct glob_limit *limit)
 {
-       const Char* ptr = pattern;
-       int rv;
+       const Char* ptr;
 
-       if ((pglob->gl_flags & GLOB_LIMIT) &&
-           limit->l_brace_cnt++ >= GLOB_LIMIT_BRACE) {
-               errno = 0;
-               return (GLOB_NOSPACE);
+       if ((ptr = g_strchr(pattern, LBRACE)) != NULL) {
+               if ((pglob->gl_flags & GLOB_LIMIT) &&
+                   limit->l_brace_cnt++ >= GLOB_LIMIT_BRACE) {
+                       errno = 0;
+                       return (GLOB_NOSPACE);
+               }
+               return (globexp2(ptr, pattern, pglob, limit));
        }
 
-       /* Protect a single {}, for find(1), like csh */
-       if (pattern[0] == LBRACE && pattern[1] == RBRACE && pattern[2] == EOS)
-               return glob0(pattern, pglob, limit);
-
-       while ((ptr = g_strchr(ptr, LBRACE)) != NULL)
-               if (!globexp2(ptr, pattern, pglob, &rv, limit))
-                       return rv;
-
-       return glob0(pattern, pglob, limit);
+       return (glob0(pattern, pglob, limit, 0));
 }
 
 
@@ -300,10 +321,10 @@ 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,
     struct glob_limit *limit)
 {
-       int     i;
+       int     i, rv;
        Char   *lm, *ls;
        const Char *pe, *pm, *pm1, *pl;
        Char    patbuf[MAXPATHLEN];
@@ -315,7 +336,7 @@ globexp2(const Char *ptr, const Char *pa
        ls = lm;
 
        /* Find the balanced brace */
-       for (i = 0, pe = ++ptr; *pe; pe++)
+       for (i = 0, pe = ++ptr; *pe != EOS; pe++)
                if (*pe == LBRACKET) {
                        /* Ignore everything between [] */
                        for (pm = pe++; *pe != RBRACKET && *pe != EOS; pe++)
@@ -337,10 +358,8 @@ globexp2(const Char *ptr, const Char *pa
                }
 
        /* Non matching braces; just glob the pattern */
-       if (i != 0 || *pe == EOS) {
-               *rv = glob0(patbuf, pglob, limit);
-               return (0);
-       }
+       if (i != 0 || *pe == EOS)
+               return (glob0(pattern, pglob, limit, 0));
 
        for (i = 0, pl = pm = ptr; pm <= pe; pm++)
                switch (*pm) {
@@ -385,7 +404,9 @@ globexp2(const Char *ptr, const Char *pa
 #ifdef DEBUG
                                qprintf("globexp2:", patbuf);
 #endif
-                               *rv = globexp1(patbuf, pglob, limit);
+                               rv = globexp1(patbuf, pglob, limit);
+                               if (rv)
+                                       return (rv);
 
                                /* move after the comma, to the next string */
                                pl = pm + 1;
@@ -395,7 +416,6 @@ globexp2(const Char *ptr, const Char *pa
                default:
                        break;
                }
-       *rv = 0;
        return (0);
 }
 
@@ -517,7 +537,8 @@ globtilde(const Char *pattern, Char *pat
  * if things went well, nonzero if errors occurred.
  */
 static int
-glob0(const Char *pattern, glob_t *pglob, struct glob_limit *limit)
+glob0(const Char *pattern, glob_t *pglob, struct glob_limit *limit,
+    int final)
 {
        const Char *qpatnext;
        int err;
@@ -587,23 +608,25 @@ glob0(const Char *pattern, glob_t *pglob
        if ((err = glob1(patbuf, pglob, limit)) != 0)
                return(err);
 
-       /*
-        * If there was no match we are going to append the pattern
-        * if GLOB_NOCHECK was specified or if GLOB_NOMAGIC was specified
-        * and the pattern did not contain any magic characters
-        * GLOB_NOMAGIC is there just for compatibility with csh.
-        */
-       if (pglob->gl_pathc == oldpathc) {
-               if (((pglob->gl_flags & GLOB_NOCHECK) ||
-                   ((pglob->gl_flags & GLOB_NOMAGIC) &&
-                       !(pglob->gl_flags & GLOB_MAGCHAR))))
-                       return (globextend(pattern, pglob, limit, 1));
-               else
-                       return (GLOB_NOMATCH);
+       if (final) {
+               /*
+                * If there was no match we are going to append the pattern
+                * if GLOB_NOCHECK was specified or if GLOB_NOMAGIC was 
specified
+                * and the pattern did not contain any magic characters
+                * GLOB_NOMAGIC is there just for compatibility with csh.
+                */
+               if (pglob->gl_pathc == oldpathc) {
+                       if (((pglob->gl_flags & GLOB_NOCHECK) ||
+                           ((pglob->gl_flags & GLOB_NOMAGIC) &&
+                               !(pglob->gl_flags & GLOB_MAGCHAR))))
+                               return (globextend(pattern, pglob, limit, 1));
+                       else
+                               return (GLOB_NOMATCH);
+               }
+               if (!(pglob->gl_flags & GLOB_NOSORT))
+                       qsort(pglob->gl_pathv + pglob->gl_offs + oldpathc,
+                           pglob->gl_pathc - oldpathc, sizeof(char *), 
compare);
        }
-       if (!(pglob->gl_flags & GLOB_NOSORT))
-               qsort(pglob->gl_pathv + pglob->gl_offs + oldpathc,
-                   pglob->gl_pathc - oldpathc, sizeof(char *), compare);
        return (0);
 }
 
@@ -856,18 +879,19 @@ globextend(const Char *path, glob_t *pgl
        len = MB_CUR_MAX * (size_t)(p - path);  /* XXX overallocation */
        if (prot)
                len += (size_t)(p - path) - 1;
-       limit->l_string_cnt += len;
-       if ((pglob->gl_flags & GLOB_LIMIT) &&
-           limit->l_string_cnt >= GLOB_LIMIT_STRING) {
-               errno = 0;
-               return (GLOB_NOSPACE);
-       }
        if ((copy = malloc(len)) != NULL) {
                if (g_Ctoc(path, copy, len, prot)) {
                        free(copy);
                        errno = 0;
                        return (GLOB_NOSPACE);
                }
+               limit->l_string_cnt += strlen(copy) + 1;
+               if ((pglob->gl_flags & GLOB_LIMIT) &&
+                   limit->l_string_cnt >= GLOB_LIMIT_STRING) {
+                       free(copy);
+                       errno = 0;
+                       return (GLOB_NOSPACE);
+               }
                pathv[pglob->gl_offs + pglob->gl_pathc++] = copy;
        }
        pathv[pglob->gl_offs + pglob->gl_pathc] = NULL;
@@ -1046,15 +1070,17 @@ qprintf(const char *str, Char *s)
 {
        Char *p;
 
-       (void)printf("%s:\n", str);
-       for (p = s; *p; p++)
-               (void)printf("%c", CHAR(*p));
-       (void)printf("\n");
-       for (p = s; *p; p++)
-               (void)printf("%c", *p & M_PROTECT ? '"' : ' ');
-       (void)printf("\n");
-       for (p = s; *p; p++)
-               (void)printf("%c", ismeta(*p) ? '_' : ' ');
-       (void)printf("\n");
+       (void)printf("%s\n", str);
+       if (s != NULL) {
+               for (p = s; *p != EOS; p++)
+                       (void)printf("%c", (char)CHAR(*p));
+               (void)printf("\n");
+               for (p = s; *p != EOS; p++)
+                       (void)printf("%c", (isprot(*p) ? '\\' : ' '));
+               (void)printf("\n");
+               for (p = s; *p != EOS; p++)
+                       (void)printf("%c", (ismeta(*p) ? '_' : ' '));
+               (void)printf("\n");
+       }
 }
 #endif
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to