Smack: add the execute lable to ldconfig
[platform/upstream/glibc.git] / posix / glob.c
index 2cd5290..5b92776 100644 (file)
@@ -1,5 +1,4 @@
-/* Copyright (C) 1991-2002, 2003, 2004, 2005, 2006, 2007, 2008, 2010, 2011
-   Free Software Foundation, Inc.
+/* Copyright (C) 1991-2015 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -13,9 +12,8 @@
    Lesser General Public License for more details.
 
    You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, write to the Free
-   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-   02111-1307 USA.  */
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
 
 #ifdef HAVE_CONFIG_H
 # include <config.h>
 
 #include <pwd.h>
 
+#if defined HAVE_STDINT_H || defined _LIBC
+# include <stdint.h>
+#elif !defined UINTPTR_MAX
+# define UINTPTR_MAX (~((size_t) 0))
+#endif
+
 #include <errno.h>
 #ifndef __set_errno
 # define __set_errno(val) errno = (val)
 # define GET_LOGIN_NAME_MAX()  (-1)
 #endif
 \f
-static const char *next_brace_sub (const char *begin, int flags) __THROW;
+static const char *next_brace_sub (const char *begin, int flags) __THROWNL;
 
 #endif /* !defined _LIBC || !defined GLOB_ONLY_P */
 
@@ -204,15 +208,15 @@ extern int __glob_pattern_type (const char *pattern, int quote)
     attribute_hidden;
 
 #if !defined _LIBC || !defined GLOB_ONLY_P
-static int prefix_array (const char *prefix, char **array, size_t n) __THROW;
-static int collated_compare (const void *, const void *) __THROW;
+static int prefix_array (const char *prefix, char **array, size_t n) __THROWNL;
+static int collated_compare (const void *, const void *) __THROWNL;
 
 
 /* Find the end of the sub-pattern in a brace expression.  */
 static const char *
 next_brace_sub (const char *cp, int flags)
 {
-  unsigned int depth = 0;
+  size_t depth = 0;
   while (*cp != '\0')
     if ((flags & GLOB_NOESCAPE) == 0 && *cp == '\\')
       {
@@ -272,6 +276,11 @@ glob (pattern, flags, errfunc, pglob)
       return -1;
     }
 
+  /* POSIX requires all slashes to be matched.  This means that with
+     a trailing slash we must match only directories.  */
+  if (pattern[0] && pattern[strlen (pattern) - 1] == '/')
+    flags |= GLOB_ONLYDIR;
+
   if (!(flags & GLOB_DOOFFS))
     /* Have to do this so `globfree' knows where to start freeing.  It
        also makes all the code that uses gl_offs simpler. */
@@ -345,7 +354,7 @@ glob (pattern, flags, errfunc, pglob)
              /* It is an illegal expression.  */
            illegal_brace:
 #ifdef _LIBC
-             if (__builtin_expect (!alloca_onealt, 0))
+             if (__glibc_unlikely (!alloca_onealt))
 #endif
                free (onealt);
              return glob (pattern, flags & ~GLOB_BRACE, errfunc, pglob);
@@ -395,7 +404,7 @@ glob (pattern, flags, errfunc, pglob)
              if (result && result != GLOB_NOMATCH)
                {
 #ifdef _LIBC
-                 if (__builtin_expect (!alloca_onealt, 0))
+                 if (__glibc_unlikely (!alloca_onealt))
 #endif
                    free (onealt);
                  if (!(flags & GLOB_APPEND))
@@ -416,7 +425,7 @@ glob (pattern, flags, errfunc, pglob)
            }
 
 #ifdef _LIBC
-         if (__builtin_expect (!alloca_onealt, 0))
+         if (__glibc_unlikely (!alloca_onealt))
 #endif
            free (onealt);
 
@@ -436,6 +445,10 @@ glob (pattern, flags, errfunc, pglob)
       else
        {
          size_t i;
+
+         if (pglob->gl_offs >= ~((size_t) 0) / sizeof (char *))
+           return GLOB_NOSPACE;
+
          pglob->gl_pathv = (char **) malloc ((pglob->gl_offs + 1)
                                              * sizeof (char *));
          if (pglob->gl_pathv == NULL)
@@ -475,7 +488,7 @@ glob (pattern, flags, errfunc, pglob)
        }
       else
        {
-         if (__builtin_expect (pattern[0] == '\0', 0))
+         if (__glibc_unlikely (pattern[0] == '\0'))
            {
              dirs.gl_pathv = NULL;
              goto no_matches;
@@ -658,7 +671,7 @@ glob (pattern, flags, errfunc, pglob)
                                                2 * pwbuflen);
                          if (newp == NULL)
                            {
-                             if (__builtin_expect (malloc_pwtmpbuf, 0))
+                             if (__glibc_unlikely (malloc_pwtmpbuf))
                                free (pwtmpbuf);
                              retval = GLOB_NOSPACE;
                              goto out;
@@ -704,7 +717,7 @@ glob (pattern, flags, errfunc, pglob)
            {
              if (flags & GLOB_TILDE_CHECK)
                {
-                 if (__builtin_expect (malloc_home_dir, 0))
+                 if (__glibc_unlikely (malloc_home_dir))
                    free (home_dir);
                  retval = GLOB_NOMATCH;
                  goto out;
@@ -717,7 +730,7 @@ glob (pattern, flags, errfunc, pglob)
          /* Now construct the full directory.  */
          if (dirname[1] == '\0')
            {
-             if (__builtin_expect (malloc_dirname, 0))
+             if (__glibc_unlikely (malloc_dirname))
                free (dirname);
 
              dirname = home_dir;
@@ -737,7 +750,7 @@ glob (pattern, flags, errfunc, pglob)
                  newp = malloc (home_len + dirlen);
                  if (newp == NULL)
                    {
-                     if (__builtin_expect (malloc_home_dir, 0))
+                     if (__glibc_unlikely (malloc_home_dir))
                        free (home_dir);
                      retval = GLOB_NOSPACE;
                      goto out;
@@ -747,7 +760,7 @@ glob (pattern, flags, errfunc, pglob)
              mempcpy (mempcpy (newp, home_dir, home_len),
                       &dirname[1], dirlen);
 
-             if (__builtin_expect (malloc_dirname, 0))
+             if (__glibc_unlikely (malloc_dirname))
                free (dirname);
 
              dirname = newp;
@@ -846,7 +859,7 @@ glob (pattern, flags, errfunc, pglob)
                if (pwtmpbuf == NULL)
                  {
                  nomem_getpw:
-                   if (__builtin_expect (malloc_user_name, 0))
+                   if (__glibc_unlikely (malloc_user_name))
                      free (user_name);
                    retval = GLOB_NOSPACE;
                    goto out;
@@ -871,7 +884,7 @@ glob (pattern, flags, errfunc, pglob)
                                          2 * buflen);
                    if (newp == NULL)
                      {
-                       if (__builtin_expect (malloc_pwtmpbuf, 0))
+                       if (__glibc_unlikely (malloc_pwtmpbuf))
                          free (pwtmpbuf);
                        goto nomem_getpw;
                      }
@@ -884,7 +897,7 @@ glob (pattern, flags, errfunc, pglob)
            p = getpwnam (user_name);
 #  endif
 
-           if (__builtin_expect (malloc_user_name, 0))
+           if (__glibc_unlikely (malloc_user_name))
              free (user_name);
 
            /* If we found a home directory use this.  */
@@ -893,7 +906,7 @@ glob (pattern, flags, errfunc, pglob)
                size_t home_len = strlen (p->pw_dir);
                size_t rest_len = end_name == NULL ? 0 : strlen (end_name);
 
-               if (__builtin_expect (malloc_dirname, 0))
+               if (__glibc_unlikely (malloc_dirname))
                  free (dirname);
                malloc_dirname = 0;
 
@@ -905,7 +918,7 @@ glob (pattern, flags, errfunc, pglob)
                    dirname = malloc (home_len + rest_len + 1);
                    if (dirname == NULL)
                      {
-                       if (__builtin_expect (malloc_pwtmpbuf, 0))
+                       if (__glibc_unlikely (malloc_pwtmpbuf))
                          free (pwtmpbuf);
                        retval = GLOB_NOSPACE;
                        goto out;
@@ -918,12 +931,12 @@ glob (pattern, flags, errfunc, pglob)
                dirlen = home_len + rest_len;
                dirname_modified = 1;
 
-               if (__builtin_expect (malloc_pwtmpbuf, 0))
+               if (__glibc_unlikely (malloc_pwtmpbuf))
                  free (pwtmpbuf);
              }
            else
              {
-               if (__builtin_expect (malloc_pwtmpbuf, 0))
+               if (__glibc_unlikely (malloc_pwtmpbuf))
                  free (pwtmpbuf);
 
                if (flags & GLOB_TILDE_CHECK)
@@ -951,13 +964,11 @@ glob (pattern, flags, errfunc, pglob)
                  && S_ISDIR (st.st_mode))
               : (__stat64 (dirname, &st64) == 0 && S_ISDIR (st64.st_mode)))))
        {
-         int newcount = pglob->gl_pathc + pglob->gl_offs;
+         size_t newcount = pglob->gl_pathc + pglob->gl_offs;
          char **new_gl_pathv;
 
-         new_gl_pathv
-           = (char **) realloc (pglob->gl_pathv,
-                                (newcount + 1 + 1) * sizeof (char *));
-         if (new_gl_pathv == NULL)
+         if (newcount > UINTPTR_MAX - (1 + 1)
+             || newcount + 1 + 1 > ~((size_t) 0) / sizeof (char *))
            {
            nospace:
              free (pglob->gl_pathv);
@@ -965,6 +976,12 @@ glob (pattern, flags, errfunc, pglob)
              pglob->gl_pathc = 0;
              return GLOB_NOSPACE;
            }
+
+         new_gl_pathv
+           = (char **) realloc (pglob->gl_pathv,
+                                (newcount + 1 + 1) * sizeof (char *));
+         if (new_gl_pathv == NULL)
+           goto nospace;
          pglob->gl_pathv = new_gl_pathv;
 
          if (flags & GLOB_MARK)
@@ -1018,7 +1035,7 @@ glob (pattern, flags, errfunc, pglob)
            *(char *) &dirname[--dirlen] = '\0';
        }
 
-      if (__builtin_expect ((flags & GLOB_ALTDIRFUNC) != 0, 0))
+      if (__glibc_unlikely ((flags & GLOB_ALTDIRFUNC) != 0))
        {
          /* Use the alternative access functions also in the recursive
             call.  */
@@ -1046,7 +1063,7 @@ glob (pattern, flags, errfunc, pglob)
         appending the results to PGLOB.  */
       for (i = 0; i < dirs.gl_pathc; ++i)
        {
-         int old_pathc;
+         size_t old_pathc;
 
 #ifdef SHELL
          {
@@ -1101,17 +1118,22 @@ glob (pattern, flags, errfunc, pglob)
          /* No matches.  */
          if (flags & GLOB_NOCHECK)
            {
-             int newcount = pglob->gl_pathc + pglob->gl_offs;
+             size_t newcount = pglob->gl_pathc + pglob->gl_offs;
              char **new_gl_pathv;
 
-             new_gl_pathv = (char **) realloc (pglob->gl_pathv,
-                                               (newcount + 2)
-                                               * sizeof (char *));
-             if (new_gl_pathv == NULL)
+             if (newcount > UINTPTR_MAX - 2
+                 || newcount + 2 > ~((size_t) 0) / sizeof (char *))
                {
+               nospace2:
                  globfree (&dirs);
                  return GLOB_NOSPACE;
                }
+
+             new_gl_pathv = (char **) realloc (pglob->gl_pathv,
+                                               (newcount + 2)
+                                               * sizeof (char *));
+             if (new_gl_pathv == NULL)
+               goto nospace2;
              pglob->gl_pathv = new_gl_pathv;
 
              pglob->gl_pathv[newcount] = __strdup (pattern);
@@ -1140,7 +1162,7 @@ glob (pattern, flags, errfunc, pglob)
     }
   else
     {
-      int old_pathc = pglob->gl_pathc;
+      size_t old_pathc = pglob->gl_pathc;
       int orig_flags = flags;
 
       if (meta & 2)
@@ -1231,7 +1253,7 @@ glob (pattern, flags, errfunc, pglob)
     }
 
  out:
-  if (__builtin_expect (malloc_dirname, 0))
+  if (__glibc_unlikely (malloc_dirname))
     free (dirname);
 
   return retval;
@@ -1246,7 +1268,7 @@ libc_hidden_def (glob)
 /* Free storage allocated in PGLOB by a previous `glob' call.  */
 void
 globfree (pglob)
-     register glob_t *pglob;
+     glob_t *pglob;
 {
   if (pglob->gl_pathv != NULL)
     {
@@ -1286,7 +1308,7 @@ collated_compare (const void *a, const void *b)
 static int
 prefix_array (const char *dirname, char **array, size_t n)
 {
-  register size_t i;
+  size_t i;
   size_t dirlen = strlen (dirname);
 #if defined __MSDOS__ || defined WINDOWS32
   int sep_char = '/';
@@ -1345,7 +1367,7 @@ __glob_pattern_type (pattern, quote)
      const char *pattern;
      int quote;
 {
-  register const char *p;
+  const char *p;
   int ret = 0;
 
   for (p = pattern; *p != '\0'; ++p)
@@ -1508,7 +1530,7 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
           of the function to copy this name into the result.  */
        flags |= GLOB_NOCHECK;
 
-      if (__builtin_expect (!alloca_fullname, 0))
+      if (__glibc_unlikely (!alloca_fullname))
        free (fullname);
     }
   else
@@ -1551,7 +1573,7 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
                }
              d64buf;
 
-             if (__builtin_expect (flags & GLOB_ALTDIRFUNC, 0))
+             if (__glibc_unlikely (flags & GLOB_ALTDIRFUNC))
                {
                  struct dirent *d32 = (*pglob->gl_readdir) (stream);
                  if (d32 != NULL)
@@ -1636,6 +1658,13 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
     {
       result = 0;
 
+      if (pglob->gl_pathc > UINTPTR_MAX - pglob->gl_offs
+         || pglob->gl_pathc + pglob->gl_offs > UINTPTR_MAX - nfound
+         || pglob->gl_pathc + pglob->gl_offs + nfound > UINTPTR_MAX - 1
+         || (pglob->gl_pathc + pglob->gl_offs + nfound + 1
+             > UINTPTR_MAX / sizeof (char *)))
+       goto memory_error;
+
       char **new_gl_pathv;
       new_gl_pathv
        = (char **) realloc (pglob->gl_pathv,
@@ -1703,7 +1732,7 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
   if (stream != NULL)
     {
       save = errno;
-      if (__builtin_expect (flags & GLOB_ALTDIRFUNC, 0))
+      if (__glibc_unlikely (flags & GLOB_ALTDIRFUNC))
        (*pglob->gl_closedir) (stream);
       else
        closedir (stream);