This is the mail archive of the glibc-cvs@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

GNU C Library master sources branch, master, updated. glibc-2.13-207-g34a9094


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU C Library master sources".

The branch, master has been updated
       via  34a9094f49241ebb72084c536cf468fd51ebe3ec (commit)
      from  78e64fdcaa44277fcab6ec60aa2d9b8b7742cf58 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
http://sources.redhat.com/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=34a9094f49241ebb72084c536cf468fd51ebe3ec

commit 34a9094f49241ebb72084c536cf468fd51ebe3ec
Author: Ulrich Drepper <drepper@gmail.com>
Date:   Fri May 20 23:46:03 2011 -0400

    Don't unconditionally use alloca in gaih_inet

diff --git a/ChangeLog b/ChangeLog
index 1ab3ae1..3b334c5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,10 @@
 2011-05-20  Ulrich Drepper  <drepper@gmail.com>
 
+	[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
 	fields after compilation and describe correct free'ing of pattern
diff --git a/NEWS b/NEWS
index 745f333..d7833e9 100644
--- a/NEWS
+++ b/NEWS
@@ -11,12 +11,12 @@ Version 2.14
 
   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
 
 * The RPC implementation in libc is obsoleted.  Old programs keep working
   but new programs cannot be linked with the routines in libc anymore.
diff --git a/include/alloca.h b/include/alloca.h
index b99c3d1..8350413 100644
--- a/include/alloca.h
+++ b/include/alloca.h
@@ -49,15 +49,24 @@ libc_hidden_proto (__libc_alloca_cutoff)
 
 #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
diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c
index 7bd89c4..5ddda88 100644
--- a/sysdeps/posix/getaddrinfo.c
+++ b/sysdeps/posix/getaddrinfo.c
@@ -278,6 +278,7 @@ gaih_inet (const char *name, const struct gaih_service *service,
   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 @@ gaih_inet (const char *name, const struct gaih_service *service,
 	  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 @@ gaih_inet (const char *name, const struct gaih_service *service,
 		    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 @@ gaih_inet (const char *name, const struct gaih_service *service,
 
       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 @@ gaih_inet (const char *name, const struct gaih_service *service,
 	      {
 		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 @@ gaih_inet (const char *name, const struct gaih_service *service,
 	}
     }
 
+  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 @@ gaih_inet (const char *name, const struct gaih_service *service,
 	  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 @@ gaih_inet (const char *name, const struct gaih_service *service,
 	  /* 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 @@ gaih_inet (const char *name, const struct gaih_service *service,
 	      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);
+	  int e;
 
-	  if (__builtin_expect (scope_delim != NULL, 0))
-	    {
-	      namebuf = alloca (scope_delim - name + 1);
-	      *((char *) __mempcpy (namebuf, name, scope_delim - name)) = '\0';
-	    }
+	  {
+	    bool malloc_namebuf = false;
+	    char *namebuf = (char *) name;
 
-	  if (inet_pton (AF_INET6, namebuf, at->addr) > 0)
+	    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 @@ gaih_inet (const char *name, const struct gaih_service *service,
 		  at->family = AF_INET;
 		}
 	      else
-		return -EAI_ADDRFAMILY;
+		{
+		  result = -EAI_ADDRFAMILY;
+		  goto free_and_return;
+		}
 
 	      if (scope_delim != NULL)
 		{
@@ -490,7 +537,10 @@ gaih_inet (const char *name, const struct gaih_service *service,
 		      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 @@ gaih_inet (const char *name, const struct gaih_service *service,
 	    {
 	      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 @@ gaih_inet (const char *name, const struct gaih_service *service,
 					   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 @@ gaih_inet (const char *name, const struct gaih_service *service,
 		  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 @@ gaih_inet (const char *name, const struct gaih_service *service,
 		  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 @@ gaih_inet (const char *name, const struct gaih_service *service,
 	  _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 @@ gaih_inet (const char *name, const struct gaih_service *service,
 			    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 @@ gaih_inet (const char *name, const struct gaih_service *service,
 			      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 @@ gaih_inet (const char *name, const struct gaih_service *service,
 	    {
 	      /* If both requests timed out report this.  */
 	      if (no_data == EAI_AGAIN && no_inet6_data == EAI_AGAIN)
-		return -EAI_AGAIN;
+		result = -EAI_AGAIN;
+	      else
+		/* We made requests but they turned out no data.  The name
+		   is known, though.  */
+		result = GAIH_OKIFUNSPEC | -EAI_NODATA;
 
-	      /* We made requests but they turned out no data.  The name
-		 is known, though.  */
-	      return 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 @@ gaih_inet (const char *name, const struct gaih_service *service,
 	/* 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 @@ gaih_inet (const char *name, const struct gaih_service *service,
 		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 @@ gaih_inet (const char *name, const struct gaih_service *service,
 #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 @@ gaih_inet (const char *name, const struct gaih_service *service,
 	    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 @@ gaih_inet (const char *name, const struct gaih_service *service,
 	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;
 }
 
 

-----------------------------------------------------------------------

Summary of changes:
 ChangeLog                   |    5 +
 NEWS                        |   12 +-
 include/alloca.h            |   19 ++-
 sysdeps/posix/getaddrinfo.c |  433 ++++++++++++++++++++++++++++++++++---------
 4 files changed, 367 insertions(+), 102 deletions(-)


hooks/post-receive
-- 
GNU C Library master sources


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]