Blame SOURCES/glibc-rh797094-2.patch

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