-/* 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
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 */
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 == '\\')
{
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. */
/* 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);
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))
}
#ifdef _LIBC
- if (__builtin_expect (!alloca_onealt, 0))
+ if (__glibc_unlikely (!alloca_onealt))
#endif
free (onealt);
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)
}
else
{
- if (__builtin_expect (pattern[0] == '\0', 0))
+ if (__glibc_unlikely (pattern[0] == '\0'))
{
dirs.gl_pathv = NULL;
goto no_matches;
2 * pwbuflen);
if (newp == NULL)
{
- if (__builtin_expect (malloc_pwtmpbuf, 0))
+ if (__glibc_unlikely (malloc_pwtmpbuf))
free (pwtmpbuf);
retval = GLOB_NOSPACE;
goto out;
{
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;
/* 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;
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;
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;
char *end_name = strchr (dirname, '/');
char *user_name;
int malloc_user_name = 0;
- const char *home_dir;
char *unescape = NULL;
if (!(flags & GLOB_NOESCAPE))
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;
2 * buflen);
if (newp == NULL)
{
- if (__builtin_expect (malloc_pwtmpbuf, 0))
+ if (__glibc_unlikely (malloc_pwtmpbuf))
free (pwtmpbuf);
goto nomem_getpw;
}
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. */
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;
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;
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)
&& 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);
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)
*(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. */
appending the results to PGLOB. */
for (i = 0; i < dirs.gl_pathc; ++i)
{
- int old_pathc;
+ size_t old_pathc;
#ifdef SHELL
{
/* 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);
}
else
{
- int old_pathc = pglob->gl_pathc;
+ size_t old_pathc = pglob->gl_pathc;
int orig_flags = flags;
if (meta & 2)
}
out:
- if (__builtin_expect (malloc_dirname, 0))
+ if (__glibc_unlikely (malloc_dirname))
free (dirname);
return retval;
/* 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)
{
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 = '/';
const char *pattern;
int quote;
{
- register const char *p;
+ const char *p;
int ret = 0;
for (p = pattern; *p != '\0'; ++p)
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
}
d64buf;
- if (__builtin_expect (flags & GLOB_ALTDIRFUNC, 0))
+ if (__glibc_unlikely (flags & GLOB_ALTDIRFUNC))
{
struct dirent *d32 = (*pglob->gl_readdir) (stream);
if (d32 != NULL)
{
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,
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);