summaryrefslogtreecommitdiff
path: root/posix
diff options
context:
space:
mode:
authorAdhemerval Zanella <adhemerval.zanella@linaro.org>2017-09-04 17:07:16 -0300
committerAdhemerval Zanella <adhemerval.zanella@linaro.org>2017-09-08 16:33:39 +0200
commitffca890177bbf0980b66bc3a6d4d25c481957348 (patch)
treed8089db57032126b04c27cee659c90e0eea7e995 /posix
parent5a79f97554af6f2eb0a654f844b3d1f56937064d (diff)
posix: fix glob bugs with long login names
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.
Diffstat (limited to 'posix')
-rw-r--r--posix/glob.c88
1 files changed, 30 insertions, 58 deletions
diff --git a/posix/glob.c b/posix/glob.c
index ef620a1f0a..a47507a1cc 100644
--- a/posix/glob.c
+++ b/posix/glob.c
@@ -75,12 +75,6 @@
#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
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 */
}