[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[commits] r13914 - in /fsf/trunk/libc: ./ include/ libio/ locale/ localedata/ stdio-common/ sysdeps/posix/



Author: eglibc
Date: Sat May 21 00:03:50 2011
New Revision: 13914

Log:
Import glibc-mainline for 2011-05-21

Added:
    fsf/trunk/libc/localedata/bug-setlocale1.c   (with props)
Modified:
    fsf/trunk/libc/ChangeLog
    fsf/trunk/libc/NEWS
    fsf/trunk/libc/include/alloca.h
    fsf/trunk/libc/libio/filedoalloc.c
    fsf/trunk/libc/locale/setlocale.c
    fsf/trunk/libc/localedata/ChangeLog
    fsf/trunk/libc/localedata/Makefile
    fsf/trunk/libc/stdio-common/perror.c
    fsf/trunk/libc/stdio-common/vfprintf.c
    fsf/trunk/libc/sysdeps/posix/getaddrinfo.c

Modified: fsf/trunk/libc/ChangeLog
==============================================================================
--- fsf/trunk/libc/ChangeLog (original)
+++ fsf/trunk/libc/ChangeLog Sat May 21 00:03:50 2011
@@ -1,4 +1,23 @@
+2011-05-21  Ulrich Drepper  <drepper@xxxxxxxxx>
+
+	[BZ #12788]
+	* locale/setlocale.c (new_composite_name): Fix test to check for
+	identical name of all categories.
+
+	[BZ #12792]
+	* libio/filedoalloc.c (local_isatty): New function.
+	(_IO_file_doallocate): Use local_isatty.
+	* stdio-common/perror.c (perror): In case a new stream is used
+	forward the stream error.
+	* stdio-common/vfprintf.c (ARGCHECK): For read-only streams also set
+	error flag.
+
 2011-05-20  Ulrich Drepper  <drepper@xxxxxxxxx>
+
+	[BZ #11869]
+	* sysdeps/posix/getaddrinfo.c (gaih_inet): Don't unconditionally use
+	alloca.
+	* include/alloca.h (extend_alloca_account): Define.
 
 	[BZ #11857]
 	* posix/regex.h: Fix comments with documentation of user-accessible

Modified: fsf/trunk/libc/NEWS
==============================================================================
--- fsf/trunk/libc/NEWS (original)
+++ fsf/trunk/libc/NEWS Sat May 21 00:03:50 2011
@@ -1,4 +1,4 @@
-GNU C Library NEWS -- history of user-visible changes.  2011-5-20
+GNU C Library NEWS -- history of user-visible changes.  2011-5-21
 Copyright (C) 1992-2009, 2010, 2011 Free Software Foundation, Inc.
 See the end for copying conditions.
 
@@ -11,12 +11,12 @@
 
   386, 6420, 7101, 9730, 9732, 9809, 10138, 10149, 10157, 11257, 11258,
   11487, 11532, 11578, 11653, 11668, 11697, 11724, 11820, 11837, 11857,
-  11892, 11895, 11901, 11945, 11947, 11952, 11987, 12052, 12083, 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
+  11869, 11892, 11895, 11901, 11945, 11947, 11952, 11987, 12052, 12083,
+  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, 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.

Modified: fsf/trunk/libc/include/alloca.h
==============================================================================
--- fsf/trunk/libc/include/alloca.h (original)
+++ fsf/trunk/libc/include/alloca.h Sat May 21 00:03:50 2011
@@ -49,15 +49,24 @@
 
 #if defined stackinfo_get_sp && defined stackinfo_sub_sp
 # define alloca_account(size, avar) \
-  ({ void *old__ = stackinfo_get_sp ();			\
-     void *m__ = __alloca (size);			\
-     avar += stackinfo_sub_sp (old__);			\
+  ({ void *old__ = stackinfo_get_sp ();					      \
+     void *m__ = __alloca (size);					      \
+     avar += stackinfo_sub_sp (old__);					      \
+     m__; })
+# define extend_alloca_account(buf, len, newlen, avar) \
+  ({ void *old__ = stackinfo_get_sp ();					      \
+     void *m__ = extend_alloca (buf, len, newlen);			      \
+     avar += stackinfo_sub_sp (old__);					      \
      m__; })
 #else
 # define alloca_account(size, avar) \
-  ({ size_t s__ = (size);		    \
-     avar += s__;			    \
+  ({ size_t s__ = (size);						      \
+     avar += s__;							      \
      __alloca (s__); })
+# define extend_alloca_account(buf, len, newlen, avar) \
+  ({ size_t s__ = (newlen);						      \
+     avar += s__;							      \
+     extend_alloca (buf, len, s__); })
 #endif
 
 #endif

Modified: fsf/trunk/libc/libio/filedoalloc.c
==============================================================================
--- fsf/trunk/libc/libio/filedoalloc.c (original)
+++ fsf/trunk/libc/libio/filedoalloc.c Sat May 21 00:03:50 2011
@@ -1,4 +1,4 @@
-/* Copyright (C) 1993, 1997, 2001, 2002 Free Software Foundation, Inc.
+/* Copyright (C) 1993, 1997, 2001, 2002, 2011 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
@@ -41,7 +41,7 @@
    4. Neither the name of the University nor the names of its contributors
       may be used to endorse or promote products derived from this software
       without specific prior written permission.
-   
+
    THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
@@ -73,6 +73,17 @@
 
 # include <device-nrs.h>
 #endif
+
+
+static int
+local_isatty (int fd)
+{
+  int save_errno = errno;
+  int res = isatty (fd);
+  __set_errno (save_errno);
+  return res;
+}
+
 
 /*
  * Allocate a file buffer, or switch to unbuffered I/O.
@@ -109,7 +120,7 @@
 #ifdef DEV_TTY_P
 	      DEV_TTY_P (&st) ||
 #endif
-	      isatty (fp->_fileno))
+	      local_isatty (fp->_fileno))
 	    fp->_flags |= _IO_LINE_BUF;
 	}
 #if _IO_HAVE_ST_BLKSIZE

Modified: fsf/trunk/libc/locale/setlocale.c
==============================================================================
--- fsf/trunk/libc/locale/setlocale.c (original)
+++ fsf/trunk/libc/locale/setlocale.c Sat May 21 00:03:50 2011
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991, 1992, 1995-2000, 2002, 2003, 2004, 2006, 2008, 2010
+/* Copyright (C) 1991, 1992, 1995-2000, 2002, 2003, 2004, 2006, 2008, 2010, 2011
    Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
@@ -155,7 +155,7 @@
 			    _nl_global_locale.__names[i]);
 	last_len = strlen (name);
 	cumlen += _nl_category_name_sizes[i] + 1 + last_len + 1;
-	if (i > 0 && same && strcmp (name, newnames[0]) != 0)
+	if (same && name != newnames[0] && strcmp (name, newnames[0]) != 0)
 	  same = 0;
       }
 

Modified: fsf/trunk/libc/localedata/ChangeLog
==============================================================================
--- fsf/trunk/libc/localedata/ChangeLog (original)
+++ fsf/trunk/libc/localedata/ChangeLog Sat May 21 00:03:50 2011
@@ -1,3 +1,9 @@
+2011-05-21  Ulrich Drepper  <drepper@xxxxxxxxx>
+
+	[BZ #12788]
+	* bug-setlocale1.c: New file.
+	* Makefile: Add rules to build and run bug-setlocale1.
+
 2011-05-17  Ulrich Drepper  <drepper@xxxxxxxxx>
 
 	[BZ #11837]

Modified: fsf/trunk/libc/localedata/Makefile
==============================================================================
--- fsf/trunk/libc/localedata/Makefile (original)
+++ fsf/trunk/libc/localedata/Makefile Sat May 21 00:03:50 2011
@@ -1,4 +1,4 @@
-# Copyright (C) 1996-2003,2005,2007,2008,2009 Free Software Foundation, Inc.
+# Copyright (C) 1996-2003,2005,2007,2008,2009,2011 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
@@ -94,7 +94,7 @@
 
 tests = $(locale_test_suite) tst-digits tst-setlocale bug-iconv-trans \
 	tst-leaks tst-mbswcs6 tst-xlocale1 tst-xlocale2 bug-usesetlocale \
-	tst-strfmon1 tst-sscanf tst-strptime
+	tst-strfmon1 tst-sscanf tst-strptime bug-setlocale1
 ifeq (yes,$(build-shared))
 ifneq (no,$(PERL))
 tests: $(objpfx)mtrace-tst-leaks
@@ -301,5 +301,8 @@
 $(objpfx)mtrace-tst-leaks: $(objpfx)tst-leaks.out
 	$(common-objpfx)malloc/mtrace $(objpfx)tst-leaks.mtrace > $@
 
+bug-setlocale1-ENV = LOCPATH=$(common-objpfx)localedata
+bug-setlocale1-ARGS = $(common-objpfx)
+
 $(objdir)/iconvdata/gconv-modules:
 	$(MAKE) -C ../iconvdata subdir=iconvdata $@

Added: fsf/trunk/libc/localedata/bug-setlocale1.c
==============================================================================
--- fsf/trunk/libc/localedata/bug-setlocale1.c (added)
+++ fsf/trunk/libc/localedata/bug-setlocale1.c Sat May 21 00:03:50 2011
@@ -1,0 +1,132 @@
+// BZ 12788
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+
+static int
+do_test (int argc, char *argv[])
+{
+  if (argc > 1)
+    {
+      char *newargv[5];
+      asprintf (&newargv[0], "%self/ld.so", argv[1]);
+      if (newargv[0] == NULL)
+	{
+	  puts ("asprintf failed");
+	  return 1;
+	}
+      newargv[1] = (char *) "--library-path";
+      newargv[2] = argv[1];
+      newargv[3] = argv[0];
+      newargv[4] = NULL;
+
+      char *env[3];
+      env[0] = (char *) "LC_CTYPE=de_DE.UTF-8";
+      char *loc = getenv ("LOCPATH");
+      if (loc == NULL || loc[0] == '\0')
+	{
+	  puts ("LOCPATH not set");
+	  return 1;
+	}
+      asprintf (&env[1], "LOCPATH=%s", loc);
+      if (newargv[0] == NULL)
+	{
+	  puts ("second asprintf failed");
+	  return 1;
+	}
+      env[2] = NULL;
+
+      execve (newargv[0], newargv, env);
+
+      puts ("execve returned");
+      return 1;
+    }
+
+  int result = 0;
+
+  char *a = setlocale (LC_ALL, "");
+  printf ("setlocale(LC_ALL, \"\") = %s\n", a);
+  if (a == NULL)
+    return 1;
+  a = strdupa (a);
+
+  char *b = setlocale (LC_CTYPE, "");
+  printf ("setlocale(LC_CTYPE, \"\") = %s\n", b);
+  if (b == NULL)
+    return 1;
+
+  char *c = setlocale (LC_ALL, NULL);
+  printf ("setlocale(LC_ALL, NULL) = %s\n", c);
+  if (c == NULL)
+    return 1;
+  c = strdupa (c);
+
+  if (strcmp (a, c) != 0)
+    {
+      puts ("*** first and third result do not match");
+      result = 1;
+    }
+
+  char *d = setlocale (LC_NUMERIC, "");
+  printf ("setlocale(LC_NUMERIC, \"\") = %s\n", d);
+  if (d == NULL)
+    return 1;
+
+  if (strcmp (d, "C") != 0)
+    {
+      puts ("*** LC_NUMERIC not C");
+      result = 1;
+    }
+
+  char *e = setlocale (LC_ALL, NULL);
+  printf ("setlocale(LC_ALL, NULL) = %s\n", e);
+  if (e == NULL)
+    return 1;
+
+  if (strcmp (a, e) != 0)
+    {
+      puts ("*** first and fifth result do not match");
+      result = 1;
+    }
+
+  char *f = setlocale (LC_ALL, "C");
+  printf ("setlocale(LC_ALL, \"C\") = %s\n", f);
+  if (f == NULL)
+    return 1;
+
+  if (strcmp (f, "C") != 0)
+    {
+      puts ("*** LC_ALL not C");
+      result = 1;
+    }
+
+  char *g = setlocale (LC_ALL, NULL);
+  printf ("setlocale(LC_ALL, NULL) = %s\n", g);
+  if (g == NULL)
+    return 1;
+
+  if (strcmp (g, "C") != 0)
+    {
+      puts ("*** LC_ALL not C");
+      result = 1;
+    }
+
+  char *h = setlocale (LC_CTYPE, NULL);
+  printf ("setlocale(LC_CTYPE, NULL) = %s\n", h);
+  if (h == NULL)
+    return 1;
+
+  if (strcmp (h, "C") != 0)
+    {
+      puts ("*** LC_CTYPE not C");
+      result = 1;
+    }
+
+  return result;
+}
+
+#define TEST_FUNCTION do_test (argc, argv)
+#include "../test-skeleton.c"

Propchange: fsf/trunk/libc/localedata/bug-setlocale1.c
------------------------------------------------------------------------------
    svn:mime-type = text/cpp

Modified: fsf/trunk/libc/stdio-common/perror.c
==============================================================================
--- fsf/trunk/libc/stdio-common/perror.c (original)
+++ fsf/trunk/libc/stdio-common/perror.c Sat May 21 00:03:50 2011
@@ -1,4 +1,5 @@
-/* Copyright (C) 1991-1993,1997,1998,2000-2005 Free Software Foundation, Inc.
+/* Copyright (C) 1991-1993,1997,1998,2000-2005,2011
+   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
@@ -73,6 +74,10 @@
 	 position.  Since the stderr stream wasn't used so far we just
 	 write to the descriptor.  */
       perror_internal (fp, s, errnum);
+
+      if (_IO_ferror_unlocked (fp))
+	stderr->_flags |= _IO_ERR_SEEN;
+
       /* Close the stream.  */
       fclose (fp);
     }

Modified: fsf/trunk/libc/stdio-common/vfprintf.c
==============================================================================
--- fsf/trunk/libc/stdio-common/vfprintf.c (original)
+++ fsf/trunk/libc/stdio-common/vfprintf.c Sat May 21 00:03:50 2011
@@ -52,6 +52,7 @@
       CHECK_FILE (S, -1);						      \
       if (S->_flags & _IO_NO_WRITES)					      \
 	{								      \
+	  S->_flags |= _IO_ERR_SEEN;					      \
 	  __set_errno (EBADF);						      \
 	  return -1;							      \
 	}								      \

Modified: fsf/trunk/libc/sysdeps/posix/getaddrinfo.c
==============================================================================
--- fsf/trunk/libc/sysdeps/posix/getaddrinfo.c (original)
+++ fsf/trunk/libc/sysdeps/posix/getaddrinfo.c Sat May 21 00:03:50 2011
@@ -278,6 +278,7 @@
   bool got_ipv6 = false;
   const char *canon = NULL;
   const char *orig_name = name;
+  size_t alloca_used = 0;
 
   if (req->ai_protocol || req->ai_socktype)
     {
@@ -310,7 +311,7 @@
 	  if (tp->name[0])
 	    {
 	      st = (struct gaih_servtuple *)
-		__alloca (sizeof (struct gaih_servtuple));
+		alloca_account (sizeof (struct gaih_servtuple), alloca_used);
 
 	      if ((rc = gaih_inet_serv (service->name, tp, req, st)))
 		return rc;
@@ -334,7 +335,8 @@
 		    continue;
 
 		  newp = (struct gaih_servtuple *)
-		    __alloca (sizeof (struct gaih_servtuple));
+		    alloca_account (sizeof (struct gaih_servtuple),
+				    alloca_used);
 
 		  if ((rc = gaih_inet_serv (service->name, tp, req, newp)))
 		    {
@@ -362,7 +364,7 @@
 
       if (req->ai_socktype || req->ai_protocol)
 	{
-	  st = __alloca (sizeof (struct gaih_servtuple));
+	  st = alloca_account (sizeof (struct gaih_servtuple), alloca_used);
 	  st->next = NULL;
 	  st->socktype = tp->socktype;
 	  st->protocol = ((tp->protoflag & GAI_PROTO_PROTOANY)
@@ -379,7 +381,8 @@
 	      {
 		struct gaih_servtuple *newp;
 
-		newp = __alloca (sizeof (struct gaih_servtuple));
+		newp = alloca_account (sizeof (struct gaih_servtuple),
+				       alloca_used);
 		newp->next = NULL;
 		newp->socktype = tp->socktype;
 		newp->protocol = tp->protocol;
@@ -391,10 +394,17 @@
 	}
     }
 
+  bool malloc_name = false;
+  bool malloc_addrmem = false;
+  struct gaih_addrtuple *addrmem = NULL;
+  bool malloc_canonbuf = false;
+  char *canonbuf = NULL;
+  bool malloc_tmpbuf = false;
+  char *tmpbuf = NULL;
+  int result = 0;
   if (name != NULL)
     {
-      at = __alloca (sizeof (struct gaih_addrtuple));
-
+      at = alloca_account (sizeof (struct gaih_addrtuple), alloca_used);
       at->family = AF_UNSPEC;
       at->scopeid = 0;
       at->next = NULL;
@@ -412,6 +422,7 @@
 	  rc = __idna_to_ascii_lz (name, &p, idn_flags);
 	  if (rc != IDNA_SUCCESS)
 	    {
+	      /* No need to jump to free_and_return here.  */
 	      if (rc == IDNA_MALLOC_ERROR)
 		return -EAI_MEMORY;
 	      if (rc == IDNA_DLOPEN_ERROR)
@@ -421,10 +432,7 @@
 	  /* In case the output string is the same as the input string
 	     no new string has been allocated.  */
 	  if (p != name)
-	    {
-	      name = strdupa (p);
-	      free (p);
-	    }
+	    malloc_name = true;
 	}
 #endif
 
@@ -441,23 +449,59 @@
 	      at->family = AF_INET6;
 	    }
 	  else
-	    return -EAI_ADDRFAMILY;
+	    {
+	      result = -EAI_ADDRFAMILY;
+	      goto free_and_return;
+	    }
 
 	  if (req->ai_flags & AI_CANONNAME)
 	    canon = name;
 	}
       else if (at->family == AF_UNSPEC)
 	{
-	  char *namebuf = (char *) name;
 	  char *scope_delim = strchr (name, SCOPE_DELIMITER);
-
-	  if (__builtin_expect (scope_delim != NULL, 0))
-	    {
-	      namebuf = alloca (scope_delim - name + 1);
-	      *((char *) __mempcpy (namebuf, name, scope_delim - name)) = '\0';
-	    }
-
-	  if (inet_pton (AF_INET6, namebuf, at->addr) > 0)
+	  int e;
+
+	  {
+	    bool malloc_namebuf = false;
+	    char *namebuf = (char *) name;
+
+	    if (__builtin_expect (scope_delim != NULL, 0))
+	      {
+		if (malloc_name)
+		  *scope_delim = '\0';
+		else
+		  {
+		    if (__libc_use_alloca (alloca_used
+					   + scope_delim - name + 1))
+		      {
+			namebuf = alloca_account (scope_delim - name + 1,
+						  alloca_used);
+			*((char *) __mempcpy (namebuf, name,
+					      scope_delim - name)) = '\0';
+		      }
+		    else
+		      {
+			namebuf = strndup (name, scope_delim - name);
+			if (namebuf == NULL)
+			  {
+			    assert (!malloc_name);
+			    return -EAI_MEMORY;
+			  }
+			malloc_namebuf = true;
+		      }
+		  }
+	      }
+
+	    e = inet_pton (AF_INET6, namebuf, at->addr);
+
+	    if (malloc_namebuf)
+	      free (namebuf);
+	    else if (scope_delim != NULL && malloc_name)
+	      /* Undo what we did above.  */
+	      *scope_delim = SCOPE_DELIMITER;
+	  }
+	  if (e > 0)
 	    {
 	      if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET6)
 		at->family = AF_INET6;
@@ -468,7 +512,10 @@
 		  at->family = AF_INET;
 		}
 	      else
-		return -EAI_ADDRFAMILY;
+		{
+		  result = -EAI_ADDRFAMILY;
+		  goto free_and_return;
+		}
 
 	      if (scope_delim != NULL)
 		{
@@ -490,7 +537,10 @@
 		      at->scopeid = (uint32_t) strtoul (scope_delim + 1, &end,
 							10);
 		      if (*end != '\0')
-			return GAIH_OKIFUNSPEC | -EAI_NONAME;
+			{
+			  result = GAIH_OKIFUNSPEC | -EAI_NONAME;
+			  goto free_and_return;
+			}
 		    }
 		}
 
@@ -517,7 +567,8 @@
 	    {
 	      int family = req->ai_family;
 	      size_t tmpbuflen = 512;
-	      char *tmpbuf = alloca (tmpbuflen);
+	      assert (tmpbuf == NULL);
+	      tmpbuf = alloca_account (tmpbuflen, alloca_used);
 	      int rc;
 	      struct hostent th;
 	      struct hostent *h;
@@ -529,50 +580,95 @@
 					   tmpbuflen, &h, &herrno);
 		  if (rc != ERANGE || herrno != NETDB_INTERNAL)
 		    break;
-		  tmpbuf = extend_alloca (tmpbuf, tmpbuflen, 2 * tmpbuflen);
+
+		  if (!malloc_tmpbuf
+		      && __libc_use_alloca (alloca_used + 2 * tmpbuflen))
+		    tmpbuf = extend_alloca_account (tmpbuf, tmpbuflen,
+						    2 * tmpbuflen,
+						    alloca_used);
+		  else
+		    {
+		      char *newp = realloc (malloc_tmpbuf ? tmpbuf : NULL,
+					    2 * tmpbuflen);
+		      if (newp == NULL)
+			{
+			  result = -EAI_MEMORY;
+			  goto free_and_return;
+			}
+		      tmpbuf = newp;
+		      malloc_tmpbuf = true;
+		      tmpbuflen = 2 * tmpbuflen;
+		    }
 		}
 
 	      if (rc == 0)
 		{
 		  if (h != NULL)
-		    /* We found data, now convert it into the list.  */
-		    for (int i = 0; h->h_addr_list[i]; ++i)
-		      {
-			if (*pat == NULL)
-			  {
-			    *pat = __alloca (sizeof (struct gaih_addrtuple));
-			    (*pat)->scopeid = 0;
-			  }
-			(*pat)->next = NULL;
-			(*pat)->family = req->ai_family;
-			if (family == req->ai_family)
-			  memcpy ((*pat)->addr, h->h_addr_list[i],
-				  h->h_length);
-			else
-			  {
-			    uint32_t *addr = (uint32_t *) (*pat)->addr;
-			    addr[3] = *(uint32_t *) h->h_addr_list[i];
-			    addr[2] = htonl (0xffff);
-			    addr[1] = 0;
-			    addr[0] = 0;
-			  }
-			pat = &((*pat)->next);
-		      }
+		    {
+		      int i;
+		      /* We found data, count the number of addresses.  */
+		      for (i = 0; h->h_addr_list[i]; ++i)
+			;
+		      if (i > 0 && *pat != NULL)
+			--i;
+
+		      if (__libc_use_alloca (alloca_used
+					     + i * sizeof (struct gaih_addrtuple)))
+			addrmem = alloca_account (i * sizeof (struct gaih_addrtuple),
+						  alloca_used);
+		      else
+			{
+			  addrmem = malloc (i
+					    * sizeof (struct gaih_addrtuple));
+			  if (addrmem == NULL)
+			    {
+			      result = -EAI_MEMORY;
+			      goto free_and_return;
+			    }
+			  malloc_addrmem = true;
+			}
+
+		      /* Now convert it into the list.  */
+		      struct gaih_addrtuple *addrfree = addrmem;
+		      for (i = 0; h->h_addr_list[i]; ++i)
+			{
+			  if (*pat == NULL)
+			    {
+			      *pat = addrfree++;
+			      (*pat)->scopeid = 0;
+			    }
+			  (*pat)->next = NULL;
+			  (*pat)->family = req->ai_family;
+			  if (family == req->ai_family)
+			    memcpy ((*pat)->addr, h->h_addr_list[i],
+				    h->h_length);
+			  else
+			    {
+			      uint32_t *addr = (uint32_t *) (*pat)->addr;
+			      addr[3] = *(uint32_t *) h->h_addr_list[i];
+			      addr[2] = htonl (0xffff);
+			      addr[1] = 0;
+			      addr[0] = 0;
+			    }
+			  pat = &((*pat)->next);
+			}
+		    }
 		}
 	      else
 		{
 		  if (herrno == NETDB_INTERNAL)
 		    {
 		      __set_h_errno (herrno);
-		      return -EAI_SYSTEM;
+		      result = -EAI_SYSTEM;
 		    }
-		  if (herrno == TRY_AGAIN)
-		    {
-		      return -EAI_AGAIN;
-		    }
-		  /* We made requests but they turned out no data.
-		     The name is known, though.  */
-		  return GAIH_OKIFUNSPEC | -EAI_NODATA;
+		  else if (herrno == TRY_AGAIN)
+		    result = -EAI_AGAIN;
+		  else
+		    /* We made requests but they turned out no data.
+		       The name is known, though.  */
+		    result = GAIH_OKIFUNSPEC | -EAI_NODATA;
+
+		  goto free_and_return;
 		}
 
 	      goto process_list;
@@ -596,21 +692,56 @@
 		  bool added_canon = (req->ai_flags & AI_CANONNAME) == 0;
 		  char *addrs = air->addrs;
 
+		  if (__libc_use_alloca (alloca_used
+					 + air->naddrs * sizeof (struct gaih_addrtuple)))
+		    addrmem = alloca_account (air->naddrs
+					      * sizeof (struct gaih_addrtuple),
+					      alloca_used);
+		  else
+		    {
+		      addrmem = malloc (air->naddrs
+					* sizeof (struct gaih_addrtuple));
+		      if (addrmem == NULL)
+			{
+			  result = -EAI_MEMORY;
+			  goto free_and_return;
+			}
+		      malloc_addrmem = true;
+		    }
+
+		  struct gaih_addrtuple *addrfree = addrmem;
 		  for (int i = 0; i < air->naddrs; ++i)
 		    {
 		      socklen_t size = (air->family[i] == AF_INET
 					? INADDRSZ : IN6ADDRSZ);
 		      if (*pat == NULL)
 			{
-			  *pat = __alloca (sizeof (struct gaih_addrtuple));
+			  *pat = addrfree++;
 			  (*pat)->scopeid = 0;
 			}
 		      uint32_t *pataddr = (*pat)->addr;
 		      (*pat)->next = NULL;
 		      if (added_canon || air->canon == NULL)
 			(*pat)->name = NULL;
-		      else
-			canon = (*pat)->name = strdupa (air->canon);
+		      else if (canonbuf == NULL)
+			{
+			  size_t canonlen = strlen (air->canon) + 1;
+			  if ((req->ai_flags & AI_CANONIDN) != 0
+			      && __libc_use_alloca (alloca_used + canonlen))
+			    canonbuf = alloca_account (canonlen, alloca_used);
+			  else
+			    {
+			      canonbuf = malloc (canonlen);
+			      if (canonbuf == NULL)
+				{
+				  result = -EAI_MEMORY;
+				  goto free_and_return;
+				}
+			      malloc_canonbuf = true;
+			    }
+			  canon = (*pat)->name = memcpy (canonbuf, air->canon,
+							 canonlen);
+			}
 
 		      if (air->family[i] == AF_INET
 			  && req->ai_family == AF_INET6
@@ -640,20 +771,26 @@
 		  free (air);
 
 		  if (at->family == AF_UNSPEC)
-		    return GAIH_OKIFUNSPEC | -EAI_NONAME;
+		    {
+		      result = GAIH_OKIFUNSPEC | -EAI_NONAME;
+		      goto free_and_return;
+		    }
 
 		  goto process_list;
 		}
 	      else if (err == 0)
 		/* The database contains a negative entry.  */
-		return 0;
+		goto free_and_return;
 	      else if (__nss_not_use_nscd_hosts == 0)
 		{
 		  if (herrno == NETDB_INTERNAL && errno == ENOMEM)
-		    return -EAI_MEMORY;
-		  if (herrno == TRY_AGAIN)
-		    return -EAI_AGAIN;
-		  return -EAI_SYSTEM;
+		    result = -EAI_MEMORY;
+		  else if (herrno == TRY_AGAIN)
+		    result = -EAI_AGAIN;
+		  else
+		    result = -EAI_SYSTEM;
+
+		  goto free_and_return;
 		}
 	    }
 #endif
@@ -682,7 +819,19 @@
 	  _res.options &= ~RES_USE_INET6;
 
 	  size_t tmpbuflen = 1024;
-	  char *tmpbuf = alloca (tmpbuflen);
+	  malloc_tmpbuf = !__libc_use_alloca (alloca_used + tmpbuflen);
+	  assert (tmpbuf == NULL);
+	  if (malloc_tmpbuf)
+	    tmpbuf = alloca_account (tmpbuflen, alloca_used);
+	  else
+	    {
+	      tmpbuf = malloc (tmpbuflen);
+	      if (tmpbuf == NULL)
+		{
+		  result = -EAI_MEMORY;
+		  goto free_and_return;
+		}
+	    }
 
 	  while (!no_more)
 	    {
@@ -711,8 +860,25 @@
 			    no_data = herrno == NO_DATA;
 			  break;
 			}
-		      tmpbuf = extend_alloca (tmpbuf,
-					      tmpbuflen, 2 * tmpbuflen);
+
+		      if (!malloc_tmpbuf
+			  && __libc_use_alloca (alloca_used + 2 * tmpbuflen))
+			tmpbuf = extend_alloca_account (tmpbuf, tmpbuflen,
+							2 * tmpbuflen,
+							alloca_used);
+		      else
+			{
+			  char *newp = realloc (malloc_tmpbuf ? tmpbuf : NULL,
+						2 * tmpbuflen);
+			  if (newp == NULL)
+			    {
+			      result = -EAI_MEMORY;
+			      goto free_and_return;
+			    }
+			  tmpbuf = newp;
+			  malloc_tmpbuf = true;
+			  tmpbuflen = 2 * tmpbuflen;
+			}
 		    }
 
 		  no_inet6_data = no_data;
@@ -787,18 +953,40 @@
 			      if (cfct != NULL)
 				{
 				  const size_t max_fqdn_len = 256;
-				  char *buf = alloca (max_fqdn_len);
+				  if ((req->ai_flags & AI_CANONIDN) != 0
+				      && __libc_use_alloca (alloca_used
+							    + max_fqdn_len))
+				    canonbuf = alloca_account (max_fqdn_len,
+							       alloca_used);
+				  else
+				    {
+				      canonbuf = malloc (max_fqdn_len);
+				      if (canonbuf == NULL)
+					{
+					  result = -EAI_MEMORY;
+					  goto free_and_return;
+					}
+				      malloc_canonbuf = true;
+				    }
 				  char *s;
 
 				  if (DL_CALL_FCT (cfct, (at->name ?: name,
-							  buf, max_fqdn_len,
+							  canonbuf,
+							  max_fqdn_len,
 							  &s, &rc, &herrno))
 				      == NSS_STATUS_SUCCESS)
 				    canon = s;
 				  else
-				    /* Set to name now to avoid using
-				       gethostbyaddr.  */
-				    canon = name;
+				    {
+				      /* Set to name now to avoid using
+					 gethostbyaddr.  */
+				      if (malloc_canonbuf)
+					{
+					  free (canonbuf);
+					  malloc_canonbuf = false;
+					}
+				      canon = name;
+				    }
 				}
 			    }
 			  status = NSS_STATUS_SUCCESS;
@@ -833,22 +1021,27 @@
 	    {
 	      /* If both requests timed out report this.  */
 	      if (no_data == EAI_AGAIN && no_inet6_data == EAI_AGAIN)
-		return -EAI_AGAIN;
-
-	      /* We made requests but they turned out no data.  The name
-		 is known, though.  */
-	      return GAIH_OKIFUNSPEC | -EAI_NODATA;
+		result = -EAI_AGAIN;
+	      else
+		/* We made requests but they turned out no data.  The name
+		   is known, though.  */
+		result = GAIH_OKIFUNSPEC | -EAI_NODATA;
+
+	      goto free_and_return;
 	    }
 	}
 
     process_list:
       if (at->family == AF_UNSPEC)
-	return GAIH_OKIFUNSPEC | -EAI_NONAME;
+	{
+	  result = GAIH_OKIFUNSPEC | -EAI_NONAME;
+	  goto free_and_return;
+	}
     }
   else
     {
       struct gaih_addrtuple *atr;
-      atr = at = __alloca (sizeof (struct gaih_addrtuple));
+      atr = at = alloca_account (sizeof (struct gaih_addrtuple), alloca_used);
       memset (at, '\0', sizeof (struct gaih_addrtuple));
 
       if (req->ai_family == AF_UNSPEC)
@@ -887,30 +1080,56 @@
 	/* Only the first entry gets the canonical name.  */
 	if (at2 == at && (req->ai_flags & AI_CANONNAME) != 0)
 	  {
+	    char *tmpbuf2 = NULL;
+	    bool malloc_tmpbuf2 = false;
+
 	    if (canon == NULL)
 	      {
 		struct hostent *h = NULL;
 		int herrno;
 		struct hostent th;
-		size_t tmpbuflen = 512;
-		char *tmpbuf = NULL;
+		size_t tmpbuf2len = 512;
 
 		do
 		  {
-		    tmpbuf = extend_alloca (tmpbuf, tmpbuflen, tmpbuflen * 2);
+		    if (__libc_use_alloca (alloca_used + 2 * tmpbuf2len))
+		      tmpbuf2 = extend_alloca_account (tmpbuf2, tmpbuf2len,
+						       tmpbuf2len * 2,
+						       alloca_used);
+		    else
+		      {
+			char *newp = realloc (malloc_tmpbuf2 ? tmpbuf2 : NULL,
+					      2 * tmpbuf2len);
+			if (newp == NULL)
+			  {
+			    if (malloc_tmpbuf2)
+			      free (tmpbuf2);
+			    result = -EAI_MEMORY;
+			    goto free_and_return;
+			  }
+
+			tmpbuf2 = newp;
+			tmpbuf2len = 2 * tmpbuf2len;
+			malloc_tmpbuf2 = true;
+		      }
+
 		    rc = __gethostbyaddr_r (at2->addr,
 					    ((at2->family == AF_INET6)
 					     ? sizeof (struct in6_addr)
 					     : sizeof (struct in_addr)),
-					    at2->family, &th, tmpbuf,
-					    tmpbuflen, &h, &herrno);
+					    at2->family, &th, tmpbuf2,
+					    tmpbuf2len, &h, &herrno);
 		  }
 		while (rc == ERANGE && herrno == NETDB_INTERNAL);
 
 		if (rc != 0 && herrno == NETDB_INTERNAL)
 		  {
+		    if (malloc_tmpbuf2)
+		      free (tmpbuf2);
+
 		    __set_h_errno (herrno);
-		    return -EAI_SYSTEM;
+		    result = -EAI_SYSTEM;
+		    goto free_and_return;
 		  }
 
 		if (h != NULL)
@@ -937,11 +1156,16 @@
 		int rc = __idna_to_unicode_lzlz (canon, &out, idn_flags);
 		if (rc != IDNA_SUCCESS)
 		  {
+		    if (malloc_tmpbuf2)
+		      free (tmpbuf2);
+
 		    if (rc == IDNA_MALLOC_ERROR)
-		      return -EAI_MEMORY;
-		    if (rc == IDNA_DLOPEN_ERROR)
-		      return -EAI_SYSTEM;
-		    return -EAI_IDN_ENCODE;
+		      result = -EAI_MEMORY;
+		    else if (rc == IDNA_DLOPEN_ERROR)
+		      result = -EAI_SYSTEM;
+		    else
+		      result = -EAI_IDN_ENCODE;
+		    goto free_and_return;
 		  }
 		/* In case the output string is the same as the input
 		   string no new string has been allocated and we
@@ -956,10 +1180,25 @@
 #ifdef HAVE_LIBIDN
 	      make_copy:
 #endif
-		canon = strdup (canon);
-		if (canon == NULL)
-		  return -EAI_MEMORY;
+		if (malloc_canonbuf)
+		  /* We already allocated the string using malloc.  */
+		  malloc_canonbuf = false;
+		else
+		  {
+		    canon = strdup (canon);
+		    if (canon == NULL)
+		      {
+			if (malloc_tmpbuf2)
+			  free (tmpbuf2);
+
+			result = -EAI_MEMORY;
+			goto free_and_return;
+		      }
+		  }
 	      }
+
+	    if (malloc_tmpbuf2)
+	      free (tmpbuf2);
 	  }
 
 	family = at2->family;
@@ -985,7 +1224,8 @@
 	    if (ai == NULL)
 	      {
 		free ((char *) canon);
-		return -EAI_MEMORY;
+		result = -EAI_MEMORY;
+		goto free_and_return;
 	      }
 
 	    ai->ai_flags = req->ai_flags;
@@ -1038,7 +1278,18 @@
 	at2 = at2->next;
       }
   }
-  return 0;
+
+ free_and_return:
+  if (malloc_name)
+    free ((char *) name);
+  if (malloc_addrmem)
+    free (addrmem);
+  if (malloc_canonbuf)
+    free (canonbuf);
+  if (malloc_tmpbuf)
+    free (tmpbuf);
+
+  return result;
 }