]> sourceware.org Git - glibc.git/commitdiff
posix: Fix getpwnam_r usage (BZ #1062)
authorAdhemerval Zanella <adhemerval.zanella@linaro.org>
Mon, 4 Sep 2017 20:00:03 +0000 (17:00 -0300)
committerAdhemerval Zanella <adhemerval.zanella@linaro.org>
Fri, 8 Sep 2017 13:51:34 +0000 (15:51 +0200)
This patch fixes longstanding misuse of errno after getpwnam_r,
which returns an error number rather than setting errno.  This is
sync with gnulib commit 5db9301.

Checked on x86_64-linux-gnu and on a build using build-many-glibcs.py
for all major architectures.

[BZ #1062]
* posix/glob.c (glob): Port recent patches to platforms
lacking getpwnam_r.
(glob): Fix longstanding misuse of errno after getpwnam_r, which
returns an error number rather than setting errno.

ChangeLog
posix/glob.c

index c8d46e9954603c16f900bf8871f73a7a4bef3f5a..39d1235c744faba48974e5918f8753ad44d47726 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
 2017-09-08  Adhemerval Zanella  <adhemerval.zanella@linaro.org>
 
+       [BZ #1062]
+       * posix/glob.c (glob): Port recent patches to platforms
+       lacking getpwnam_r.
+       (glob): Fix longstanding misuse of errno after getpwnam_r, which
+       returns an error number rather than setting errno.
+
        * include/scratch_buffer.h (scratch_buffer): Use a C99 align method
        instead of GCC extension.
        * malloc/scratch_buffer_grow.c [!_LIBC]: Include libc-config.h.
index 29e894819f7a0d5c2729edf8cbbb027e1a883824..ef620a1f0ae1f168f63968af7747b9bf2c584fb3 100644 (file)
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
-#ifndef _LIBC
-# include <config.h>
-#endif
-
 #include <glob.h>
 
 #include <errno.h>
 #endif
 
 #include <errno.h>
-#ifndef __set_errno
-# define __set_errno(val) errno = (val)
-#endif
-
 #include <dirent.h>
 #include <stdlib.h>
 #include <string.h>
 
 #include <flexmember.h>
 #include <glob_internal.h>
+#include <scratch_buffer.h>
 
-#ifdef _SC_GETPW_R_SIZE_MAX
-# define GETPW_R_SIZE_MAX()    sysconf (_SC_GETPW_R_SIZE_MAX)
-#else
-# define GETPW_R_SIZE_MAX()    (-1)
-#endif
 #ifdef _SC_LOGIN_NAME_MAX
 # define GET_LOGIN_NAME_MAX()  sysconf (_SC_LOGIN_NAME_MAX)
 #else
@@ -648,97 +636,36 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
              if (success)
                {
                  struct passwd *p;
-                 char *malloc_pwtmpbuf = NULL;
-                 char *pwtmpbuf;
+                 struct scratch_buffer pwtmpbuf;
+                 scratch_buffer_init (&pwtmpbuf);
 # if defined HAVE_GETPWNAM_R || defined _LIBC
-                 long int pwbuflenmax = GETPW_R_SIZE_MAX ();
-                 size_t pwbuflen = pwbuflenmax;
                  struct passwd pwbuf;
-                 int save = errno;
 
-#  ifndef _LIBC
-                 if (! (0 < pwbuflenmax && pwbuflenmax <= SIZE_MAX))
-                   /* 'sysconf' does not support _SC_GETPW_R_SIZE_MAX.
-                      Try a moderate value.  */
-                   pwbuflen = 1024;
-#  endif
-                 if (glob_use_alloca (alloca_used, pwbuflen))
-                   pwtmpbuf = alloca_account (pwbuflen, alloca_used);
-                 else
+                 while (getpwnam_r (name, &pwbuf,
+                                    pwtmpbuf.data, pwtmpbuf.length, &p)
+                        == ERANGE)
                    {
-                     pwtmpbuf = malloc (pwbuflen);
-                     if (pwtmpbuf == NULL)
+                     if (!scratch_buffer_grow (&pwtmpbuf))
                        {
-                         if (__glibc_unlikely (malloc_name))
-                           free (name);
                          retval = GLOB_NOSPACE;
                          goto out;
                        }
-                     malloc_pwtmpbuf = pwtmpbuf;
-                   }
-
-                 while (getpwnam_r (name, &pwbuf, pwtmpbuf, pwbuflen, &p)
-                        != 0)
-                   {
-                     size_t newlen;
-                     bool v;
-                     if (errno != ERANGE)
-                       {
-                         p = NULL;
-                         break;
-                       }
-                     v = size_add_wrapv (pwbuflen, pwbuflen, &newlen);
-                     if (!v && malloc_pwtmpbuf == NULL
-                         && glob_use_alloca (alloca_used, newlen))
-                       pwtmpbuf = extend_alloca_account (pwtmpbuf, pwbuflen,
-                                                         newlen, alloca_used);
-                     else
-                       {
-                         char *newp = (v ? NULL
-                                       : realloc (malloc_pwtmpbuf, newlen));
-                         if (newp == NULL)
-                           {
-                             free (malloc_pwtmpbuf);
-                             if (__glibc_unlikely (malloc_name))
-                               free (name);
-                             retval = GLOB_NOSPACE;
-                             goto out;
-                           }
-                         malloc_pwtmpbuf = pwtmpbuf = newp;
-                       }
-                     pwbuflen = newlen;
-                     __set_errno (save);
                    }
 # else
                  p = getpwnam (name);
 # endif
-                 if (__glibc_unlikely (malloc_name))
-                   free (name);
                  if (p != NULL)
                    {
-                     if (malloc_pwtmpbuf == NULL)
-                       home_dir = p->pw_dir;
-                     else
+                     home_dir = strdup (p->pw_dir);
+                     malloc_home_dir = 1;
+                     if (home_dir == NULL)
                        {
-                         size_t home_dir_len = strlen (p->pw_dir) + 1;
-                         if (glob_use_alloca (alloca_used, home_dir_len))
-                           home_dir = alloca_account (home_dir_len,
-                                                      alloca_used);
-                         else
-                           {
-                             home_dir = malloc (home_dir_len);
-                             if (home_dir == NULL)
-                               {
-                                 free (pwtmpbuf);
-                                 retval = GLOB_NOSPACE;
-                                 goto out;
-                               }
-                             malloc_home_dir = 1;
-                           }
-                         memcpy (home_dir, p->pw_dir, home_dir_len);
+                         scratch_buffer_free (&pwtmpbuf);
+                         retval = GLOB_NOSPACE;
+                         goto out;
                        }
                    }
-                 free (malloc_pwtmpbuf);
+                 scratch_buffer_free (&pwtmpbuf);
                }
              else
                {
@@ -875,61 +802,21 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
          /* Look up specific user's home directory.  */
          {
            struct passwd *p;
-           char *malloc_pwtmpbuf = NULL;
+           struct scratch_buffer pwtmpbuf;
+           scratch_buffer_init (&pwtmpbuf);
+
 #  if defined HAVE_GETPWNAM_R || defined _LIBC
-           long int buflenmax = GETPW_R_SIZE_MAX ();
-           size_t buflen = buflenmax;
-           char *pwtmpbuf;
            struct passwd pwbuf;
-           int save = errno;
-
-#   ifndef _LIBC
-           if (! (0 <= buflenmax && buflenmax <= SIZE_MAX))
-             /* Perhaps 'sysconf' does not support _SC_GETPW_R_SIZE_MAX.  Try a
-                moderate value.  */
-             buflen = 1024;
-#   endif
-           if (glob_use_alloca (alloca_used, buflen))
-             pwtmpbuf = alloca_account (buflen, alloca_used);
-           else
+
+           while (getpwnam_r (user_name, &pwbuf,
+                              pwtmpbuf.data, pwtmpbuf.length, &p)
+                  == ERANGE)
              {
-               pwtmpbuf = malloc (buflen);
-               if (pwtmpbuf == NULL)
+               if (!scratch_buffer_grow (&pwtmpbuf))
                  {
-                 nomem_getpw:
-                   if (__glibc_unlikely (malloc_user_name))
-                     free (user_name);
                    retval = GLOB_NOSPACE;
                    goto out;
                  }
-               malloc_pwtmpbuf = pwtmpbuf;
-             }
-
-           while (getpwnam_r (user_name, &pwbuf, pwtmpbuf, buflen, &p) != 0)
-             {
-               size_t newlen;
-               bool v;
-               if (errno != ERANGE)
-                 {
-                   p = NULL;
-                   break;
-                 }
-               v = size_add_wrapv (buflen, buflen, &newlen);
-               if (!v && malloc_pwtmpbuf == NULL
-                   && glob_use_alloca (alloca_used, newlen))
-                 pwtmpbuf = extend_alloca_account (pwtmpbuf, buflen,
-                                                   newlen, alloca_used);
-               else
-                 {
-                   char *newp = v ? NULL : realloc (malloc_pwtmpbuf, newlen);
-                   if (newp == NULL)
-                     {
-                       free (malloc_pwtmpbuf);
-                       goto nomem_getpw;
-                     }
-                   malloc_pwtmpbuf = pwtmpbuf = newp;
-                 }
-               __set_errno (save);
              }
 #  else
            p = getpwnam (user_name);
@@ -956,7 +843,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
                    dirname = malloc (home_len + rest_len + 1);
                    if (dirname == NULL)
                      {
-                       free (malloc_pwtmpbuf);
+                       scratch_buffer_free (&pwtmpbuf);
                        retval = GLOB_NOSPACE;
                        goto out;
                      }
@@ -967,13 +854,9 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
 
                dirlen = home_len + rest_len;
                dirname_modified = 1;
-
-               free (malloc_pwtmpbuf);
              }
            else
              {
-               free (malloc_pwtmpbuf);
-
                if (flags & GLOB_TILDE_CHECK)
                  {
                    /* We have to regard it as an error if we cannot find the
@@ -982,6 +865,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
                    goto out;
                  }
              }
+           scratch_buffer_free (&pwtmpbuf);
          }
 #endif /* !WINDOWS32 */
        }
This page took 0.051652 seconds and 5 git commands to generate.