Blame SOURCES/glibc-rh797094-1.patch

b40826
diff -rup a/include/alloca.h b/include/alloca.h
b40826
--- a/include/alloca.h	2012-02-29 13:11:19.439693476 -0700
b40826
+++ b/include/alloca.h	2012-02-29 13:11:49.832530623 -0700
b40826
@@ -49,15 +49,24 @@ libc_hidden_proto (__libc_alloca_cutoff)
b40826
 
b40826
 #if defined stackinfo_get_sp && defined stackinfo_sub_sp
b40826
 # define alloca_account(size, avar) \
b40826
-  ({ void *old__ = stackinfo_get_sp ();			\
b40826
-     void *m__ = __alloca (size);			\
b40826
-     avar += stackinfo_sub_sp (old__);			\
b40826
+  ({ void *old__ = stackinfo_get_sp ();					      \
b40826
+     void *m__ = __alloca (size);					      \
b40826
+     avar += stackinfo_sub_sp (old__);					      \
b40826
+     m__; })
b40826
+# define extend_alloca_account(buf, len, newlen, avar) \
b40826
+  ({ void *old__ = stackinfo_get_sp ();					      \
b40826
+     void *m__ = extend_alloca (buf, len, newlen);			      \
b40826
+     avar += stackinfo_sub_sp (old__);					      \
b40826
      m__; })
b40826
 #else
b40826
 # define alloca_account(size, avar) \
b40826
-  ({ size_t s__ = (size);		    \
b40826
-     avar += s__;			    \
b40826
+  ({ size_t s__ = (size);						      \
b40826
+     avar += s__;							      \
b40826
      __alloca (s__); })
b40826
+# define extend_alloca_account(buf, len, newlen, avar) \
b40826
+  ({ size_t s__ = (newlen);						      \
b40826
+     avar += s__;							      \
b40826
+     extend_alloca (buf, len, s__); })
b40826
 #endif
b40826
 
b40826
 #endif
b40826
diff -rup a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c
b40826
--- a/sysdeps/posix/getaddrinfo.c	2012-02-29 13:11:19.588692676 -0700
b40826
+++ b/sysdeps/posix/getaddrinfo.c	2012-02-29 13:12:42.972245862 -0700
b40826
@@ -278,6 +278,7 @@ gaih_inet (const char *name, const struc
b40826
   bool got_ipv6 = false;
b40826
   const char *canon = NULL;
b40826
   const char *orig_name = name;
b40826
+  size_t alloca_used = 0;
b40826
 
b40826
   if (req->ai_protocol || req->ai_socktype)
b40826
     {
b40826
@@ -310,7 +311,7 @@ gaih_inet (const char *name, const struc
b40826
 	  if (tp->name[0])
b40826
 	    {
b40826
 	      st = (struct gaih_servtuple *)
b40826
-		__alloca (sizeof (struct gaih_servtuple));
b40826
+		alloca_account (sizeof (struct gaih_servtuple), alloca_used);
b40826
 
b40826
 	      if ((rc = gaih_inet_serv (service->name, tp, req, st)))
b40826
 		return rc;
b40826
@@ -334,7 +335,8 @@ gaih_inet (const char *name, const struc
b40826
 		    continue;
b40826
 
b40826
 		  newp = (struct gaih_servtuple *)
b40826
-		    __alloca (sizeof (struct gaih_servtuple));
b40826
+		    alloca_account (sizeof (struct gaih_servtuple),
b40826
+				    alloca_used);
b40826
 
b40826
 		  if ((rc = gaih_inet_serv (service->name, tp, req, newp)))
b40826
 		    {
b40826
@@ -362,7 +364,7 @@ gaih_inet (const char *name, const struc
b40826
 
b40826
       if (req->ai_socktype || req->ai_protocol)
b40826
 	{
b40826
-	  st = __alloca (sizeof (struct gaih_servtuple));
b40826
+	  st = alloca_account (sizeof (struct gaih_servtuple), alloca_used);
b40826
 	  st->next = NULL;
b40826
 	  st->socktype = tp->socktype;
b40826
 	  st->protocol = ((tp->protoflag & GAI_PROTO_PROTOANY)
b40826
@@ -379,7 +381,8 @@ gaih_inet (const char *name, const struc
b40826
 	      {
b40826
 		struct gaih_servtuple *newp;
b40826
 
b40826
-		newp = __alloca (sizeof (struct gaih_servtuple));
b40826
+		newp = alloca_account (sizeof (struct gaih_servtuple),
b40826
+				       alloca_used);
b40826
 		newp->next = NULL;
b40826
 		newp->socktype = tp->socktype;
b40826
 		newp->protocol = tp->protocol;
b40826
@@ -391,10 +394,17 @@ gaih_inet (const char *name, const struc
b40826
 	}
b40826
     }
b40826
 
b40826
+  bool malloc_name = false;
b40826
+  bool malloc_addrmem = false;
b40826
+  struct gaih_addrtuple *addrmem = NULL;
b40826
+  bool malloc_canonbuf = false;
b40826
+  char *canonbuf = NULL;
b40826
+  bool malloc_tmpbuf = false;
b40826
+  char *tmpbuf = NULL;
b40826
+  int result = 0;
b40826
   if (name != NULL)
b40826
     {
b40826
-      at = __alloca (sizeof (struct gaih_addrtuple));
b40826
-
b40826
+      at = alloca_account (sizeof (struct gaih_addrtuple), alloca_used);
b40826
       at->family = AF_UNSPEC;
b40826
       at->scopeid = 0;
b40826
       at->next = NULL;
b40826
@@ -412,6 +422,7 @@ gaih_inet (const char *name, const struc
b40826
 	  rc = __idna_to_ascii_lz (name, &p, idn_flags);
b40826
 	  if (rc != IDNA_SUCCESS)
b40826
 	    {
b40826
+	      /* No need to jump to free_and_return here.  */
b40826
 	      if (rc == IDNA_MALLOC_ERROR)
b40826
 		return -EAI_MEMORY;
b40826
 	      if (rc == IDNA_DLOPEN_ERROR)
b40826
@@ -421,10 +432,7 @@ gaih_inet (const char *name, const struc
b40826
 	  /* In case the output string is the same as the input string
b40826
 	     no new string has been allocated.  */
b40826
 	  if (p != name)
b40826
-	    {
b40826
-	      name = strdupa (p);
b40826
-	      free (p);
b40826
-	    }
b40826
+	    malloc_name = true;
b40826
 	}
b40826
 #endif
b40826
 
b40826
@@ -441,23 +449,59 @@ gaih_inet (const char *name, const struc
b40826
 	      at->family = AF_INET6;
b40826
 	    }
b40826
 	  else
b40826
-	    return -EAI_ADDRFAMILY;
b40826
+	    {
b40826
+	      result = -EAI_ADDRFAMILY;
b40826
+	      goto free_and_return;
b40826
+	    }
b40826
 
b40826
 	  if (req->ai_flags & AI_CANONNAME)
b40826
 	    canon = name;
b40826
 	}
b40826
       else if (at->family == AF_UNSPEC)
b40826
 	{
b40826
-	  char *namebuf = (char *) name;
b40826
 	  char *scope_delim = strchr (name, SCOPE_DELIMITER);
b40826
+	  int e;
b40826
 
b40826
-	  if (__builtin_expect (scope_delim != NULL, 0))
b40826
-	    {
b40826
-	      namebuf = alloca (scope_delim - name + 1);
b40826
-	      *((char *) __mempcpy (namebuf, name, scope_delim - name)) = '\0';
b40826
-	    }
b40826
+	  {
b40826
+	    bool malloc_namebuf = false;
b40826
+	    char *namebuf = (char *) name;
b40826
+
b40826
+	    if (__builtin_expect (scope_delim != NULL, 0))
b40826
+	      {
b40826
+		if (malloc_name)
b40826
+		  *scope_delim = '\0';
b40826
+		else
b40826
+		  {
b40826
+		    if (__libc_use_alloca (alloca_used
b40826
+					   + scope_delim - name + 1))
b40826
+		      {
b40826
+			namebuf = alloca_account (scope_delim - name + 1,
b40826
+						  alloca_used);
b40826
+			*((char *) __mempcpy (namebuf, name,
b40826
+					      scope_delim - name)) = '\0';
b40826
+		      }
b40826
+		    else
b40826
+		      {
b40826
+			namebuf = strndup (name, scope_delim - name);
b40826
+			if (namebuf == NULL)
b40826
+			  {
b40826
+			    assert (!malloc_name);
b40826
+			    return -EAI_MEMORY;
b40826
+			  }
b40826
+			malloc_namebuf = true;
b40826
+		      }
b40826
+		  }
b40826
+	      }
b40826
 
b40826
-	  if (inet_pton (AF_INET6, namebuf, at->addr) > 0)
b40826
+	    e = inet_pton (AF_INET6, namebuf, at->addr);
b40826
+
b40826
+	    if (malloc_namebuf)
b40826
+	      free (namebuf);
b40826
+	    else if (scope_delim != NULL && malloc_name)
b40826
+	      /* Undo what we did above.  */
b40826
+	      *scope_delim = SCOPE_DELIMITER;
b40826
+	  }
b40826
+	  if (e > 0)
b40826
 	    {
b40826
 	      if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET6)
b40826
 		at->family = AF_INET6;
b40826
@@ -468,7 +512,10 @@ gaih_inet (const char *name, const struc
b40826
 		  at->family = AF_INET;
b40826
 		}
b40826
 	      else
b40826
-		return -EAI_ADDRFAMILY;
b40826
+		{
b40826
+		  result = -EAI_ADDRFAMILY;
b40826
+		  goto free_and_return;
b40826
+		}
b40826
 
b40826
 	      if (scope_delim != NULL)
b40826
 		{
b40826
@@ -490,7 +537,10 @@ gaih_inet (const char *name, const struc
b40826
 		      at->scopeid = (uint32_t) strtoul (scope_delim + 1, &end,
b40826
 							10);
b40826
 		      if (*end != '\0')
b40826
-			return GAIH_OKIFUNSPEC | -EAI_NONAME;
b40826
+			{
b40826
+			  result = GAIH_OKIFUNSPEC | -EAI_NONAME;
b40826
+			  goto free_and_return;
b40826
+			}
b40826
 		    }
b40826
 		}
b40826
 
b40826
@@ -520,59 +570,80 @@ gaih_inet (const char *name, const struc
b40826
 	    {
b40826
 	      int family = req->ai_family;
b40826
 	      size_t tmpbuflen = 512;
b40826
-	      char *tmpbuf = alloca (tmpbuflen);
b40826
+	      assert (tmpbuf == NULL);
b40826
+	      tmpbuf = alloca_account (tmpbuflen, alloca_used);
b40826
 	      int rc;
b40826
 	      struct hostent th;
b40826
 	      struct hostent *h;
b40826
 	      int herrno;
b40826
 
b40826
-	    simple_again:
b40826
 	      while (1)
b40826
 		{
b40826
-		  rc = __gethostbyname2_r (name, family, &th, tmpbuf,
b40826
+		  rc = __gethostbyname2_r (name, AF_INET, &th, tmpbuf,
b40826
 					   tmpbuflen, &h, &herrno);
b40826
 		  if (rc != ERANGE || herrno != NETDB_INTERNAL)
b40826
 		    break;
b40826
-		  tmpbuf = extend_alloca (tmpbuf, tmpbuflen, 2 * tmpbuflen);
b40826
+
b40826
+		  if (!malloc_tmpbuf
b40826
+		      && __libc_use_alloca (alloca_used + 2 * tmpbuflen))
b40826
+		    tmpbuf = extend_alloca_account (tmpbuf, tmpbuflen,
b40826
+						    2 * tmpbuflen,
b40826
+						    alloca_used);
b40826
+		  else
b40826
+		    {
b40826
+		      char *newp = realloc (malloc_tmpbuf ? tmpbuf : NULL,
b40826
+					    2 * tmpbuflen);
b40826
+		      if (newp == NULL)
b40826
+			{
b40826
+			  result = -EAI_MEMORY;
b40826
+			  goto free_and_return;
b40826
+			}
b40826
+		      tmpbuf = newp;
b40826
+		      malloc_tmpbuf = true;
b40826
+		      tmpbuflen = 2 * tmpbuflen;
b40826
+		    }
b40826
 		}
b40826
 
b40826
 	      if (rc == 0)
b40826
 		{
b40826
-		  if (h == NULL)
b40826
+		  if (h != NULL)
b40826
 		    {
b40826
-		      if (req->ai_family == AF_INET6
b40826
-			  && (req->ai_flags & AI_V4MAPPED)
b40826
-			  && family == AF_INET6)
b40826
+		      int i;
b40826
+		      /* We found data, count the number of addresses.  */
b40826
+		      for (i = 0; h->h_addr_list[i]; ++i)
b40826
+			;
b40826
+		      if (i > 0 && *pat != NULL)
b40826
+			--i;
b40826
+
b40826
+		      if (__libc_use_alloca (alloca_used
b40826
+					     + i * sizeof (struct gaih_addrtuple)))
b40826
+			addrmem = alloca_account (i * sizeof (struct gaih_addrtuple),
b40826
+						  alloca_used);
b40826
+		      else
b40826
 			{
b40826
-			  /* Try again, this time looking for IPv4
b40826
-			     addresses.  */
b40826
-			  family = AF_INET;
b40826
-			  goto simple_again;
b40826
+			  addrmem = malloc (i
b40826
+					    * sizeof (struct gaih_addrtuple));
b40826
+			  if (addrmem == NULL)
b40826
+			{
b40826
+			      result = -EAI_MEMORY;
b40826
+			      goto free_and_return;
b40826
 			}
b40826
+			  malloc_addrmem = true;
b40826
 		    }
b40826
-		  else
b40826
-		    {
b40826
-		      /* We found data, now convert it into the list.  */
b40826
-		      for (int i = 0; h->h_addr_list[i]; ++i)
b40826
+
b40826
+		      /* Now convert it into the list.  */
b40826
+		      struct gaih_addrtuple *addrfree = addrmem;
b40826
+		      for (i = 0; h->h_addr_list[i]; ++i)
b40826
 			{
b40826
 			  if (*pat == NULL)
b40826
 			    {
b40826
-			      *pat = __alloca (sizeof (struct gaih_addrtuple));
b40826
+			      *pat = addrfree++;
b40826
 			      (*pat)->scopeid = 0;
b40826
 			    }
b40826
 			  (*pat)->next = NULL;
b40826
-			  (*pat)->family = req->ai_family;
b40826
-			  if (family == req->ai_family)
b40826
+			  (*pat)->family = AF_INET;
b40826
 			    memcpy ((*pat)->addr, h->h_addr_list[i],
b40826
 				    h->h_length);
b40826
-			  else
b40826
-			    {
b40826
-			      uint32_t *addr = (uint32_t *) (*pat)->addr;
b40826
-			      addr[3] = *(uint32_t *) h->h_addr_list[i];
b40826
-			      addr[2] = htonl (0xffff);
b40826
-			      addr[1] = 0;
b40826
-			      addr[0] = 0;
b40826
-			    }
b40826
 			  pat = &((*pat)->next);
b40826
 			}
b40826
 		    }
b40826
@@ -582,15 +653,16 @@ gaih_inet (const char *name, const struc
b40826
 		  if (herrno == NETDB_INTERNAL)
b40826
 		    {
b40826
 		      __set_h_errno (herrno);
b40826
-		      return -EAI_SYSTEM;
b40826
-		    }
b40826
-		  if (herrno == TRY_AGAIN)
b40826
-		    {
b40826
-		      return -EAI_AGAIN;
b40826
+		      result = -EAI_SYSTEM;
b40826
 		    }
b40826
+		  else if (herrno == TRY_AGAIN)
b40826
+		    result = -EAI_AGAIN;
b40826
+		  else
b40826
 		  /* We made requests but they turned out no data.
b40826
 		     The name is known, though.  */
b40826
-		  return GAIH_OKIFUNSPEC | -EAI_NODATA;
b40826
+		    result = GAIH_OKIFUNSPEC | -EAI_NODATA;
b40826
+
b40826
+		  goto free_and_return;
b40826
 		}
b40826
 
b40826
 	      goto process_list;
b40826
@@ -613,21 +685,56 @@ gaih_inet (const char *name, const struc
b40826
 		  bool added_canon = (req->ai_flags & AI_CANONNAME) == 0;
b40826
 		  char *addrs = air->addrs;
b40826
 
b40826
+		  if (__libc_use_alloca (alloca_used
b40826
+					 + air->naddrs * sizeof (struct gaih_addrtuple)))
b40826
+		    addrmem = alloca_account (air->naddrs
b40826
+					      * sizeof (struct gaih_addrtuple),
b40826
+					      alloca_used);
b40826
+		  else
b40826
+		    {
b40826
+		      addrmem = malloc (air->naddrs
b40826
+					* sizeof (struct gaih_addrtuple));
b40826
+		      if (addrmem == NULL)
b40826
+			{
b40826
+			  result = -EAI_MEMORY;
b40826
+			  goto free_and_return;
b40826
+			}
b40826
+		      malloc_addrmem = true;
b40826
+		    }
b40826
+
b40826
+		  struct gaih_addrtuple *addrfree = addrmem;
b40826
 		  for (int i = 0; i < air->naddrs; ++i)
b40826
 		    {
b40826
 		      socklen_t size = (air->family[i] == AF_INET
b40826
 					? INADDRSZ : IN6ADDRSZ);
b40826
 		      if (*pat == NULL)
b40826
 			{
b40826
-			  *pat = __alloca (sizeof (struct gaih_addrtuple));
b40826
+			  *pat = addrfree++;
b40826
 			  (*pat)->scopeid = 0;
b40826
 			}
b40826
 		      uint32_t *pataddr = (*pat)->addr;
b40826
 		      (*pat)->next = NULL;
b40826
 		      if (added_canon || air->canon == NULL)
b40826
 			(*pat)->name = NULL;
b40826
-		      else
b40826
-			canon = (*pat)->name = strdupa (air->canon);
b40826
+		      else if (canonbuf == NULL)
b40826
+			{
b40826
+			  size_t canonlen = strlen (air->canon) + 1;
b40826
+			  if ((req->ai_flags & AI_CANONIDN) != 0
b40826
+			      && __libc_use_alloca (alloca_used + canonlen))
b40826
+			    canonbuf = alloca_account (canonlen, alloca_used);
b40826
+			  else
b40826
+			    {
b40826
+			      canonbuf = malloc (canonlen);
b40826
+			      if (canonbuf == NULL)
b40826
+				{
b40826
+				  result = -EAI_MEMORY;
b40826
+				  goto free_and_return;
b40826
+				}
b40826
+			      malloc_canonbuf = true;
b40826
+			    }
b40826
+			  canon = (*pat)->name = memcpy (canonbuf, air->canon,
b40826
+							 canonlen);
b40826
+			}
b40826
 
b40826
 		      if (air->family[i] == AF_INET
b40826
 			  && req->ai_family == AF_INET6
b40826
@@ -657,20 +764,26 @@ gaih_inet (const char *name, const struc
b40826
 		  free (air);
b40826
 
b40826
 		  if (at->family == AF_UNSPEC)
b40826
-		    return GAIH_OKIFUNSPEC | -EAI_NONAME;
b40826
+		    {
b40826
+		      result = GAIH_OKIFUNSPEC | -EAI_NONAME;
b40826
+		      goto free_and_return;
b40826
+		    }
b40826
 
b40826
 		  goto process_list;
b40826
 		}
b40826
 	      else if (err == 0)
b40826
 		/* The database contains a negative entry.  */
b40826
-		return 0;
b40826
+		goto free_and_return;
b40826
 	      else if (__nss_not_use_nscd_hosts == 0)
b40826
 		{
b40826
 		  if (herrno == NETDB_INTERNAL && errno == ENOMEM)
b40826
-		    return -EAI_MEMORY;
b40826
-		  if (herrno == TRY_AGAIN)
b40826
-		    return -EAI_AGAIN;
b40826
-		  return -EAI_SYSTEM;
b40826
+		    result = -EAI_MEMORY;
b40826
+		  else if (herrno == TRY_AGAIN)
b40826
+		    result = -EAI_AGAIN;
b40826
+		  else
b40826
+		    result = -EAI_SYSTEM;
b40826
+
b40826
+		  goto free_and_return;
b40826
 		}
b40826
 	    }
b40826
 #endif
b40826
@@ -699,7 +812,19 @@ gaih_inet (const char *name, const struc
b40826
 	  _res.options &= ~RES_USE_INET6;
b40826
 
b40826
 	  size_t tmpbuflen = 1024;
b40826
-	  char *tmpbuf = alloca (tmpbuflen);
b40826
+	  malloc_tmpbuf = !__libc_use_alloca (alloca_used + tmpbuflen);
b40826
+	  assert (tmpbuf == NULL);
b40826
+	  if (!malloc_tmpbuf)
b40826
+	    tmpbuf = alloca_account (tmpbuflen, alloca_used);
b40826
+	  else
b40826
+	    {
b40826
+	      tmpbuf = malloc (tmpbuflen);
b40826
+	      if (tmpbuf == NULL)
b40826
+		{
b40826
+		  result = -EAI_MEMORY;
b40826
+		  goto free_and_return;
b40826
+		}
b40826
+	    }
b40826
 
b40826
 	  while (!no_more)
b40826
 	    {
b40826
@@ -728,8 +853,25 @@ gaih_inet (const char *name, const struc
b40826
 			    no_data = herrno == NO_DATA;
b40826
 			  break;
b40826
 			}
b40826
-		      tmpbuf = extend_alloca (tmpbuf,
b40826
-					      tmpbuflen, 2 * tmpbuflen);
b40826
+
b40826
+		      if (!malloc_tmpbuf
b40826
+			  && __libc_use_alloca (alloca_used + 2 * tmpbuflen))
b40826
+			tmpbuf = extend_alloca_account (tmpbuf, tmpbuflen,
b40826
+							2 * tmpbuflen,
b40826
+							alloca_used);
b40826
+		      else
b40826
+			{
b40826
+			  char *newp = realloc (malloc_tmpbuf ? tmpbuf : NULL,
b40826
+						2 * tmpbuflen);
b40826
+			  if (newp == NULL)
b40826
+			    {
b40826
+			      result = -EAI_MEMORY;
b40826
+			      goto free_and_return;
b40826
+			    }
b40826
+			  tmpbuf = newp;
b40826
+			  malloc_tmpbuf = true;
b40826
+			  tmpbuflen = 2 * tmpbuflen;
b40826
+			}
b40826
 		    }
b40826
 
b40826
 		  if (status == NSS_STATUS_SUCCESS)
b40826
@@ -832,18 +974,40 @@ gaih_inet (const char *name, const struc
b40826
 			      if (cfct != NULL)
b40826
 				{
b40826
 				  const size_t max_fqdn_len = 256;
b40826
-				  char *buf = alloca (max_fqdn_len);
b40826
+				  if ((req->ai_flags & AI_CANONIDN) != 0
b40826
+				      && __libc_use_alloca (alloca_used
b40826
+							    + max_fqdn_len))
b40826
+				    canonbuf = alloca_account (max_fqdn_len,
b40826
+							       alloca_used);
b40826
+				  else
b40826
+				    {
b40826
+				      canonbuf = malloc (max_fqdn_len);
b40826
+				      if (canonbuf == NULL)
b40826
+					{
b40826
+					  result = -EAI_MEMORY;
b40826
+					  goto free_and_return;
b40826
+					}
b40826
+				      malloc_canonbuf = true;
b40826
+				    }
b40826
 				  char *s;
b40826
 
b40826
 				  if (DL_CALL_FCT (cfct, (at->name ?: name,
b40826
-							  buf, max_fqdn_len,
b40826
+							  canonbuf,
b40826
+							  max_fqdn_len,
b40826
 							  &s, &rc, &herrno))
b40826
 				      == NSS_STATUS_SUCCESS)
b40826
 				    canon = s;
b40826
 				  else
b40826
-				    /* Set to name now to avoid using
b40826
-				       gethostbyaddr.  */
b40826
-				    canon = name;
b40826
+				    {
b40826
+				      /* Set to name now to avoid using
b40826
+					 gethostbyaddr.  */
b40826
+				      if (malloc_canonbuf)
b40826
+					{
b40826
+					  free (canonbuf);
b40826
+					  malloc_canonbuf = false;
b40826
+					}
b40826
+				      canon = name;
b40826
+				    }
b40826
 				}
b40826
 			    }
b40826
 			  status = NSS_STATUS_SUCCESS;
b40826
@@ -878,22 +1042,27 @@ gaih_inet (const char *name, const struc
b40826
 	    {
b40826
 	      /* If both requests timed out report this.  */
b40826
 	      if (no_data == EAI_AGAIN && no_inet6_data == EAI_AGAIN)
b40826
-		return -EAI_AGAIN;
b40826
+		result = -EAI_AGAIN;
b40826
+	      else
b40826
+		/* We made requests but they turned out no data.  The name
b40826
+		   is known, though.  */
b40826
+		result = GAIH_OKIFUNSPEC | -EAI_NODATA;
b40826
 
b40826
-	      /* We made requests but they turned out no data.  The name
b40826
-		 is known, though.  */
b40826
-	      return GAIH_OKIFUNSPEC | -EAI_NODATA;
b40826
+	      goto free_and_return;
b40826
 	    }
b40826
 	}
b40826
 
b40826
     process_list:
b40826
       if (at->family == AF_UNSPEC)
b40826
-	return GAIH_OKIFUNSPEC | -EAI_NONAME;
b40826
+	{
b40826
+	  result = GAIH_OKIFUNSPEC | -EAI_NONAME;
b40826
+	  goto free_and_return;
b40826
+	}
b40826
     }
b40826
   else
b40826
     {
b40826
       struct gaih_addrtuple *atr;
b40826
-      atr = at = __alloca (sizeof (struct gaih_addrtuple));
b40826
+      atr = at = alloca_account (sizeof (struct gaih_addrtuple), alloca_used);
b40826
       memset (at, '\0', sizeof (struct gaih_addrtuple));
b40826
 
b40826
       if (req->ai_family == AF_UNSPEC)
b40826
@@ -932,6 +1101,9 @@ gaih_inet (const char *name, const struc
b40826
 	/* Only the first entry gets the canonical name.  */
b40826
 	if (at2 == at && (req->ai_flags & AI_CANONNAME) != 0)
b40826
 	  {
b40826
+	    char *tmpbuf2 = NULL;
b40826
+	    bool malloc_tmpbuf2 = false;
b40826
+
b40826
 	    if (canon == NULL)
b40826
 	      {
b40826
 		/* If the canonical name cannot be determined, use
b40826
@@ -952,11 +1124,16 @@ gaih_inet (const char *name, const struc
b40826
 		int rc = __idna_to_unicode_lzlz (canon, &out, idn_flags);
b40826
 		if (rc != IDNA_SUCCESS)
b40826
 		  {
b40826
+		    if (malloc_tmpbuf2)
b40826
+		      free (tmpbuf2);
b40826
+
b40826
 		    if (rc == IDNA_MALLOC_ERROR)
b40826
-		      return -EAI_MEMORY;
b40826
-		    if (rc == IDNA_DLOPEN_ERROR)
b40826
-		      return -EAI_SYSTEM;
b40826
-		    return -EAI_IDN_ENCODE;
b40826
+		      result = -EAI_MEMORY;
b40826
+		    else if (rc == IDNA_DLOPEN_ERROR)
b40826
+		      result = -EAI_SYSTEM;
b40826
+		    else
b40826
+		      result = -EAI_IDN_ENCODE;
b40826
+		    goto free_and_return;
b40826
 		  }
b40826
 		/* In case the output string is the same as the input
b40826
 		   string no new string has been allocated and we
b40826
@@ -970,10 +1147,25 @@ gaih_inet (const char *name, const struc
b40826
 #ifdef HAVE_LIBIDN
b40826
 	      make_copy:
b40826
 #endif
b40826
-		canon = strdup (canon);
b40826
-		if (canon == NULL)
b40826
-		  return -EAI_MEMORY;
b40826
+		if (malloc_canonbuf)
b40826
+		  /* We already allocated the string using malloc.  */
b40826
+		  malloc_canonbuf = false;
b40826
+		else
b40826
+		  {
b40826
+		    canon = strdup (canon);
b40826
+		    if (canon == NULL)
b40826
+		      {
b40826
+			if (malloc_tmpbuf2)
b40826
+			  free (tmpbuf2);
b40826
+
b40826
+			result = -EAI_MEMORY;
b40826
+			goto free_and_return;
b40826
+		      }
b40826
+		  }
b40826
 	      }
b40826
+
b40826
+	    if (malloc_tmpbuf2)
b40826
+	      free (tmpbuf2);
b40826
 	  }
b40826
 
b40826
 	family = at2->family;
b40826
@@ -999,7 +1191,8 @@ gaih_inet (const char *name, const struc
b40826
 	    if (ai == NULL)
b40826
 	      {
b40826
 		free ((char *) canon);
b40826
-		return -EAI_MEMORY;
b40826
+		result = -EAI_MEMORY;
b40826
+		goto free_and_return;
b40826
 	      }
b40826
 
b40826
 	    ai->ai_flags = req->ai_flags;
b40826
@@ -1052,7 +1245,18 @@ gaih_inet (const char *name, const struc
b40826
 	at2 = at2->next;
b40826
       }
b40826
   }
b40826
-  return 0;
b40826
+
b40826
+ free_and_return:
b40826
+  if (malloc_name)
b40826
+    free ((char *) name);
b40826
+  if (malloc_addrmem)
b40826
+    free (addrmem);
b40826
+  if (malloc_canonbuf)
b40826
+    free (canonbuf);
b40826
+  if (malloc_tmpbuf)
b40826
+    free (tmpbuf);
b40826
+
b40826
+  return result;
b40826
 }
b40826
 
b40826