Add a few more alloca size checks

This commit is contained in:
Ulrich Drepper 2011-05-22 23:04:16 -04:00
parent de7ce8f171
commit f2962a7195
5 changed files with 373 additions and 114 deletions

View File

@ -1,5 +1,13 @@
2011-05-22 Ulrich Drepper <drepper@gmail.com>
[BZ #12671]
* nis/nss_nis/nis-alias.c (_nss_nis_getaliasbyname_r): Use malloc in
some situations.
* nscd/nscd_getserv_r.c (nscd_getserv_r): Likewise.
* posix/glob.c (glob_in_dir): Take additional parameter alloca_used.
add in in __libc_use_alloca calls. Adjust callers.
(glob): Use malloc in some situations.
* elf/dl-runtime.c (_dl_profile_fixup): Also store LA_SYMB_NOPLTENTER
and LA_SYMB_NOPLTEXIT in flags which are passed to pltenter and
pltexit.

8
NEWS
View File

@ -1,4 +1,4 @@
GNU C Library NEWS -- history of user-visible changes. 2011-5-21
GNU C Library NEWS -- history of user-visible changes. 2011-5-22
Copyright (C) 1992-2009, 2010, 2011 Free Software Foundation, Inc.
See the end for copying conditions.
@ -15,9 +15,9 @@ Version 2.14
12158, 12178, 12200, 12346, 12393, 12420, 12432, 12445, 12449, 12453,
12454, 12460, 12469, 12489, 12509, 12510, 12511, 12518, 12527, 12541,
12545, 12551, 12582, 12583, 12587, 12597, 12601, 12611, 12625, 12626,
12631, 12650, 12653, 12655, 12660, 12681, 12685, 12711, 12713, 12714,
12717, 12723, 12724, 12734, 12738, 12746, 12766, 12775, 12777, 12782,
12788, 12792
12631, 12650, 12653, 12655, 12660, 12671, 12681, 12685, 12711, 12713,
12714, 12717, 12723, 12724, 12734, 12738, 12746, 12766, 12775, 12777,
12782, 12788, 12792
* The RPC implementation in libc is obsoleted. Old programs keep working
but new programs cannot be linked with the routines in libc anymore.

View File

@ -1,4 +1,4 @@
/* Copyright (C) 1996-2002, 2003, 2006 Free Software Foundation, Inc.
/* Copyright (C) 1996-2002, 2003, 2006, 2011 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1996.
@ -142,10 +142,10 @@ internal_nis_getaliasent_r (struct aliasent *alias, char *buffer,
int yperr;
if (new_start)
yperr = yp_first (domain, "mail.aliases", &outkey, &keylen, &result,
yperr = yp_first (domain, "mail.aliases", &outkey, &keylen, &result,
&len);
else
yperr = yp_next (domain, "mail.aliases", oldkey, oldkeylen, &outkey,
yperr = yp_next (domain, "mail.aliases", oldkey, oldkeylen, &outkey,
&keylen, &result, &len);
if (__builtin_expect (yperr != YPERR_SUCCESS, 0))
@ -153,20 +153,20 @@ internal_nis_getaliasent_r (struct aliasent *alias, char *buffer,
enum nss_status retval = yperr2nss (yperr);
if (retval == NSS_STATUS_TRYAGAIN)
*errnop = errno;
return retval;
}
*errnop = errno;
return retval;
}
if (__builtin_expect ((size_t) (len + 1) > buflen, 0))
{
{
free (result);
*errnop = ERANGE;
return NSS_STATUS_TRYAGAIN;
}
*errnop = ERANGE;
return NSS_STATUS_TRYAGAIN;
}
char *p = strncpy (buffer, result, len);
buffer[len] = '\0';
while (isspace (*p))
++p;
++p;
free (result);
parse_res = _nss_nis_parse_aliasent (outkey, p, alias, buffer,
@ -213,13 +213,25 @@ _nss_nis_getaliasbyname_r (const char *name, struct aliasent *alias,
return NSS_STATUS_UNAVAIL;
}
size_t namlen = strlen (name);
char name2[namlen + 1];
char *domain;
if (__builtin_expect (yp_get_default_domain (&domain), 0))
return NSS_STATUS_UNAVAIL;
size_t namlen = strlen (name);
char *name2;
int use_alloca = __libc_use_alloca (namlen + 1);
if (use_alloca)
name2 = __alloca (namlen + 1);
else
{
name2 = malloc (namlen + 1);
if (name2 == NULL)
{
*errnop = ENOMEM;
return NSS_STATUS_TRYAGAIN;
}
}
/* Convert name to lowercase. */
size_t i;
for (i = 0; i < namlen; ++i)
@ -230,6 +242,9 @@ _nss_nis_getaliasbyname_r (const char *name, struct aliasent *alias,
int len;
int yperr = yp_match (domain, "mail.aliases", name2, namlen, &result, &len);
if (!use_alloca)
free (name2);
if (__builtin_expect (yperr != YPERR_SUCCESS, 0))
{
enum nss_status retval = yperr2nss (yperr);

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2007, 2009 Free Software Foundation, Inc.
/* Copyright (C) 2007, 2009, 2011 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2007.
@ -17,6 +17,7 @@
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <assert.h>
#include <errno.h>
#include <string.h>
#include <not-cancel.h>
@ -80,6 +81,7 @@ nscd_getserv_r (const char *crit, size_t critlen, const char *proto,
{
int gc_cycle;
int nretries = 0;
size_t alloca_used = 0;
/* If the mapping is available, try to search there instead of
communicating with the nscd. */
@ -88,13 +90,23 @@ nscd_getserv_r (const char *crit, size_t critlen, const char *proto,
&gc_cycle);
size_t protolen = proto == NULL ? 0 : strlen (proto);
size_t keylen = critlen + 1 + protolen + 1;
char *key = alloca (keylen);
int alloca_key = __libc_use_alloca (keylen);
char *key;
if (alloca_key)
key = alloca_account (keylen, alloca_used);
else
{
key = malloc (keylen);
if (key == NULL)
return -1;
}
memcpy (__mempcpy (__mempcpy (key, crit, critlen),
"/", 1), proto ?: "", protolen + 1);
retry:;
const char *s_name = NULL;
const char *s_proto = NULL;
int alloca_aliases_len = 0;
const uint32_t *aliases_len = NULL;
const char *aliases_list = NULL;
int retval = -1;
@ -136,8 +148,22 @@ nscd_getserv_r (const char *crit, size_t critlen, const char *proto,
if (((uintptr_t) aliases_len & (__alignof__ (*aliases_len) - 1))
!= 0)
{
uint32_t *tmp = alloca (serv_resp.s_aliases_cnt
* sizeof (uint32_t));
uint32_t *tmp;
alloca_aliases_len
= __libc_use_alloca (alloca_used
+ (serv_resp.s_aliases_cnt
* sizeof (uint32_t)));
if (alloca_aliases_len)
tmp = __alloca (serv_resp.s_aliases_cnt * sizeof (uint32_t));
else
{
tmp = malloc (serv_resp.s_aliases_cnt * sizeof (uint32_t));
if (tmp == NULL)
{
retval = ENOMEM;
goto out;
}
}
aliases_len = memcpy (tmp, aliases_len,
serv_resp.s_aliases_cnt
* sizeof (uint32_t));
@ -217,8 +243,24 @@ nscd_getserv_r (const char *crit, size_t critlen, const char *proto,
if (serv_resp.s_aliases_cnt > 0)
{
aliases_len = alloca (serv_resp.s_aliases_cnt
* sizeof (uint32_t));
assert (alloca_aliases_len == 0);
alloca_aliases_len
= __libc_use_alloca (alloca_used
+ (serv_resp.s_aliases_cnt
* sizeof (uint32_t)));
if (alloca_aliases_len)
aliases_len = alloca (serv_resp.s_aliases_cnt
* sizeof (uint32_t));
else
{
aliases_len = malloc (serv_resp.s_aliases_cnt
* sizeof (uint32_t));
if (aliases_len == NULL)
{
retval = ENOMEM;
goto out_close;
}
}
vec[n].iov_base = (void *) aliases_len;
vec[n].iov_len = serv_resp.s_aliases_cnt * sizeof (uint32_t);
@ -329,5 +371,10 @@ nscd_getserv_r (const char *crit, size_t critlen, const char *proto,
goto retry;
}
if (!alloca_aliases_len)
free ((void *) aliases_len);
if (!alloca_key)
free (key);
return retval;
}

View File

@ -1,4 +1,4 @@
/* Copyright (C) 1991-2002, 2003, 2004, 2005, 2006, 2007, 2008, 2010
/* Copyright (C) 1991-2002, 2003, 2004, 2005, 2006, 2007, 2008, 2010, 2011
Free Software Foundation, Inc.
This file is part of the GNU C Library.
@ -199,7 +199,7 @@ static const char *next_brace_sub (const char *begin, int flags) __THROW;
static int glob_in_dir (const char *pattern, const char *directory,
int flags, int (*errfunc) (const char *, int),
glob_t *pglob);
glob_t *pglob, size_t alloca_used);
extern int __glob_pattern_type (const char *pattern, int quote)
attribute_hidden;
@ -253,13 +253,18 @@ glob (pattern, flags, errfunc, pglob)
glob_t *pglob;
{
const char *filename;
const char *dirname;
char *dirname = NULL;
size_t dirlen;
int status;
size_t oldcount;
int meta;
int dirname_modified;
int malloc_dirname = 0;
glob_t dirs;
int retval = 0;
#ifdef _LIBC
size_t alloca_used = 0;
#endif
if (pattern == NULL || pglob == NULL || (flags & ~__GLOB_FLAGS) != 0)
{
@ -308,20 +313,26 @@ glob (pattern, flags, errfunc, pglob)
const char *next;
const char *rest;
size_t rest_len;
#ifdef __GNUC__
char onealt[strlen (pattern) - 1];
#else
char *onealt = (char *) malloc (strlen (pattern) - 1);
if (onealt == NULL)
{
if (!(flags & GLOB_APPEND))
{
pglob->gl_pathc = 0;
pglob->gl_pathv = NULL;
}
return GLOB_NOSPACE;
}
char *onealt;
size_t pattern_len = strlen (pattern) - 1;
#ifdef _LIBC
int alloca_onealt = __libc_use_alloca (alloca_used + pattern_len);
if (alloca_onealt)
onealt = alloca_account (pattern_len, alloca_used);
else
#endif
{
onealt = (char *) malloc (pattern_len);
if (onealt == NULL)
{
if (!(flags & GLOB_APPEND))
{
pglob->gl_pathc = 0;
pglob->gl_pathv = NULL;
}
return GLOB_NOSPACE;
}
}
/* We know the prefix for all sub-patterns. */
alt_start = mempcpy (onealt, pattern, begin - pattern);
@ -332,9 +343,11 @@ glob (pattern, flags, errfunc, pglob)
if (next == NULL)
{
/* It is an illegal expression. */
#ifndef __GNUC__
free (onealt);
illegal_brace:
#ifdef _LIBC
if (__builtin_expect (!alloca_onealt, 0))
#endif
free (onealt);
return glob (pattern, flags & ~GLOB_BRACE, errfunc, pglob);
}
@ -344,13 +357,8 @@ glob (pattern, flags, errfunc, pglob)
{
rest = next_brace_sub (rest + 1, flags);
if (rest == NULL)
{
/* It is an illegal expression. */
#ifndef __GNUC__
free (onealt);
#endif
return glob (pattern, flags & ~GLOB_BRACE, errfunc, pglob);
}
/* It is an illegal expression. */
goto illegal_brace;
}
/* Please note that we now can be sure the brace expression
is well-formed. */
@ -386,9 +394,10 @@ glob (pattern, flags, errfunc, pglob)
/* If we got an error, return it. */
if (result && result != GLOB_NOMATCH)
{
#ifndef __GNUC__
free (onealt);
#ifdef _LIBC
if (__builtin_expect (!alloca_onealt, 0))
#endif
free (onealt);
if (!(flags & GLOB_APPEND))
{
globfree (pglob);
@ -406,9 +415,10 @@ glob (pattern, flags, errfunc, pglob)
assert (next != NULL);
}
#ifndef __GNUC__
free (onealt);
#ifdef _LIBC
if (__builtin_expect (!alloca_onealt, 0))
#endif
free (onealt);
if (pglob->gl_pathc != firstc)
/* We found some entries. */
@ -455,7 +465,7 @@ glob (pattern, flags, errfunc, pglob)
case is nothing but a notation for a directory. */
if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && pattern[0] == '~')
{
dirname = pattern;
dirname = (char *) pattern;
dirlen = strlen (pattern);
/* Set FILENAME to NULL as a special flag. This is ugly but
@ -473,9 +483,9 @@ glob (pattern, flags, errfunc, pglob)
filename = pattern;
#ifdef _AMIGA
dirname = "";
dirname = (char *) "";
#else
dirname = ".";
dirname = (char *) ".";
#endif
dirlen = 0;
}
@ -485,7 +495,7 @@ glob (pattern, flags, errfunc, pglob)
&& (flags & GLOB_NOESCAPE) == 0))
{
/* "/pattern" or "\\/pattern". */
dirname = "/";
dirname = (char *) "/";
dirlen = 1;
++filename;
}
@ -511,7 +521,17 @@ glob (pattern, flags, errfunc, pglob)
from "d:/", since "d:" and "d:/" are not the same.*/
}
#endif
newp = (char *) __alloca (dirlen + 1);
#ifdef _LIBC
if (__libc_use_alloca (alloca_used + dirlen + 1))
newp = alloca_account (dirlen + 1, alloca_used);
else
#endif
{
newp = malloc (dirlen + 1);
if (newp == NULL)
return GLOB_NOSPACE;
malloc_dirname = 1;
}
*((char *) mempcpy (newp, pattern, dirlen)) = '\0';
dirname = newp;
++filename;
@ -551,7 +571,8 @@ glob (pattern, flags, errfunc, pglob)
oldcount = pglob->gl_pathc + pglob->gl_offs;
goto no_matches;
}
return val;
retval = val;
goto out;
}
}
@ -563,7 +584,8 @@ glob (pattern, flags, errfunc, pglob)
&& (dirname[2] == '\0' || dirname[2] == '/')))
{
/* Look up home directory. */
const char *home_dir = getenv ("HOME");
char *home_dir = getenv ("HOME");
int malloc_home_dir = 0;
# ifdef _AMIGA
if (home_dir == NULL || home_dir[0] == '\0')
home_dir = "SYS:";
@ -582,7 +604,7 @@ glob (pattern, flags, errfunc, pglob)
/* `sysconf' does not support _SC_LOGIN_NAME_MAX. Try
a moderate value. */
buflen = 20;
name = (char *) __alloca (buflen);
name = alloca_account (buflen, alloca_used);
success = getlogin_r (name, buflen) == 0;
if (success)
@ -592,6 +614,7 @@ glob (pattern, flags, errfunc, pglob)
long int pwbuflen = GETPW_R_SIZE_MAX ();
char *pwtmpbuf;
struct passwd pwbuf;
int malloc_pwtmpbuf = 0;
int save = errno;
# ifndef _LIBC
@ -600,7 +623,18 @@ glob (pattern, flags, errfunc, pglob)
Try a moderate value. */
pwbuflen = 1024;
# endif
pwtmpbuf = (char *) __alloca (pwbuflen);
if (__libc_use_alloca (alloca_used + pwbuflen))
pwtmpbuf = alloca_account (pwbuflen, alloca_used);
else
{
pwtmpbuf = malloc (pwbuflen);
if (pwtmpbuf == NULL)
{
retval = GLOB_NOSPACE;
goto out;
}
malloc_pwtmpbuf = 1;
}
while (getpwnam_r (name, &pwbuf, pwtmpbuf, pwbuflen, &p)
!= 0)
@ -610,46 +644,115 @@ glob (pattern, flags, errfunc, pglob)
p = NULL;
break;
}
# ifdef _LIBC
pwtmpbuf = extend_alloca (pwtmpbuf, pwbuflen,
if (!malloc_pwtmpbuf
&& __libc_use_alloca (alloca_used
+ 2 * pwbuflen))
pwtmpbuf = extend_alloca_account (pwtmpbuf, pwbuflen,
2 * pwbuflen,
alloca_used);
else
{
char *newp = realloc (malloc_pwtmpbuf
? pwtmpbuf : NULL,
2 * pwbuflen);
# else
pwbuflen *= 2;
pwtmpbuf = (char *) __alloca (pwbuflen);
# endif
if (newp == NULL)
{
if (__builtin_expect (malloc_pwtmpbuf, 0))
free (pwtmpbuf);
retval = GLOB_NOSPACE;
goto out;
}
pwtmpbuf = newp;
pwbuflen = 2 * pwbuflen;
malloc_pwtmpbuf = 1;
}
__set_errno (save);
}
# else
p = getpwnam (name);
# endif
if (p != NULL)
home_dir = p->pw_dir;
{
if (!malloc_pwtmpbuf)
home_dir = p->pw_dir;
else
{
size_t home_dir_len = strlen (p->pw_dir) + 1;
if (__libc_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);
free (pwtmpbuf);
}
}
}
}
if (home_dir == NULL || home_dir[0] == '\0')
{
if (flags & GLOB_TILDE_CHECK)
return GLOB_NOMATCH;
{
if (__builtin_expect (malloc_home_dir, 0))
free (home_dir);
retval = GLOB_NOMATCH;
goto out;
}
else
home_dir = "~"; /* No luck. */
home_dir = (char *) "~"; /* No luck. */
}
# endif /* WINDOWS32 */
# endif
/* Now construct the full directory. */
if (dirname[1] == '\0')
{
if (__builtin_expect (malloc_dirname, 0))
free (dirname);
dirname = home_dir;
dirlen = strlen (dirname);
malloc_dirname = malloc_home_dir;
}
else
{
char *newp;
size_t home_len = strlen (home_dir);
newp = (char *) __alloca (home_len + dirlen);
int use_alloca = __libc_use_alloca (alloca_used
+ home_len + dirlen);
if (use_alloca)
newp = alloca_account (home_len + dirlen, alloca_used);
else
{
newp = malloc (home_len + dirlen);
if (newp == NULL)
{
if (__builtin_expect (malloc_home_dir, 0))
free (home_dir);
retval = GLOB_NOSPACE;
goto out;
}
}
mempcpy (mempcpy (newp, home_dir, home_len),
&dirname[1], dirlen);
if (__builtin_expect (malloc_dirname, 0))
free (dirname);
dirname = newp;
dirlen += home_len - 1;
malloc_dirname = !use_alloca;
}
dirname_modified = 1;
}
@ -657,7 +760,8 @@ glob (pattern, flags, errfunc, pglob)
else
{
char *end_name = strchr (dirname, '/');
const char *user_name;
char *user_name;
int malloc_user_name = 0;
const char *home_dir;
char *unescape = NULL;
@ -677,7 +781,18 @@ glob (pattern, flags, errfunc, pglob)
else
{
char *newp;
newp = (char *) __alloca (end_name - dirname);
if (__libc_use_alloca (alloca_used + (end_name - dirname)))
newp = alloca_account (end_name - dirname, alloca_used);
else
{
newp = malloc (end_name - dirname);
if (newp == NULL)
{
retval = GLOB_NOSPACE;
goto out;
}
malloc_user_name = 1;
}
if (unescape != NULL)
{
char *p = mempcpy (newp, dirname + 1,
@ -714,6 +829,7 @@ glob (pattern, flags, errfunc, pglob)
# if defined HAVE_GETPWNAM_R || defined _LIBC
long int buflen = GETPW_R_SIZE_MAX ();
char *pwtmpbuf;
int malloc_pwtmpbuf = 0;
struct passwd pwbuf;
int save = errno;
@ -723,7 +839,21 @@ glob (pattern, flags, errfunc, pglob)
moderate value. */
buflen = 1024;
# endif
pwtmpbuf = (char *) __alloca (buflen);
if (__libc_use_alloca (alloca_used + buflen))
pwtmpbuf = alloca_account (buflen, alloca_used);
else
{
pwtmpbuf = malloc (buflen);
if (pwtmpbuf == NULL)
{
nomem_getpw:
if (__builtin_expect (malloc_user_name, 0))
free (user_name);
retval = GLOB_NOSPACE;
goto out;
}
malloc_pwtmpbuf = 1;
}
while (getpwnam_r (user_name, &pwbuf, pwtmpbuf, buflen, &p) != 0)
{
@ -732,40 +862,77 @@ glob (pattern, flags, errfunc, pglob)
p = NULL;
break;
}
# ifdef _LIBC
pwtmpbuf = extend_alloca (pwtmpbuf, buflen, 2 * buflen);
# else
buflen *= 2;
pwtmpbuf = __alloca (buflen);
# endif
if (!malloc_pwtmpbuf
&& __libc_use_alloca (alloca_used + 2 * buflen))
pwtmpbuf = extend_alloca_account (pwtmpbuf, buflen,
2 * buflen, alloca_used);
else
{
char *newp = realloc (malloc_pwtmpbuf ? pwtmpbuf : NULL,
2 * buflen);
if (newp == NULL)
{
if (__builtin_expect (malloc_pwtmpbuf, 0))
free (pwtmpbuf);
goto nomem_getpw;
}
pwtmpbuf = newp;
malloc_pwtmpbuf = 1;
}
__set_errno (save);
}
# else
p = getpwnam (user_name);
# endif
if (__builtin_expect (malloc_user_name, 0))
free (user_name);
/* If we found a home directory use this. */
if (p != NULL)
home_dir = p->pw_dir;
{
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))
free (dirname);
malloc_dirname = 0;
if (__libc_use_alloca (alloca_used + home_len + rest_len + 1))
dirname = alloca_account (home_len + rest_len + 1,
alloca_used);
else
{
dirname = malloc (home_len + rest_len + 1);
if (dirname == NULL)
{
if (__builtin_expect (malloc_pwtmpbuf, 0))
free (pwtmpbuf);
retval = GLOB_NOSPACE;
goto out;
}
malloc_dirname = 1;
}
*((char *) mempcpy (mempcpy (dirname, p->pw_dir, home_len),
end_name, rest_len)) = '\0';
dirlen = home_len + rest_len;
dirname_modified = 1;
if (__builtin_expect (malloc_pwtmpbuf, 0))
free (pwtmpbuf);
}
else
home_dir = NULL;
{
if (__builtin_expect (malloc_pwtmpbuf, 0))
free (pwtmpbuf);
if (flags & GLOB_TILDE_CHECK)
/* We have to regard it as an error if we cannot find the
home directory. */
return GLOB_NOMATCH;
}
}
/* If we found a home directory use this. */
if (home_dir != NULL)
{
char *newp;
size_t home_len = strlen (home_dir);
size_t rest_len = end_name == NULL ? 0 : strlen (end_name);
newp = (char *) __alloca (home_len + rest_len + 1);
*((char *) mempcpy (mempcpy (newp, home_dir, home_len),
end_name, rest_len)) = '\0';
dirname = newp;
dirlen = home_len + rest_len;
dirname_modified = 1;
}
else
if (flags & GLOB_TILDE_CHECK)
/* We have to regard it as an error if we cannot find the
home directory. */
return GLOB_NOMATCH;
}
# endif /* Not Amiga && not WINDOWS32. */
}
@ -899,7 +1066,7 @@ glob (pattern, flags, errfunc, pglob)
status = glob_in_dir (filename, dirs.gl_pathv[i],
((flags | GLOB_APPEND)
& ~(GLOB_NOCHECK | GLOB_NOMAGIC)),
errfunc, pglob);
errfunc, pglob, alloca_used);
if (status == GLOB_NOMATCH)
/* No matches in this directory. Try the next. */
continue;
@ -1000,7 +1167,8 @@ glob (pattern, flags, errfunc, pglob)
}
if (dirname_modified)
flags &= ~(GLOB_NOCHECK | GLOB_NOMAGIC);
status = glob_in_dir (filename, dirname, flags, errfunc, pglob);
status = glob_in_dir (filename, dirname, flags, errfunc, pglob,
alloca_used);
if (status != 0)
{
if (status == GLOB_NOMATCH && flags != orig_flags
@ -1063,7 +1231,11 @@ glob (pattern, flags, errfunc, pglob)
sizeof (char *), collated_compare);
}
return 0;
out:
if (__builtin_expect (malloc_dirname, 0))
free (dirname);
return retval;
}
#if defined _LIBC && !defined glob
libc_hidden_def (glob)
@ -1273,7 +1445,7 @@ link_exists2_p (const char *dir, size_t dirlen, const char *fname,
static int
glob_in_dir (const char *pattern, const char *directory, int flags,
int (*errfunc) (const char *, int),
glob_t *pglob)
glob_t *pglob, size_t alloca_used)
{
size_t dirlen = strlen (directory);
void *stream = NULL;
@ -1288,11 +1460,12 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
struct globnames *names = &init_names;
struct globnames *names_alloca = &init_names;
size_t nfound = 0;
size_t allocasize = sizeof (init_names);
size_t cur = 0;
int meta;
int save;
alloca_used += sizeof (init_names);
init_names.next = NULL;
init_names.count = INITIAL_COUNT;
@ -1308,20 +1481,36 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
{
/* Since we use the normal file functions we can also use stat()
to verify the file is there. */
struct stat st;
struct_stat64 st64;
union
{
struct stat st;
struct_stat64 st64;
} ust;
size_t patlen = strlen (pattern);
char *fullname = (char *) __alloca (dirlen + 1 + patlen + 1);
int alloca_fullname = __libc_use_alloca (alloca_used
+ dirlen + 1 + patlen + 1);
char *fullname;
if (alloca_fullname)
fullname = alloca_account (dirlen + 1 + patlen + 1, alloca_used);
else
{
fullname = malloc (dirlen + 1 + patlen + 1);
if (fullname == NULL)
return GLOB_NOSPACE;
}
mempcpy (mempcpy (mempcpy (fullname, directory, dirlen),
"/", 1),
pattern, patlen + 1);
if ((__builtin_expect (flags & GLOB_ALTDIRFUNC, 0)
? (*pglob->gl_stat) (fullname, &st)
: __stat64 (fullname, &st64)) == 0)
? (*pglob->gl_stat) (fullname, &ust.st)
: __stat64 (fullname, &ust.st64)) == 0)
/* We found this file to be existing. Now tell the rest
of the function to copy this name into the result. */
flags |= GLOB_NOCHECK;
if (__builtin_expect (!alloca_fullname, 0))
free (fullname);
}
else
{
@ -1409,9 +1598,9 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
size_t size = (sizeof (struct globnames)
+ ((count - INITIAL_COUNT)
* sizeof (char *)));
allocasize += size;
if (__libc_use_alloca (allocasize))
newnames = names_alloca = __alloca (size);
if (__libc_use_alloca (alloca_used + size))
newnames = names_alloca
= alloca_account (size, alloca_used);
else if ((newnames = malloc (size))
== NULL)
goto memory_error;