[15/25] nscd: Switch to struct scratch_buffer in adhstaiX

Message ID 4feca22c942850a1692003f870eb518a24a08a99.1425285061.git.fweimer@redhat.com
State Superseded
Headers

Commit Message

Florian Weimer March 1, 2015, 5:59 p.m. UTC
  The pre-allocation of the three scratch buffers increased the initial
stack size somewhat, but if retries are needed, the previous version
used more stack space if extend_alloca could not merge allocations.
Lack of alloca accounting also means could be problematic with
extremely large NSS responses, too.
---
 nscd/aicache.c | 79 +++++++++++++++++++++++++++++++++-------------------------
 1 file changed, 45 insertions(+), 34 deletions(-)
  

Patch

diff --git a/nscd/aicache.c b/nscd/aicache.c
index 937cb93..d757b12 100644
--- a/nscd/aicache.c
+++ b/nscd/aicache.c
@@ -26,6 +26,7 @@ 
 #include <unistd.h>
 #include <sys/mman.h>
 #include <resolv/res_hconf.h>
+#include <scratch_buffer.h>
 
 #include "dbg_log.h"
 #include "nscd.h"
@@ -113,10 +114,13 @@  addhstaiX (struct database_dyn *db, int fd, request_header *req,
   int old_res_options = _res.options;
   _res.options &= ~RES_USE_INET6;
 
-  size_t tmpbuf6len = 1024;
-  char *tmpbuf6 = alloca (tmpbuf6len);
-  size_t tmpbuf4len = 0;
-  char *tmpbuf4 = NULL;
+  struct scratch_buffer tmpbuf6;
+  scratch_buffer_init (&tmpbuf6);
+  struct scratch_buffer tmpbuf4;
+  scratch_buffer_init (&tmpbuf4);
+  struct scratch_buffer canonbuf;
+  scratch_buffer_init (&canonbuf);
+
   int32_t ttl = INT32_MAX;
   ssize_t total = 0;
   char *key_copy = NULL;
@@ -129,6 +133,7 @@  addhstaiX (struct database_dyn *db, int fd, request_header *req,
       int status[2] = { NSS_STATUS_UNAVAIL, NSS_STATUS_UNAVAIL };
       int naddrs = 0;
       size_t addrslen = 0;
+
       char *canon = NULL;
       size_t canonlen;
 
@@ -143,12 +148,17 @@  addhstaiX (struct database_dyn *db, int fd, request_header *req,
 	      at = &atmem;
 	      rc6 = 0;
 	      herrno = 0;
-	      status[1] = DL_CALL_FCT (fct4, (key, &at, tmpbuf6, tmpbuf6len,
+	      status[1] = DL_CALL_FCT (fct4, (key, &at,
+					      tmpbuf6.data, tmpbuf6.length,
 					      &rc6, &herrno, &ttl));
 	      if (rc6 != ERANGE || (herrno != NETDB_INTERNAL
 				    && herrno != TRY_AGAIN))
 		break;
-	      tmpbuf6 = extend_alloca (tmpbuf6, tmpbuf6len, 2 * tmpbuf6len);
+	      if (!scratch_buffer_grow (&tmpbuf6))
+		{
+		  rc6 = ENOMEM;
+		  break;
+		}
 	    }
 
 	  if (rc6 != 0 && herrno == NETDB_INTERNAL)
@@ -226,41 +236,38 @@  addhstaiX (struct database_dyn *db, int fd, request_header *req,
 	  while (1)
 	    {
 	      rc6 = 0;
-	      status[0] = DL_CALL_FCT (fct, (key, AF_INET6, &th[0], tmpbuf6,
-					     tmpbuf6len, &rc6, &herrno, &ttl,
+	      status[0] = DL_CALL_FCT (fct, (key, AF_INET6, &th[0],
+					     tmpbuf6.data, tmpbuf6.length,
+					     &rc6, &herrno, &ttl,
 					     &canon));
 	      if (rc6 != ERANGE || herrno != NETDB_INTERNAL)
 		break;
-	      tmpbuf6 = extend_alloca (tmpbuf6, tmpbuf6len, 2 * tmpbuf6len);
+	      if (!scratch_buffer_grow (&tmpbuf6))
+		{
+		  rc6 = ENOMEM;
+		  break;
+		}
 	    }
 
 	  if (rc6 != 0 && herrno == NETDB_INTERNAL)
 	    goto out;
 
-	  /* If the IPv6 lookup has been successful do not use the
-	     buffer used in that lookup, use a new one.  */
-	  if (status[0] == NSS_STATUS_SUCCESS && rc6 == 0)
-	    {
-	      tmpbuf4len = 512;
-	      tmpbuf4 = alloca (tmpbuf4len);
-	    }
-	  else
-	    {
-	      tmpbuf4len = tmpbuf6len;
-	      tmpbuf4 = tmpbuf6;
-	    }
-
 	  /* Next collect IPv4 information.  */
 	  while (1)
 	    {
 	      rc4 = 0;
-	      status[1] = DL_CALL_FCT (fct, (key, AF_INET, &th[1], tmpbuf4,
-					     tmpbuf4len, &rc4, &herrno,
+	      status[1] = DL_CALL_FCT (fct, (key, AF_INET, &th[1],
+					     tmpbuf4.data, tmpbuf4.length,
+					     &rc4, &herrno,
 					     ttl == INT32_MAX ? &ttl : NULL,
 					     canon == NULL ? &canon : NULL));
 	      if (rc4 != ERANGE || herrno != NETDB_INTERNAL)
 		break;
-	      tmpbuf4 = extend_alloca (tmpbuf4, tmpbuf4len, 2 * tmpbuf4len);
+	      if (!scratch_buffer_grow (&tmpbuf4))
+		{
+		  rc4 = ENOMEM;
+		  break;
+		}
 	    }
 
 	  if (rc4 != 0 && herrno == NETDB_INTERNAL)
@@ -286,13 +293,11 @@  addhstaiX (struct database_dyn *db, int fd, request_header *req,
 	      cfct = __nss_lookup_function (nip, "getcanonname_r");
 	      if (cfct != NULL)
 		{
-		  const size_t max_fqdn_len = 256;
-		  char *buf = alloca (max_fqdn_len);
 		  char *s;
 		  int rc;
 
-		  if (DL_CALL_FCT (cfct, (key, buf, max_fqdn_len, &s,
-					  &rc, &herrno))
+		  if (DL_CALL_FCT (cfct, (key, canonbuf.data, canonbuf.length,
+					  &s, &rc, &herrno))
 		      == NSS_STATUS_SUCCESS)
 		    canon = s;
 		  else
@@ -321,18 +326,20 @@  addhstaiX (struct database_dyn *db, int fd, request_header *req,
 		      addrfamily = AF_INET6;
 		    }
 
-		  size_t tmpbuflen = 512;
-		  char *tmpbuf = alloca (tmpbuflen);
 		  int rc;
 		  while (1)
 		    {
 		      rc = __gethostbyaddr2_r (addr, addrlen, addrfamily,
-					       &hstent_mem, tmpbuf, tmpbuflen,
+					       &hstent_mem,
+					       canonbuf.data, canonbuf.length,
 					       &hstent, &herrno, NULL);
 		      if (rc != ERANGE || herrno != NETDB_INTERNAL)
 			break;
-		      tmpbuf = extend_alloca (tmpbuf, tmpbuflen,
-					      tmpbuflen * 2);
+		      if (!scratch_buffer_grow (&canonbuf))
+			{
+			  rc = ENOMEM;
+			  break;
+			}
 		    }
 
 		  if (rc == 0)
@@ -560,6 +567,10 @@  next_nip:
 	dh->usable = false;
     }
 
+  scratch_buffer_free (&tmpbuf6);
+  scratch_buffer_free (&tmpbuf4);
+  scratch_buffer_free (&canonbuf);
+
   return timeout;
 }