summary refs log tree commit diff
path: root/nscd/hstcache.c
diff options
context:
space:
mode:
authorFlorian Weimer <fweimer@redhat.com>2018-06-25 16:04:29 +0200
committerFlorian Weimer <fweimer@redhat.com>2018-06-25 18:41:52 +0200
commit2f9f0d182eb87bfab49534d4f9ac102d6c0c0469 (patch)
tree64fa5153b603211a98a89ef0847d6640d45e38b9 /nscd/hstcache.c
parent318bad78b084cd510c7b672a1a0859c0df08dbb7 (diff)
downloadglibc-2f9f0d182eb87bfab49534d4f9ac102d6c0c0469.tar.gz
glibc-2f9f0d182eb87bfab49534d4f9ac102d6c0c0469.tar.xz
glibc-2f9f0d182eb87bfab49534d4f9ac102d6c0c0469.zip
nscd: Use struct scratch_buffer, not extend_alloca in most caches [BZ #18023]
This replaces the ERANGE retry loops with loops which have heap
fallback.  Heap allocation might actually be required for extremely
large NSS results.
Diffstat (limited to 'nscd/hstcache.c')
-rw-r--r--nscd/hstcache.c58
1 files changed, 20 insertions, 38 deletions
diff --git a/nscd/hstcache.c b/nscd/hstcache.c
index 6ef0c653ea..5597e13ec1 100644
--- a/nscd/hstcache.c
+++ b/nscd/hstcache.c
@@ -34,6 +34,7 @@
 #include <arpa/nameser.h>
 #include <sys/mman.h>
 #include <stackinfo.h>
+#include <scratch_buffer.h>
 
 #include "nscd.h"
 #include "dbg_log.h"
@@ -432,11 +433,8 @@ addhstbyX (struct database_dyn *db, int fd, request_header *req,
      look again in the table whether the dataset is now available.  We
      simply insert it.  It does not matter if it is in there twice.  The
      pruning function only will look at the timestamp.  */
-  int buflen = 1024;
-  char *buffer = (char *) alloca (buflen);
   struct hostent resultbuf;
   struct hostent *hst;
-  bool use_malloc = false;
   int errval = 0;
   int32_t ttl = INT32_MAX;
 
@@ -456,46 +454,30 @@ addhstbyX (struct database_dyn *db, int fd, request_header *req,
 	dbg_log (_("Reloading \"%s\" in hosts cache!"), (char *) str);
     }
 
-  while (lookup (req->type, key, &resultbuf, buffer, buflen, &hst, &ttl) != 0
+  struct scratch_buffer tmpbuf;
+  scratch_buffer_init (&tmpbuf);
+
+  while (lookup (req->type, key, &resultbuf,
+		 tmpbuf.data, tmpbuf.length, &hst, &ttl) != 0
 	 && h_errno == NETDB_INTERNAL
 	 && (errval = errno) == ERANGE)
-    {
-      errno = 0;
-
-      if (__glibc_unlikely (buflen > 32768))
-	{
-	  char *old_buffer = buffer;
-	  buflen *= 2;
-	  buffer = (char *) realloc (use_malloc ? buffer : NULL, buflen);
-	  if (buffer == NULL)
-	    {
-	      /* We ran out of memory.  We cannot do anything but
-		 sending a negative response.  In reality this should
-		 never happen.  */
-	      hst = NULL;
-	      buffer = old_buffer;
-
-	      /* We set the error to indicate this is (possibly) a
-		 temporary error and that it does not mean the entry
-		 is not available at all.  */
-	      h_errno = TRY_AGAIN;
-	      errval = EAGAIN;
-	      break;
-	    }
-	  use_malloc = true;
-	}
-      else
-	/* Allocate a new buffer on the stack.  If possible combine it
-	   with the previously allocated buffer.  */
-	buffer = (char *) extend_alloca (buffer, buflen, 2 * buflen);
-    }
+    if (!scratch_buffer_grow (&tmpbuf))
+      {
+	/* We ran out of memory.  We cannot do anything but sending a
+	   negative response.  In reality this should never
+	   happen.  */
+	hst = NULL;
+	/* We set the error to indicate this is (possibly) a temporary
+	   error and that it does not mean the entry is not
+	   available at all.  */
+	h_errno = TRY_AGAIN;
+	errval = EAGAIN;
+	break;
+      }
 
   time_t timeout = cache_addhst (db, fd, req, key, hst, uid, he, dh,
 				 h_errno == TRY_AGAIN ? errval : 0, ttl);
-
-  if (use_malloc)
-    free (buffer);
-
+  scratch_buffer_free (&tmpbuf);
   return timeout;
 }