Blame SOURCES/glibc-rh797094-2.patch

b9ba6d
From: Ulrich Drepper <drepper@gmail.com>
b9ba6d
Date: Mon, 23 May 2011 03:04:16 +0000 (-0400)
b9ba6d
Subject: Add a few more alloca size checks
b9ba6d
X-Git-Tag: glibc-2.14~41
b9ba6d
X-Git-Url: http://sourceware.org/git/?p=glibc.git;a=commitdiff_plain;h=f2962a71959fd254a7a223437ca4b63b9e81130c
b9ba6d
b9ba6d
Add a few more alloca size checks
b9ba6d
---
b9ba6d
b9ba6d
 2011-05-22  Ulrich Drepper  <drepper@gmail.com>
b9ba6d
 
b9ba6d
	[BZ #12671]
b9ba6d
	* nis/nss_nis/nis-alias.c (_nss_nis_getaliasbyname_r): Use malloc in
b9ba6d
	some situations.
b9ba6d
	* nscd/nscd_getserv_r.c (nscd_getserv_r): Likewise.
b9ba6d
	* posix/glob.c (glob_in_dir): Take additional parameter alloca_used.
b9ba6d
	add in in __libc_use_alloca calls.  Adjust callers.
b9ba6d
	(glob): Use malloc in some situations.
b9ba6d
diff --git a/nis/nss_nis/nis-alias.c b/nis/nss_nis/nis-alias.c
b9ba6d
index 9286e36..cfe4097 100644
b9ba6d
--- a/nis/nss_nis/nis-alias.c
b9ba6d
+++ b/nis/nss_nis/nis-alias.c
b9ba6d
@@ -1,4 +1,4 @@
b9ba6d
-/* Copyright (C) 1996-2002, 2003, 2006 Free Software Foundation, Inc.
b9ba6d
+/* Copyright (C) 1996-2002, 2003, 2006, 2011 Free Software Foundation, Inc.
b9ba6d
    This file is part of the GNU C Library.
b9ba6d
    Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1996.
b9ba6d
 
b9ba6d
@@ -142,10 +142,10 @@ internal_nis_getaliasent_r (struct aliasent *alias, char *buffer,
b9ba6d
       int yperr;
b9ba6d
 
b9ba6d
       if (new_start)
b9ba6d
-        yperr = yp_first (domain, "mail.aliases", &outkey, &keylen, &result,
b9ba6d
+	yperr = yp_first (domain, "mail.aliases", &outkey, &keylen, &result,
b9ba6d
 			  &len;;
b9ba6d
       else
b9ba6d
-        yperr = yp_next (domain, "mail.aliases", oldkey, oldkeylen, &outkey,
b9ba6d
+	yperr = yp_next (domain, "mail.aliases", oldkey, oldkeylen, &outkey,
b9ba6d
 			 &keylen, &result, &len;;
b9ba6d
 
b9ba6d
       if (__builtin_expect (yperr != YPERR_SUCCESS, 0))
b9ba6d
@@ -153,20 +153,20 @@ internal_nis_getaliasent_r (struct aliasent *alias, char *buffer,
b9ba6d
 	  enum nss_status retval = yperr2nss (yperr);
b9ba6d
 
b9ba6d
 	  if (retval == NSS_STATUS_TRYAGAIN)
b9ba6d
-            *errnop = errno;
b9ba6d
-          return retval;
b9ba6d
-        }
b9ba6d
+	    *errnop = errno;
b9ba6d
+	  return retval;
b9ba6d
+	}
b9ba6d
 
b9ba6d
       if (__builtin_expect ((size_t) (len + 1) > buflen, 0))
b9ba6d
-        {
b9ba6d
+	{
b9ba6d
 	  free (result);
b9ba6d
-          *errnop = ERANGE;
b9ba6d
-          return NSS_STATUS_TRYAGAIN;
b9ba6d
-        }
b9ba6d
+	  *errnop = ERANGE;
b9ba6d
+	  return NSS_STATUS_TRYAGAIN;
b9ba6d
+	}
b9ba6d
       char *p = strncpy (buffer, result, len);
b9ba6d
       buffer[len] = '\0';
b9ba6d
       while (isspace (*p))
b9ba6d
-        ++p;
b9ba6d
+	++p;
b9ba6d
       free (result);
b9ba6d
 
b9ba6d
       parse_res = _nss_nis_parse_aliasent (outkey, p, alias, buffer,
b9ba6d
@@ -213,13 +213,25 @@ _nss_nis_getaliasbyname_r (const char *name, struct aliasent *alias,
b9ba6d
       return NSS_STATUS_UNAVAIL;
b9ba6d
     }
b9ba6d
 
b9ba6d
-  size_t namlen = strlen (name);
b9ba6d
-  char name2[namlen + 1];
b9ba6d
-
b9ba6d
   char *domain;
b9ba6d
   if (__builtin_expect (yp_get_default_domain (&domain), 0))
b9ba6d
     return NSS_STATUS_UNAVAIL;
b9ba6d
 
b9ba6d
+  size_t namlen = strlen (name);
b9ba6d
+  char *name2;
b9ba6d
+  int use_alloca = __libc_use_alloca (namlen + 1);
b9ba6d
+  if (use_alloca)
b9ba6d
+    name2 = __alloca (namlen + 1);
b9ba6d
+  else
b9ba6d
+    {
b9ba6d
+      name2 = malloc (namlen + 1);
b9ba6d
+      if (name2 == NULL)
b9ba6d
+	{
b9ba6d
+	  *errnop = ENOMEM;
b9ba6d
+	  return NSS_STATUS_TRYAGAIN;
b9ba6d
+	}
b9ba6d
+    }
b9ba6d
+
b9ba6d
   /* Convert name to lowercase.  */
b9ba6d
   size_t i;
b9ba6d
   for (i = 0; i < namlen; ++i)
b9ba6d
@@ -230,6 +242,9 @@ _nss_nis_getaliasbyname_r (const char *name, struct aliasent *alias,
b9ba6d
   int len;
b9ba6d
   int yperr = yp_match (domain, "mail.aliases", name2, namlen, &result, &len;;
b9ba6d
 
b9ba6d
+  if (!use_alloca)
b9ba6d
+    free (name2);
b9ba6d
+
b9ba6d
   if (__builtin_expect (yperr != YPERR_SUCCESS, 0))
b9ba6d
     {
b9ba6d
       enum nss_status retval = yperr2nss (yperr);
b9ba6d
diff --git a/nscd/nscd_getserv_r.c b/nscd/nscd_getserv_r.c
b9ba6d
index dce4165..de96a57 100644
b9ba6d
--- a/nscd/nscd_getserv_r.c
b9ba6d
+++ b/nscd/nscd_getserv_r.c
b9ba6d
@@ -1,4 +1,4 @@
b9ba6d
-/* Copyright (C) 2007, 2009 Free Software Foundation, Inc.
b9ba6d
+/* Copyright (C) 2007, 2009, 2011 Free Software Foundation, Inc.
b9ba6d
    This file is part of the GNU C Library.
b9ba6d
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2007.
b9ba6d
 
b9ba6d
@@ -17,6 +17,7 @@
b9ba6d
    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
b9ba6d
    02111-1307 USA.  */
b9ba6d
 
b9ba6d
+#include <assert.h>
b9ba6d
 #include <errno.h>
b9ba6d
 #include <string.h>
b9ba6d
 #include <not-cancel.h>
b9ba6d
@@ -80,6 +81,7 @@ nscd_getserv_r (const char *crit, size_t critlen, const char *proto,
b9ba6d
 {
b9ba6d
   int gc_cycle;
b9ba6d
   int nretries = 0;
b9ba6d
+  size_t alloca_used = 0;
b9ba6d
 
b9ba6d
   /* If the mapping is available, try to search there instead of
b9ba6d
      communicating with the nscd.  */
b9ba6d
@@ -88,13 +90,23 @@ nscd_getserv_r (const char *crit, size_t critlen, const char *proto,
b9ba6d
 			       &gc_cycle);
b9ba6d
   size_t protolen = proto == NULL ? 0 : strlen (proto);
b9ba6d
   size_t keylen = critlen + 1 + protolen + 1;
b9ba6d
-  char *key = alloca (keylen);
b9ba6d
+  int alloca_key = __libc_use_alloca (keylen);
b9ba6d
+  char *key;
b9ba6d
+  if (alloca_key)
b9ba6d
+    key = alloca_account (keylen, alloca_used);
b9ba6d
+  else
b9ba6d
+    {
b9ba6d
+      key = malloc (keylen);
b9ba6d
+      if (key == NULL)
b9ba6d
+	return -1;
b9ba6d
+    }
b9ba6d
   memcpy (__mempcpy (__mempcpy (key, crit, critlen),
b9ba6d
 		     "/", 1), proto ?: "", protolen + 1);
b9ba6d
 
b9ba6d
  retry:;
b9ba6d
   const char *s_name = NULL;
b9ba6d
   const char *s_proto = NULL;
b9ba6d
+  int alloca_aliases_len = 0;
b9ba6d
   const uint32_t *aliases_len = NULL;
b9ba6d
   const char *aliases_list = NULL;
b9ba6d
   int retval = -1;
b9ba6d
@@ -136,8 +148,22 @@ nscd_getserv_r (const char *crit, size_t critlen, const char *proto,
b9ba6d
 	  if (((uintptr_t) aliases_len & (__alignof__ (*aliases_len) - 1))
b9ba6d
 	      != 0)
b9ba6d
 	    {
b9ba6d
-	      uint32_t *tmp = alloca (serv_resp.s_aliases_cnt
b9ba6d
-				      * sizeof (uint32_t));
b9ba6d
+	      uint32_t *tmp;
b9ba6d
+	      alloca_aliases_len
b9ba6d
+		= __libc_use_alloca (alloca_used
b9ba6d
+				     + (serv_resp.s_aliases_cnt
b9ba6d
+					* sizeof (uint32_t)));
b9ba6d
+	      if (alloca_aliases_len)
b9ba6d
+		tmp = __alloca (serv_resp.s_aliases_cnt * sizeof (uint32_t));
b9ba6d
+	      else
b9ba6d
+		{
b9ba6d
+		  tmp = malloc (serv_resp.s_aliases_cnt * sizeof (uint32_t));
b9ba6d
+		  if (tmp == NULL)
b9ba6d
+		    {
b9ba6d
+		      retval = ENOMEM;
b9ba6d
+		      goto out;
b9ba6d
+		    }
b9ba6d
+		}
b9ba6d
 	      aliases_len = memcpy (tmp, aliases_len,
b9ba6d
 				    serv_resp.s_aliases_cnt
b9ba6d
 				    * sizeof (uint32_t));
b9ba6d
@@ -217,8 +243,24 @@ nscd_getserv_r (const char *crit, size_t critlen, const char *proto,
b9ba6d
 
b9ba6d
 	  if (serv_resp.s_aliases_cnt > 0)
b9ba6d
 	    {
b9ba6d
-	      aliases_len = alloca (serv_resp.s_aliases_cnt
b9ba6d
-				    * sizeof (uint32_t));
b9ba6d
+	      assert (alloca_aliases_len == 0);
b9ba6d
+	      alloca_aliases_len
b9ba6d
+		= __libc_use_alloca (alloca_used
b9ba6d
+				     + (serv_resp.s_aliases_cnt
b9ba6d
+					* sizeof (uint32_t)));
b9ba6d
+	      if (alloca_aliases_len)
b9ba6d
+		aliases_len = alloca (serv_resp.s_aliases_cnt
b9ba6d
+				      * sizeof (uint32_t));
b9ba6d
+	      else
b9ba6d
+		{
b9ba6d
+		  aliases_len = malloc (serv_resp.s_aliases_cnt
b9ba6d
+					* sizeof (uint32_t));
b9ba6d
+		  if (aliases_len == NULL)
b9ba6d
+		    {
b9ba6d
+		      retval = ENOMEM;
b9ba6d
+		      goto out_close;
b9ba6d
+		    }
b9ba6d
+		}
b9ba6d
 	      vec[n].iov_base = (void *) aliases_len;
b9ba6d
 	      vec[n].iov_len = serv_resp.s_aliases_cnt * sizeof (uint32_t);
b9ba6d
 
b9ba6d
@@ -329,5 +371,10 @@ nscd_getserv_r (const char *crit, size_t critlen, const char *proto,
b9ba6d
 	goto retry;
b9ba6d
     }
b9ba6d
 
b9ba6d
+  if (!alloca_aliases_len)
b9ba6d
+    free ((void *) aliases_len);
b9ba6d
+  if (!alloca_key)
b9ba6d
+    free (key);
b9ba6d
+
b9ba6d
   return retval;
b9ba6d
 }
b9ba6d
diff --git a/posix/glob.c b/posix/glob.c
b9ba6d
index 6df083a..79b6e50 100644
b9ba6d
--- a/posix/glob.c
b9ba6d
+++ b/posix/glob.c
b9ba6d
@@ -1,4 +1,4 @@
b9ba6d
-/* Copyright (C) 1991-2002, 2003, 2004, 2005, 2006, 2007, 2008, 2010
b9ba6d
+/* Copyright (C) 1991-2002, 2003, 2004, 2005, 2006, 2007, 2008, 2010, 2011
b9ba6d
    Free Software Foundation, Inc.
b9ba6d
    This file is part of the GNU C Library.
b9ba6d
 
b9ba6d
@@ -199,7 +199,7 @@ static const char *next_brace_sub (const char *begin, int flags) __THROW;
b9ba6d
 
b9ba6d
 static int glob_in_dir (const char *pattern, const char *directory,
b9ba6d
 			int flags, int (*errfunc) (const char *, int),
b9ba6d
-			glob_t *pglob);
b9ba6d
+			glob_t *pglob, size_t alloca_used);
b9ba6d
 extern int __glob_pattern_type (const char *pattern, int quote)
b9ba6d
     attribute_hidden;
b9ba6d
 
b9ba6d
@@ -253,13 +253,18 @@ glob (pattern, flags, errfunc, pglob)
b9ba6d
      glob_t *pglob;
b9ba6d
 {
b9ba6d
   const char *filename;
b9ba6d
-  const char *dirname;
b9ba6d
+  char *dirname = NULL;
b9ba6d
   size_t dirlen;
b9ba6d
   int status;
b9ba6d
   size_t oldcount;
b9ba6d
   int meta;
b9ba6d
   int dirname_modified;
b9ba6d
+  int malloc_dirname = 0;
b9ba6d
   glob_t dirs;
b9ba6d
+  int retval = 0;
b9ba6d
+#ifdef _LIBC
b9ba6d
+  size_t alloca_used = 0;
b9ba6d
+#endif
b9ba6d
 
b9ba6d
   if (pattern == NULL || pglob == NULL || (flags & ~__GLOB_FLAGS) != 0)
b9ba6d
     {
b9ba6d
@@ -308,20 +313,26 @@ glob (pattern, flags, errfunc, pglob)
b9ba6d
 	  const char *next;
b9ba6d
 	  const char *rest;
b9ba6d
 	  size_t rest_len;
b9ba6d
-#ifdef __GNUC__
b9ba6d
-	  char onealt[strlen (pattern) - 1];
b9ba6d
-#else
b9ba6d
-	  char *onealt = (char *) malloc (strlen (pattern) - 1);
b9ba6d
-	  if (onealt == NULL)
b9ba6d
+	  char *onealt;
b9ba6d
+	  size_t pattern_len = strlen (pattern) - 1;
b9ba6d
+#ifdef _LIBC
b9ba6d
+	  int alloca_onealt = __libc_use_alloca (alloca_used + pattern_len);
b9ba6d
+	  if (alloca_onealt)
b9ba6d
+	    onealt = alloca_account (pattern_len, alloca_used);
b9ba6d
+	  else
b9ba6d
+#endif
b9ba6d
 	    {
b9ba6d
-	      if (!(flags & GLOB_APPEND))
b9ba6d
+	      onealt = (char *) malloc (pattern_len);
b9ba6d
+	      if (onealt == NULL)
b9ba6d
 		{
b9ba6d
-		  pglob->gl_pathc = 0;
b9ba6d
-		  pglob->gl_pathv = NULL;
b9ba6d
+		  if (!(flags & GLOB_APPEND))
b9ba6d
+		    {
b9ba6d
+		      pglob->gl_pathc = 0;
b9ba6d
+		      pglob->gl_pathv = NULL;
b9ba6d
+		    }
b9ba6d
+		  return GLOB_NOSPACE;
b9ba6d
 		}
b9ba6d
-	      return GLOB_NOSPACE;
b9ba6d
 	    }
b9ba6d
-#endif
b9ba6d
 
b9ba6d
 	  /* We know the prefix for all sub-patterns.  */
b9ba6d
 	  alt_start = mempcpy (onealt, pattern, begin - pattern);
b9ba6d
@@ -332,9 +343,11 @@ glob (pattern, flags, errfunc, pglob)
b9ba6d
 	  if (next == NULL)
b9ba6d
 	    {
b9ba6d
 	      /* It is an illegal expression.  */
b9ba6d
-#ifndef __GNUC__
b9ba6d
-	      free (onealt);
b9ba6d
+	    illegal_brace:
b9ba6d
+#ifdef _LIBC
b9ba6d
+	      if (__builtin_expect (!alloca_onealt, 0))
b9ba6d
 #endif
b9ba6d
+		free (onealt);
b9ba6d
 	      return glob (pattern, flags & ~GLOB_BRACE, errfunc, pglob);
b9ba6d
 	    }
b9ba6d
 
b9ba6d
@@ -344,13 +357,8 @@ glob (pattern, flags, errfunc, pglob)
b9ba6d
 	    {
b9ba6d
 	      rest = next_brace_sub (rest + 1, flags);
b9ba6d
 	      if (rest == NULL)
b9ba6d
-		{
b9ba6d
-		  /* It is an illegal expression.  */
b9ba6d
-#ifndef __GNUC__
b9ba6d
-		  free (onealt);
b9ba6d
-#endif
b9ba6d
-		  return glob (pattern, flags & ~GLOB_BRACE, errfunc, pglob);
b9ba6d
-		}
b9ba6d
+		/* It is an illegal expression.  */
b9ba6d
+		goto illegal_brace;
b9ba6d
 	    }
b9ba6d
 	  /* Please note that we now can be sure the brace expression
b9ba6d
 	     is well-formed.  */
b9ba6d
@@ -386,9 +394,10 @@ glob (pattern, flags, errfunc, pglob)
b9ba6d
 	      /* If we got an error, return it.  */
b9ba6d
 	      if (result && result != GLOB_NOMATCH)
b9ba6d
 		{
b9ba6d
-#ifndef __GNUC__
b9ba6d
-		  free (onealt);
b9ba6d
+#ifdef _LIBC
b9ba6d
+		  if (__builtin_expect (!alloca_onealt, 0))
b9ba6d
 #endif
b9ba6d
+		    free (onealt);
b9ba6d
 		  if (!(flags & GLOB_APPEND))
b9ba6d
 		    {
b9ba6d
 		      globfree (pglob);
b9ba6d
@@ -406,9 +415,10 @@ glob (pattern, flags, errfunc, pglob)
b9ba6d
 	      assert (next != NULL);
b9ba6d
 	    }
b9ba6d
 
b9ba6d
-#ifndef __GNUC__
b9ba6d
-	  free (onealt);
b9ba6d
+#ifdef _LIBC
b9ba6d
+	  if (__builtin_expect (!alloca_onealt, 0))
b9ba6d
 #endif
b9ba6d
+	    free (onealt);
b9ba6d
 
b9ba6d
 	  if (pglob->gl_pathc != firstc)
b9ba6d
 	    /* We found some entries.  */
b9ba6d
@@ -455,7 +465,7 @@ glob (pattern, flags, errfunc, pglob)
b9ba6d
 	 case is nothing but a notation for a directory.  */
b9ba6d
       if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && pattern[0] == '~')
b9ba6d
 	{
b9ba6d
-	  dirname = pattern;
b9ba6d
+	  dirname = (char *) pattern;
b9ba6d
 	  dirlen = strlen (pattern);
b9ba6d
 
b9ba6d
 	  /* Set FILENAME to NULL as a special flag.  This is ugly but
b9ba6d
@@ -473,9 +483,9 @@ glob (pattern, flags, errfunc, pglob)
b9ba6d
 
b9ba6d
 	  filename = pattern;
b9ba6d
 #ifdef _AMIGA
b9ba6d
-	  dirname = "";
b9ba6d
+	  dirname = (char *) "";
b9ba6d
 #else
b9ba6d
-	  dirname = ".";
b9ba6d
+	  dirname = (char *) ".";
b9ba6d
 #endif
b9ba6d
 	  dirlen = 0;
b9ba6d
 	}
b9ba6d
@@ -485,7 +495,7 @@ glob (pattern, flags, errfunc, pglob)
b9ba6d
 	       && (flags & GLOB_NOESCAPE) == 0))
b9ba6d
     {
b9ba6d
       /* "/pattern" or "\\/pattern".  */
b9ba6d
-      dirname = "/";
b9ba6d
+      dirname = (char *) "/";
b9ba6d
       dirlen = 1;
b9ba6d
       ++filename;
b9ba6d
     }
b9ba6d
@@ -511,7 +521,17 @@ glob (pattern, flags, errfunc, pglob)
b9ba6d
 	     from "d:/", since "d:" and "d:/" are not the same.*/
b9ba6d
 	}
b9ba6d
 #endif
b9ba6d
-      newp = (char *) __alloca (dirlen + 1);
b9ba6d
+#ifdef _LIBC
b9ba6d
+      if (__libc_use_alloca (alloca_used + dirlen + 1))
b9ba6d
+	newp = alloca_account (dirlen + 1, alloca_used);
b9ba6d
+      else
b9ba6d
+#endif
b9ba6d
+	{
b9ba6d
+	  newp = malloc (dirlen + 1);
b9ba6d
+	  if (newp == NULL)
b9ba6d
+	    return GLOB_NOSPACE;
b9ba6d
+	  malloc_dirname = 1;
b9ba6d
+	}
b9ba6d
       *((char *) mempcpy (newp, pattern, dirlen)) = '\0';
b9ba6d
       dirname = newp;
b9ba6d
       ++filename;
b9ba6d
@@ -551,7 +571,8 @@ glob (pattern, flags, errfunc, pglob)
b9ba6d
 	      oldcount = pglob->gl_pathc + pglob->gl_offs;
b9ba6d
 	      goto no_matches;
b9ba6d
 	    }
b9ba6d
-	  return val;
b9ba6d
+	  retval = val;
b9ba6d
+	  goto out;
b9ba6d
 	}
b9ba6d
     }
b9ba6d
 
b9ba6d
@@ -563,7 +584,8 @@ glob (pattern, flags, errfunc, pglob)
b9ba6d
 	      && (dirname[2] == '\0' || dirname[2] == '/')))
b9ba6d
 	{
b9ba6d
 	  /* Look up home directory.  */
b9ba6d
-	  const char *home_dir = getenv ("HOME");
b9ba6d
+	  char *home_dir = getenv ("HOME");
b9ba6d
+	  int malloc_home_dir = 0;
b9ba6d
 # ifdef _AMIGA
b9ba6d
 	  if (home_dir == NULL || home_dir[0] == '\0')
b9ba6d
 	    home_dir = "SYS:";
b9ba6d
@@ -582,7 +604,7 @@ glob (pattern, flags, errfunc, pglob)
b9ba6d
 		/* `sysconf' does not support _SC_LOGIN_NAME_MAX.  Try
b9ba6d
 		   a moderate value.  */
b9ba6d
 		buflen = 20;
b9ba6d
-	      name = (char *) __alloca (buflen);
b9ba6d
+	      name = alloca_account (buflen, alloca_used);
b9ba6d
 
b9ba6d
 	      success = getlogin_r (name, buflen) == 0;
b9ba6d
 	      if (success)
b9ba6d
@@ -592,6 +614,7 @@ glob (pattern, flags, errfunc, pglob)
b9ba6d
 		  long int pwbuflen = GETPW_R_SIZE_MAX ();
b9ba6d
 		  char *pwtmpbuf;
b9ba6d
 		  struct passwd pwbuf;
b9ba6d
+		  int malloc_pwtmpbuf = 0;
b9ba6d
 		  int save = errno;
b9ba6d
 
b9ba6d
 #    ifndef _LIBC
b9ba6d
@@ -600,7 +623,18 @@ glob (pattern, flags, errfunc, pglob)
b9ba6d
 		       Try a moderate value.  */
b9ba6d
 		    pwbuflen = 1024;
b9ba6d
 #    endif
b9ba6d
-		  pwtmpbuf = (char *) __alloca (pwbuflen);
b9ba6d
+		  if (__libc_use_alloca (alloca_used + pwbuflen))
b9ba6d
+		    pwtmpbuf = alloca_account (pwbuflen, alloca_used);
b9ba6d
+		  else
b9ba6d
+		    {
b9ba6d
+		      pwtmpbuf = malloc (pwbuflen);
b9ba6d
+		      if (pwtmpbuf == NULL)
b9ba6d
+			{
b9ba6d
+			  retval = GLOB_NOSPACE;
b9ba6d
+			  goto out;
b9ba6d
+			}
b9ba6d
+		      malloc_pwtmpbuf = 1;
b9ba6d
+		    }
b9ba6d
 
b9ba6d
 		  while (getpwnam_r (name, &pwbuf, pwtmpbuf, pwbuflen, &p)
b9ba6d
 			 != 0)
b9ba6d
@@ -610,46 +644,115 @@ glob (pattern, flags, errfunc, pglob)
b9ba6d
 			  p = NULL;
b9ba6d
 			  break;
b9ba6d
 			}
b9ba6d
-#    ifdef _LIBC
b9ba6d
-		      pwtmpbuf = extend_alloca (pwtmpbuf, pwbuflen,
b9ba6d
+
b9ba6d
+		      if (!malloc_pwtmpbuf
b9ba6d
+			  && __libc_use_alloca (alloca_used
b9ba6d
+						+ 2 * pwbuflen))
b9ba6d
+			pwtmpbuf = extend_alloca_account (pwtmpbuf, pwbuflen,
b9ba6d
+							  2 * pwbuflen,
b9ba6d
+							  alloca_used);
b9ba6d
+		      else
b9ba6d
+			{
b9ba6d
+			  char *newp = realloc (malloc_pwtmpbuf
b9ba6d
+						? pwtmpbuf : NULL,
b9ba6d
 						2 * pwbuflen);
b9ba6d
-#    else
b9ba6d
-		      pwbuflen *= 2;
b9ba6d
-		      pwtmpbuf = (char *) __alloca (pwbuflen);
b9ba6d
-#    endif
b9ba6d
+			  if (newp == NULL)
b9ba6d
+			    {
b9ba6d
+			      if (__builtin_expect (malloc_pwtmpbuf, 0))
b9ba6d
+				free (pwtmpbuf);
b9ba6d
+			      retval = GLOB_NOSPACE;
b9ba6d
+			      goto out;
b9ba6d
+			    }
b9ba6d
+			  pwtmpbuf = newp;
b9ba6d
+			  pwbuflen = 2 * pwbuflen;
b9ba6d
+			  malloc_pwtmpbuf = 1;
b9ba6d
+			}
b9ba6d
 		      __set_errno (save);
b9ba6d
 		    }
b9ba6d
 #   else
b9ba6d
 		  p = getpwnam (name);
b9ba6d
 #   endif
b9ba6d
 		  if (p != NULL)
b9ba6d
-		    home_dir = p->pw_dir;
b9ba6d
+		    {
b9ba6d
+		      if (!malloc_pwtmpbuf)
b9ba6d
+			home_dir = p->pw_dir;
b9ba6d
+		      else
b9ba6d
+			{
b9ba6d
+			  size_t home_dir_len = strlen (p->pw_dir) + 1;
b9ba6d
+			  if (__libc_use_alloca (alloca_used + home_dir_len))
b9ba6d
+			    home_dir = alloca_account (home_dir_len,
b9ba6d
+						       alloca_used);
b9ba6d
+			  else
b9ba6d
+			    {
b9ba6d
+			      home_dir = malloc (home_dir_len);
b9ba6d
+			      if (home_dir == NULL)
b9ba6d
+				{
b9ba6d
+				  free (pwtmpbuf);
b9ba6d
+				  retval = GLOB_NOSPACE;
b9ba6d
+				  goto out;
b9ba6d
+				}
b9ba6d
+			      malloc_home_dir = 1;
b9ba6d
+			    }
b9ba6d
+			  memcpy (home_dir, p->pw_dir, home_dir_len);
b9ba6d
+
b9ba6d
+			  free (pwtmpbuf);
b9ba6d
+			}
b9ba6d
+		    }
b9ba6d
 		}
b9ba6d
 	    }
b9ba6d
 	  if (home_dir == NULL || home_dir[0] == '\0')
b9ba6d
 	    {
b9ba6d
 	      if (flags & GLOB_TILDE_CHECK)
b9ba6d
-		return GLOB_NOMATCH;
b9ba6d
+		{
b9ba6d
+		  if (__builtin_expect (malloc_home_dir, 0))
b9ba6d
+		    free (home_dir);
b9ba6d
+		  retval = GLOB_NOMATCH;
b9ba6d
+		  goto out;
b9ba6d
+		}
b9ba6d
 	      else
b9ba6d
-		home_dir = "~"; /* No luck.  */
b9ba6d
+		home_dir = (char *) "~"; /* No luck.  */
b9ba6d
 	    }
b9ba6d
 #  endif /* WINDOWS32 */
b9ba6d
 # endif
b9ba6d
 	  /* Now construct the full directory.  */
b9ba6d
 	  if (dirname[1] == '\0')
b9ba6d
 	    {
b9ba6d
+	      if (__builtin_expect (malloc_dirname, 0))
b9ba6d
+		free (dirname);
b9ba6d
+
b9ba6d
 	      dirname = home_dir;
b9ba6d
 	      dirlen = strlen (dirname);
b9ba6d
+	      malloc_dirname = malloc_home_dir;
b9ba6d
 	    }
b9ba6d
 	  else
b9ba6d
 	    {
b9ba6d
 	      char *newp;
b9ba6d
 	      size_t home_len = strlen (home_dir);
b9ba6d
-	      newp = (char *) __alloca (home_len + dirlen);
b9ba6d
+	      int use_alloca = __libc_use_alloca (alloca_used
b9ba6d
+						  + home_len + dirlen);
b9ba6d
+	      if (use_alloca)
b9ba6d
+		newp = alloca_account (home_len + dirlen, alloca_used);
b9ba6d
+	      else
b9ba6d
+		{
b9ba6d
+		  newp = malloc (home_len + dirlen);
b9ba6d
+		  if (newp == NULL)
b9ba6d
+		    {
b9ba6d
+		      if (__builtin_expect (malloc_home_dir, 0))
b9ba6d
+			free (home_dir);
b9ba6d
+		      retval = GLOB_NOSPACE;
b9ba6d
+		      goto out;
b9ba6d
+		    }
b9ba6d
+		}
b9ba6d
+
b9ba6d
 	      mempcpy (mempcpy (newp, home_dir, home_len),
b9ba6d
 		       &dirname[1], dirlen);
b9ba6d
+
b9ba6d
+	      if (__builtin_expect (malloc_dirname, 0))
b9ba6d
+		free (dirname);
b9ba6d
+
b9ba6d
 	      dirname = newp;
b9ba6d
 	      dirlen += home_len - 1;
b9ba6d
+	      malloc_dirname = !use_alloca;
b9ba6d
 	    }
b9ba6d
 	  dirname_modified = 1;
b9ba6d
 	}
b9ba6d
@@ -657,7 +760,8 @@ glob (pattern, flags, errfunc, pglob)
b9ba6d
       else
b9ba6d
 	{
b9ba6d
 	  char *end_name = strchr (dirname, '/');
b9ba6d
-	  const char *user_name;
b9ba6d
+	  char *user_name;
b9ba6d
+	  int malloc_user_name = 0;
b9ba6d
 	  const char *home_dir;
b9ba6d
 	  char *unescape = NULL;
b9ba6d
 
b9ba6d
@@ -677,7 +781,18 @@ glob (pattern, flags, errfunc, pglob)
b9ba6d
 	  else
b9ba6d
 	    {
b9ba6d
 	      char *newp;
b9ba6d
-	      newp = (char *) __alloca (end_name - dirname);
b9ba6d
+	      if (__libc_use_alloca (alloca_used + (end_name - dirname)))
b9ba6d
+		newp = alloca_account (end_name - dirname, alloca_used);
b9ba6d
+	      else
b9ba6d
+		{
b9ba6d
+		  newp = malloc (end_name - dirname);
b9ba6d
+		  if (newp == NULL)
b9ba6d
+		    {
b9ba6d
+		      retval = GLOB_NOSPACE;
b9ba6d
+		      goto out;
b9ba6d
+		    }
b9ba6d
+		  malloc_user_name = 1;
b9ba6d
+		}
b9ba6d
 	      if (unescape != NULL)
b9ba6d
 		{
b9ba6d
 		  char *p = mempcpy (newp, dirname + 1,
b9ba6d
@@ -714,6 +829,7 @@ glob (pattern, flags, errfunc, pglob)
b9ba6d
 #  if defined HAVE_GETPWNAM_R || defined _LIBC
b9ba6d
 	    long int buflen = GETPW_R_SIZE_MAX ();
b9ba6d
 	    char *pwtmpbuf;
b9ba6d
+	    int malloc_pwtmpbuf = 0;
b9ba6d
 	    struct passwd pwbuf;
b9ba6d
 	    int save = errno;
b9ba6d
 
b9ba6d
@@ -723,7 +839,21 @@ glob (pattern, flags, errfunc, pglob)
b9ba6d
 		 moderate value.  */
b9ba6d
 	      buflen = 1024;
b9ba6d
 #   endif
b9ba6d
-	    pwtmpbuf = (char *) __alloca (buflen);
b9ba6d
+	    if (__libc_use_alloca (alloca_used + buflen))
b9ba6d
+	      pwtmpbuf = alloca_account (buflen, alloca_used);
b9ba6d
+	    else
b9ba6d
+	      {
b9ba6d
+		pwtmpbuf = malloc (buflen);
b9ba6d
+		if (pwtmpbuf == NULL)
b9ba6d
+		  {
b9ba6d
+		  nomem_getpw:
b9ba6d
+		    if (__builtin_expect (malloc_user_name, 0))
b9ba6d
+		      free (user_name);
b9ba6d
+		    retval = GLOB_NOSPACE;
b9ba6d
+		    goto out;
b9ba6d
+		  }
b9ba6d
+		malloc_pwtmpbuf = 1;
b9ba6d
+	      }
b9ba6d
 
b9ba6d
 	    while (getpwnam_r (user_name, &pwbuf, pwtmpbuf, buflen, &p) != 0)
b9ba6d
 	      {
b9ba6d
@@ -732,40 +862,77 @@ glob (pattern, flags, errfunc, pglob)
b9ba6d
 		    p = NULL;
b9ba6d
 		    break;
b9ba6d
 		  }
b9ba6d
-#   ifdef _LIBC
b9ba6d
-		pwtmpbuf = extend_alloca (pwtmpbuf, buflen, 2 * buflen);
b9ba6d
-#   else
b9ba6d
-		buflen *= 2;
b9ba6d
-		pwtmpbuf = __alloca (buflen);
b9ba6d
-#   endif
b9ba6d
+		if (!malloc_pwtmpbuf
b9ba6d
+		    && __libc_use_alloca (alloca_used + 2 * buflen))
b9ba6d
+		  pwtmpbuf = extend_alloca_account (pwtmpbuf, buflen,
b9ba6d
+						    2 * buflen, alloca_used);
b9ba6d
+		else
b9ba6d
+		  {
b9ba6d
+		    char *newp = realloc (malloc_pwtmpbuf ? pwtmpbuf : NULL,
b9ba6d
+					  2 * buflen);
b9ba6d
+		    if (newp == NULL)
b9ba6d
+		      {
b9ba6d
+			if (__builtin_expect (malloc_pwtmpbuf, 0))
b9ba6d
+			  free (pwtmpbuf);
b9ba6d
+			goto nomem_getpw;
b9ba6d
+		      }
b9ba6d
+		    pwtmpbuf = newp;
b9ba6d
+		    malloc_pwtmpbuf = 1;
b9ba6d
+		  }
b9ba6d
 		__set_errno (save);
b9ba6d
 	      }
b9ba6d
 #  else
b9ba6d
 	    p = getpwnam (user_name);
b9ba6d
 #  endif
b9ba6d
+
b9ba6d
+	    if (__builtin_expect (malloc_user_name, 0))
b9ba6d
+	      free (user_name);
b9ba6d
+
b9ba6d
+	    /* If we found a home directory use this.  */
b9ba6d
 	    if (p != NULL)
b9ba6d
-	      home_dir = p->pw_dir;
b9ba6d
+	      {
b9ba6d
+		size_t home_len = strlen (p->pw_dir);
b9ba6d
+		size_t rest_len = end_name == NULL ? 0 : strlen (end_name);
b9ba6d
+
b9ba6d
+		if (__builtin_expect (malloc_dirname, 0))
b9ba6d
+		  free (dirname);
b9ba6d
+		malloc_dirname = 0;
b9ba6d
+
b9ba6d
+		if (__libc_use_alloca (alloca_used + home_len + rest_len + 1))
b9ba6d
+		  dirname = alloca_account (home_len + rest_len + 1,
b9ba6d
+					    alloca_used);
b9ba6d
+		else
b9ba6d
+		  {
b9ba6d
+		    dirname = malloc (home_len + rest_len + 1);
b9ba6d
+		    if (dirname == NULL)
b9ba6d
+		      {
b9ba6d
+			if (__builtin_expect (malloc_pwtmpbuf, 0))
b9ba6d
+			  free (pwtmpbuf);
b9ba6d
+			retval = GLOB_NOSPACE;
b9ba6d
+			goto out;
b9ba6d
+		      }
b9ba6d
+		    malloc_dirname = 1;
b9ba6d
+		  }
b9ba6d
+		*((char *) mempcpy (mempcpy (dirname, p->pw_dir, home_len),
b9ba6d
+				    end_name, rest_len)) = '\0';
b9ba6d
+
b9ba6d
+		dirlen = home_len + rest_len;
b9ba6d
+		dirname_modified = 1;
b9ba6d
+
b9ba6d
+		if (__builtin_expect (malloc_pwtmpbuf, 0))
b9ba6d
+		  free (pwtmpbuf);
b9ba6d
+	      }
b9ba6d
 	    else
b9ba6d
-	      home_dir = NULL;
b9ba6d
+	      {
b9ba6d
+		if (__builtin_expect (malloc_pwtmpbuf, 0))
b9ba6d
+		  free (pwtmpbuf);
b9ba6d
+
b9ba6d
+		if (flags & GLOB_TILDE_CHECK)
b9ba6d
+		  /* We have to regard it as an error if we cannot find the
b9ba6d
+		     home directory.  */
b9ba6d
+		  return GLOB_NOMATCH;
b9ba6d
+	      }
b9ba6d
 	  }
b9ba6d
-	  /* If we found a home directory use this.  */
b9ba6d
-	  if (home_dir != NULL)
b9ba6d
-	    {
b9ba6d
-	      char *newp;
b9ba6d
-	      size_t home_len = strlen (home_dir);
b9ba6d
-	      size_t rest_len = end_name == NULL ? 0 : strlen (end_name);
b9ba6d
-	      newp = (char *) __alloca (home_len + rest_len + 1);
b9ba6d
-	      *((char *) mempcpy (mempcpy (newp, home_dir, home_len),
b9ba6d
-				  end_name, rest_len)) = '\0';
b9ba6d
-	      dirname = newp;
b9ba6d
-	      dirlen = home_len + rest_len;
b9ba6d
-	      dirname_modified = 1;
b9ba6d
-	    }
b9ba6d
-	  else
b9ba6d
-	    if (flags & GLOB_TILDE_CHECK)
b9ba6d
-	      /* We have to regard it as an error if we cannot find the
b9ba6d
-		 home directory.  */
b9ba6d
-	      return GLOB_NOMATCH;
b9ba6d
 	}
b9ba6d
 # endif	/* Not Amiga && not WINDOWS32.  */
b9ba6d
     }
b9ba6d
@@ -899,7 +1066,7 @@ glob (pattern, flags, errfunc, pglob)
b9ba6d
 	  status = glob_in_dir (filename, dirs.gl_pathv[i],
b9ba6d
 				((flags | GLOB_APPEND)
b9ba6d
 				 & ~(GLOB_NOCHECK | GLOB_NOMAGIC)),
b9ba6d
-				errfunc, pglob);
b9ba6d
+				errfunc, pglob, alloca_used);
b9ba6d
 	  if (status == GLOB_NOMATCH)
b9ba6d
 	    /* No matches in this directory.  Try the next.  */
b9ba6d
 	    continue;
b9ba6d
@@ -1000,7 +1167,8 @@ glob (pattern, flags, errfunc, pglob)
b9ba6d
 	}
b9ba6d
       if (dirname_modified)
b9ba6d
 	flags &= ~(GLOB_NOCHECK | GLOB_NOMAGIC);
b9ba6d
-      status = glob_in_dir (filename, dirname, flags, errfunc, pglob);
b9ba6d
+      status = glob_in_dir (filename, dirname, flags, errfunc, pglob,
b9ba6d
+			    alloca_used);
b9ba6d
       if (status != 0)
b9ba6d
 	{
b9ba6d
 	  if (status == GLOB_NOMATCH && flags != orig_flags
b9ba6d
@@ -1063,7 +1231,11 @@ glob (pattern, flags, errfunc, pglob)
b9ba6d
 	     sizeof (char *), collated_compare);
b9ba6d
     }
b9ba6d
 
b9ba6d
-  return 0;
b9ba6d
+ out:
b9ba6d
+  if (__builtin_expect (malloc_dirname, 0))
b9ba6d
+    free (dirname);
b9ba6d
+
b9ba6d
+  return retval;
b9ba6d
 }
b9ba6d
 #if defined _LIBC && !defined glob
b9ba6d
 libc_hidden_def (glob)
b9ba6d
@@ -1273,7 +1445,7 @@ link_exists2_p (const char *dir, size_t dirlen, const char *fname,
b9ba6d
 static int
b9ba6d
 glob_in_dir (const char *pattern, const char *directory, int flags,
b9ba6d
 	     int (*errfunc) (const char *, int),
b9ba6d
-	     glob_t *pglob)
b9ba6d
+	     glob_t *pglob, size_t alloca_used)
b9ba6d
 {
b9ba6d
   size_t dirlen = strlen (directory);
b9ba6d
   void *stream = NULL;
b9ba6d
@@ -1288,11 +1460,12 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
b9ba6d
   struct globnames *names = &init_names;
b9ba6d
   struct globnames *names_alloca = &init_names;
b9ba6d
   size_t nfound = 0;
b9ba6d
-  size_t allocasize = sizeof (init_names);
b9ba6d
   size_t cur = 0;
b9ba6d
   int meta;
b9ba6d
   int save;
b9ba6d
 
b9ba6d
+  alloca_used += sizeof (init_names);
b9ba6d
+
b9ba6d
   init_names.next = NULL;
b9ba6d
   init_names.count = INITIAL_COUNT;
b9ba6d
 
b9ba6d
@@ -1308,20 +1481,36 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
b9ba6d
     {
b9ba6d
       /* Since we use the normal file functions we can also use stat()
b9ba6d
 	 to verify the file is there.  */
b9ba6d
-      struct stat st;
b9ba6d
-      struct_stat64 st64;
b9ba6d
+      union
b9ba6d
+      {
b9ba6d
+	struct stat st;
b9ba6d
+	struct_stat64 st64;
b9ba6d
+      } ust;
b9ba6d
       size_t patlen = strlen (pattern);
b9ba6d
-      char *fullname = (char *) __alloca (dirlen + 1 + patlen + 1);
b9ba6d
+      int alloca_fullname = __libc_use_alloca (alloca_used
b9ba6d
+					       + dirlen + 1 + patlen + 1);
b9ba6d
+      char *fullname;
b9ba6d
+      if (alloca_fullname)
b9ba6d
+	fullname = alloca_account (dirlen + 1 + patlen + 1, alloca_used);
b9ba6d
+      else
b9ba6d
+	{
b9ba6d
+	  fullname = malloc (dirlen + 1 + patlen + 1);
b9ba6d
+	  if (fullname == NULL)
b9ba6d
+	    return GLOB_NOSPACE;
b9ba6d
+	}
b9ba6d
 
b9ba6d
       mempcpy (mempcpy (mempcpy (fullname, directory, dirlen),
b9ba6d
 			"/", 1),
b9ba6d
 	       pattern, patlen + 1);
b9ba6d
       if ((__builtin_expect (flags & GLOB_ALTDIRFUNC, 0)
b9ba6d
-	   ? (*pglob->gl_stat) (fullname, &st)
b9ba6d
-	   : __stat64 (fullname, &st64)) == 0)
b9ba6d
+	   ? (*pglob->gl_stat) (fullname, &ust.st)
b9ba6d
+	   : __stat64 (fullname, &ust.st64)) == 0)
b9ba6d
 	/* We found this file to be existing.  Now tell the rest
b9ba6d
 	   of the function to copy this name into the result.  */
b9ba6d
 	flags |= GLOB_NOCHECK;
b9ba6d
+
b9ba6d
+      if (__builtin_expect (!alloca_fullname, 0))
b9ba6d
+	free (fullname);
b9ba6d
     }
b9ba6d
   else
b9ba6d
     {
b9ba6d
@@ -1409,9 +1598,9 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
b9ba6d
 			  size_t size = (sizeof (struct globnames)
b9ba6d
 					 + ((count - INITIAL_COUNT)
b9ba6d
 					    * sizeof (char *)));
b9ba6d
-			  allocasize += size;
b9ba6d
-			  if (__libc_use_alloca (allocasize))
b9ba6d
-			    newnames = names_alloca = __alloca (size);
b9ba6d
+			  if (__libc_use_alloca (alloca_used + size))
b9ba6d
+			    newnames = names_alloca
b9ba6d
+			      = alloca_account (size, alloca_used);
b9ba6d
 			  else if ((newnames = malloc (size))
b9ba6d
 				   == NULL)
b9ba6d
 			    goto memory_error;