]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
posix: fix glob bugs with long login names
authorAdhemerval Zanella <adhemerval.zanella@linaro.org>
Mon, 4 Sep 2017 20:07:16 +0000 (17:07 -0300)
committerAdhemerval Zanella <adhemerval.zanella@linaro.org>
Fri, 8 Sep 2017 14:33:39 +0000 (16:33 +0200)
Current glob implementation allows unlimited user name for home
directory construction on GLOB_TILDE case.  To accomplish it glob
either construct a name on stack if size are small enough (based
on current alloca_used) or in heap otherwise.

This patch simplifies storage allocation by using the same scratch
buffer for both get_rlogin_r and getpwnam_r.

This also syncs with gnulib commit 064df0b (glob: fix bugs with long
login names).

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

* posix/glob.c (GET_LOGIN_NAME_MAX): Remove.
(glob): Use the same scratch buffer for both getlogin_r and
getpwnam_r.  Don’t require preallocation of the login name.  This
simplifies storage allocation, and corrects the handling of
long login names.

ChangeLog
posix/glob.c

index 39d1235c744faba48974e5918f8753ad44d47726..4c9334e839003c153c9c0406fa5dbab1ea7f128a 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,12 @@
 2017-09-08  Adhemerval Zanella  <adhemerval.zanella@linaro.org>
 
+       [BZ #1062]
+       * posix/glob.c (GET_LOGIN_NAME_MAX): Remove.
+       (glob): Use the same scratch buffer for both getlogin_r and
+       getpwnam_r.  Don’t require preallocation of the login name.  This
+       simplifies storage allocation, and corrects the handling of
+       long login names.
+
        [BZ #1062]
        * posix/glob.c (glob): Port recent patches to platforms
        lacking getpwnam_r.
index ef620a1f0ae1f168f63968af7747b9bf2c584fb3..a47507a1ccefc0e9f961b3999c64854ede1d3335 100644 (file)
 #include <flexmember.h>
 #include <glob_internal.h>
 #include <scratch_buffer.h>
-
-#ifdef _SC_LOGIN_NAME_MAX
-# define GET_LOGIN_NAME_MAX()  sysconf (_SC_LOGIN_NAME_MAX)
-#else
-# define GET_LOGIN_NAME_MAX()  (-1)
-#endif
 \f
 static const char *next_brace_sub (const char *begin, int flags) __THROWNL;
 
@@ -610,67 +604,45 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
              else
                home_dir = "c:/users/default"; /* poor default */
 #else
-             int success;
-             char *name;
-             int malloc_name = 0;
-             size_t buflen = GET_LOGIN_NAME_MAX () + 1;
-
-             if (buflen == 0)
-               /* 'sysconf' does not support _SC_LOGIN_NAME_MAX.  Try
-                  a moderate value.  */
-               buflen = 20;
-             if (glob_use_alloca (alloca_used, buflen))
-               name = alloca_account (buflen, alloca_used);
-             else
+             int err;
+             struct passwd *p;
+             struct passwd pwbuf;
+             struct scratch_buffer s;
+             scratch_buffer_init (&s);
+             while (true)
                {
-                 name = malloc (buflen);
-                 if (name == NULL)
+                 p = NULL;
+                 err = __getlogin_r (s.data, s.length);
+                 if (err == 0)
                    {
-                     retval = GLOB_NOSPACE;
-                     goto out;
-                   }
-                 malloc_name = 1;
-               }
-
-             success = __getlogin_r (name, buflen) == 0;
-             if (success)
-               {
-                 struct passwd *p;
-                 struct scratch_buffer pwtmpbuf;
-                 scratch_buffer_init (&pwtmpbuf);
 # if defined HAVE_GETPWNAM_R || defined _LIBC
-                 struct passwd pwbuf;
-
-                 while (getpwnam_r (name, &pwbuf,
-                                    pwtmpbuf.data, pwtmpbuf.length, &p)
-                        == ERANGE)
-                   {
-                     if (!scratch_buffer_grow (&pwtmpbuf))
-                       {
-                         retval = GLOB_NOSPACE;
-                         goto out;
-                       }
-                   }
+                     size_t ssize = strlen (s.data) + 1;
+                     err = getpwnam_r (s.data, &pwbuf, s.data + ssize,
+                                       s.length - ssize, &p);
 # else
-                 p = getpwnam (name);
+                     p = getpwnam (s.data);
+                     if (p == NULL)
+                       err = errno;
 # endif
-                 if (p != NULL)
+                   }
+                 if (err != ERANGE)
+                   break;
+                 if (!scratch_buffer_grow (&s))
                    {
-                     home_dir = strdup (p->pw_dir);
-                     malloc_home_dir = 1;
-                     if (home_dir == NULL)
-                       {
-                         scratch_buffer_free (&pwtmpbuf);
-                         retval = GLOB_NOSPACE;
-                         goto out;
-                       }
+                     retval = GLOB_NOSPACE;
+                     goto out;
                    }
-                 scratch_buffer_free (&pwtmpbuf);
                }
-             else
+             if (err == 0)
+               {
+                 home_dir = strdup (p->pw_dir);
+                 malloc_home_dir = 1;
+               }
+             scratch_buffer_free (&s);
+             if (err == 0 && home_dir == NULL)
                {
-                 if (__glibc_unlikely (malloc_name))
-                   free (name);
+                 retval = GLOB_NOSPACE;
+                 goto out;
                }
 #endif /* WINDOWS32 */
            }