[20/25] getaddrinfo: Use struct scratch_buffer instead of extend_alloca
diff mbox

Message ID b757dcaa3199366c9563ced1070d2cc4be15f59a.1425285061.git.fweimer@redhat.com
State New
Headers show

Commit Message

Florian Weimer March 1, 2015, 6:38 p.m. UTC
This results in slightly smaller buffers in some cases, but as the
buffer size is passed to the called functions (and they will request
an increased buffer size with an ERANGE error code), this does not
result in a functional difference.
---
 sysdeps/posix/getaddrinfo.c | 126 ++++++++++++++------------------------------
 1 file changed, 40 insertions(+), 86 deletions(-)

Patch
diff mbox

diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c
index 31bb7e6..e089f25 100644
--- a/sysdeps/posix/getaddrinfo.c
+++ b/sysdeps/posix/getaddrinfo.c
@@ -63,6 +63,7 @@  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <nscd/nscd-client.h>
 #include <nscd/nscd_proto.h>
 #include <resolv/res_hconf.h>
+#include <scratch_buffer.h>
 
 #ifdef HAVE_LIBIDN
 extern int __idna_to_ascii_lz (const char *input, char **output, int flags);
@@ -138,21 +139,22 @@  gaih_inet_serv (const char *servicename, const struct gaih_typeproto *tp,
 		const struct addrinfo *req, struct gaih_servtuple *st)
 {
   struct servent *s;
-  size_t tmpbuflen = 1024;
   struct servent ts;
-  char *tmpbuf;
   int r;
+  struct scratch_buffer tmpbuf;
+  scratch_buffer_init (&tmpbuf);
 
   do
     {
-      tmpbuf = __alloca (tmpbuflen);
-
-      r = __getservbyname_r (servicename, tp->name, &ts, tmpbuf, tmpbuflen,
-			     &s);
+      r = __getservbyname_r (servicename, tp->name, &ts,
+			     tmpbuf.data, tmpbuf.length, &s);
       if (r != 0 || s == NULL)
 	{
 	  if (r == ERANGE)
-	    tmpbuflen *= 2;
+	    {
+	      if (!scratch_buffer_grow (&tmpbuf))
+		return -EAI_MEMORY;
+	    }
 	  else
 	    return -EAI_SERVICE;
 	}
@@ -164,7 +166,7 @@  gaih_inet_serv (const char *servicename, const struct gaih_typeproto *tp,
   st->protocol = ((tp->protoflag & GAI_PROTO_PROTOANY)
 		  ? req->ai_protocol : tp->protocol);
   st->port = s->s_port;
-
+  scratch_buffer_free (&tmpbuf);
   return 0;
 }
 
@@ -178,25 +180,15 @@  gaih_inet_serv (const char *servicename, const struct gaih_typeproto *tp,
   no_data = 0;								      \
   while (1) {								      \
     rc = 0;								      \
-    status = DL_CALL_FCT (fct, (name, _family, &th, tmpbuf, tmpbuflen,	      \
+    status = DL_CALL_FCT (fct, (name, _family, &th,			      \
+				tmpbuf.data, tmpbuf.length,		      \
 				&rc, &herrno, NULL, &localcanon));	      \
     if (rc != ERANGE || herrno != NETDB_INTERNAL)			      \
       break;								      \
-    if (!malloc_tmpbuf && __libc_use_alloca (alloca_used + 2 * tmpbuflen))    \
-      tmpbuf = extend_alloca_account (tmpbuf, tmpbuflen, 2 * tmpbuflen,	      \
-				      alloca_used);			      \
-    else								      \
+    if (!scratch_buffer_grow (&tmpbuf))					      \
       {									      \
-	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;					      \
+	result = -EAI_MEMORY;						      \
+	goto free_and_return;						      \
       }									      \
   }									      \
   if (status == NSS_STATUS_SUCCESS && rc == 0)				      \
@@ -280,7 +272,10 @@  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;
+
+  /* Reserve stack memory for this function's buffer and the one in
+     gaih_inet_serv.  */
+  size_t alloca_used = 2 * sizeof (struct scratch_buffer);
 
   if (req->ai_protocol || req->ai_socktype)
     {
@@ -401,9 +396,10 @@  gaih_inet (const char *name, const struct gaih_service *service,
   struct gaih_addrtuple *addrmem = NULL;
   bool malloc_canonbuf = false;
   char *canonbuf = NULL;
-  bool malloc_tmpbuf = false;
-  char *tmpbuf = NULL;
   int result = 0;
+  struct scratch_buffer tmpbuf;
+  scratch_buffer_init (&tmpbuf);
+
   if (name != NULL)
     {
       at = alloca_account (sizeof (struct gaih_addrtuple), alloca_used);
@@ -571,11 +567,8 @@  gaih_inet (const char *name, const struct gaih_service *service,
 	  if (req->ai_family == AF_INET
 	      && (req->ai_flags & AI_CANONNAME) == 0)
 	    {
-	      /* Allocate additional room for struct host_data.  */
-	      size_t tmpbuflen = (512 + MAX_NR_ALIASES * sizeof(char*)
-				  + 16 * sizeof(char));
-	      assert (tmpbuf == NULL);
-	      tmpbuf = alloca_account (tmpbuflen, alloca_used);
+	      /* tmpbuf must not have been used so far.  */
+	      assert (tmpbuf.data == tmpbuf.__space);
 	      int rc;
 	      struct hostent th;
 	      struct hostent *h;
@@ -583,28 +576,15 @@  gaih_inet (const char *name, const struct gaih_service *service,
 
 	      while (1)
 		{
-		  rc = __gethostbyname2_r (name, AF_INET, &th, tmpbuf,
-					   tmpbuflen, &h, &herrno);
+		  rc = __gethostbyname2_r (name, AF_INET, &th,
+					   tmpbuf.data, tmpbuf.length,
+					   &h, &herrno);
 		  if (rc != ERANGE || herrno != NETDB_INTERNAL)
 		    break;
-
-		  if (!malloc_tmpbuf
-		      && __libc_use_alloca (alloca_used + 2 * tmpbuflen))
-		    tmpbuf = extend_alloca_account (tmpbuf, tmpbuflen,
-						    2 * tmpbuflen,
-						    alloca_used);
-		  else
+		  if (!scratch_buffer_grow (&tmpbuf))
 		    {
-		      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;
+		      result = -EAI_MEMORY;
+		      goto free_and_return;
 		    }
 		}
 
@@ -826,21 +806,8 @@  gaih_inet (const char *name, const struct gaih_service *service,
 	  old_res_options = _res.options;
 	  _res.options &= ~RES_USE_INET6;
 
-	  size_t tmpbuflen = 1024 + sizeof(struct gaih_addrtuple);
-	  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)
-		{
-		  _res.options |= old_res_options & RES_USE_INET6;
-		  result = -EAI_MEMORY;
-		  goto free_and_return;
-		}
-	    }
+	  /* tmpbuf has not been used yet.  */
+	  assert (tmpbuf.data == tmpbuf.__space);
 
 	  while (!no_more)
 	    {
@@ -859,8 +826,9 @@  gaih_inet (const char *name, const struct gaih_service *service,
 		  while (1)
 		    {
 		      rc = 0;
-		      status = DL_CALL_FCT (fct4, (name, pat, tmpbuf,
-						   tmpbuflen, &rc, &herrno,
+		      status = DL_CALL_FCT (fct4, (name, pat,
+						   tmpbuf.data, tmpbuf.length,
+						   &rc, &herrno,
 						   NULL));
 		      if (status == NSS_STATUS_SUCCESS)
 			break;
@@ -874,24 +842,11 @@  gaih_inet (const char *name, const struct gaih_service *service,
 			  break;
 			}
 
-		      if (!malloc_tmpbuf
-			  && __libc_use_alloca (alloca_used + 2 * tmpbuflen))
-			tmpbuf = extend_alloca_account (tmpbuf, tmpbuflen,
-							2 * tmpbuflen,
-							alloca_used);
-		      else
+		      if (!scratch_buffer_grow (&tmpbuf))
 			{
-			  char *newp = realloc (malloc_tmpbuf ? tmpbuf : NULL,
-						2 * tmpbuflen);
-			  if (newp == NULL)
-			    {
-			      _res.options |= old_res_options & RES_USE_INET6;
-			      result = -EAI_MEMORY;
-			      goto free_and_return;
-			    }
-			  tmpbuf = newp;
-			  malloc_tmpbuf = true;
-			  tmpbuflen = 2 * tmpbuflen;
+			  _res.options |= old_res_options & RES_USE_INET6;
+			  result = -EAI_MEMORY;
+			  goto free_and_return;
 			}
 		    }
 
@@ -1278,8 +1233,7 @@  gaih_inet (const char *name, const struct gaih_service *service,
     free (addrmem);
   if (malloc_canonbuf)
     free (canonbuf);
-  if (malloc_tmpbuf)
-    free (tmpbuf);
+  scratch_buffer_free (&tmpbuf);
 
   return result;
 }