]> Savannah Git Hosting - gnulib.git/commitdiff
glob: fix bugs with long login names
authorPaul Eggert <eggert@cs.ucla.edu>
Sat, 2 Sep 2017 22:39:16 +0000 (15:39 -0700)
committerPaul Eggert <eggert@cs.ucla.edu>
Sat, 2 Sep 2017 22:45:55 +0000 (15:45 -0700)
Problem reported by Adhemerval Zanella in:
https://sourceware.org/ml/libc-alpha/2017-08/msg00455.html
* lib/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
lib/glob.c

index b67d21799560116cb4d92e7497b2374b0409fed6..351495b2f11ff80e16b370a222012ddbce61524f 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2017-09-02  Paul Eggert  <eggert@cs.ucla.edu>
+
+       glob: fix bugs with long login names
+       Problem reported by Adhemerval Zanella in:
+       https://sourceware.org/ml/libc-alpha/2017-08/msg00455.html
+       * lib/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.
+
 2017-09-02  Bruno Haible  <bruno@clisp.org>
 
        dirent: Update doc.
index 7ca11361ec741575509c1bd8ecdd90a55ef5cfb9..8eb2b973028a85507c4118cee9ea35a3b77d98b8 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;
 
@@ -611,67 +605,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 */
             }