[17/25] nss_files: Use struct scratch_buffer instead of extend_alloca

Message ID 886463585410f8c046babe912b326121f7a7c295.1425285061.git.fweimer@redhat.com
State Superseded
Headers

Commit Message

Florian Weimer March 1, 2015, 6:09 p.m. UTC
  In both _nss_files_gethostbyname3_r and _nss_files_initgroups_dyn,
__libc_use_alloca was misused because it was not taken into account
that extend_alloca can fail to merge allocations.
---
 nss/nss_files/files-hosts.c      | 64 +++++++---------------------------------
 nss/nss_files/files-initgroups.c | 32 +++++++-------------
 2 files changed, 20 insertions(+), 76 deletions(-)
  

Patch

diff --git a/nss/nss_files/files-hosts.c b/nss/nss_files/files-hosts.c
index 4c51c90..4fd492d 100644
--- a/nss/nss_files/files-hosts.c
+++ b/nss/nss_files/files-hosts.c
@@ -22,7 +22,7 @@ 
 #include <arpa/nameser.h>
 #include <netdb.h>
 #include <resolv.h>
-
+#include <scratch_buffer.h>
 
 /* Get implementation for some internal functions.  */
 #include "../resolv/mapv4v6addr.h"
@@ -149,15 +149,12 @@  _nss_files_gethostbyname3_r (const char *name, int af, struct hostent *result,
 	  && _res_hconf.flags & HCONF_FLAG_MULTI)
 	{
 	  /* We have to get all host entries from the file.  */
-	  size_t tmp_buflen = MIN (buflen, 4096);
-	  char tmp_buffer_stack[tmp_buflen]
-	    __attribute__ ((__aligned__ (__alignof__ (struct hostent_data))));
-	  char *tmp_buffer = tmp_buffer_stack;
 	  struct hostent tmp_result_buf;
 	  int naddrs = 1;
 	  int naliases = 0;
 	  char *bufferend;
-	  bool tmp_buffer_malloced = false;
+	  struct scratch_buffer tmpbuf;
+	  scratch_buffer_init (&tmpbuf);
 
 	  while (result->h_aliases[naliases] != NULL)
 	    ++naliases;
@@ -165,9 +162,9 @@  _nss_files_gethostbyname3_r (const char *name, int af, struct hostent *result,
 	  bufferend = (char *) &result->h_aliases[naliases + 1];
 
 	again:
-	  while ((status = internal_getent (&tmp_result_buf, tmp_buffer,
-					    tmp_buflen, errnop, herrnop, af,
-					    flags))
+	  while ((status = internal_getent (&tmp_result_buf,
+					    tmpbuf.data, tmpbuf.length,
+					    errnop, herrnop, af, flags))
 		 == NSS_STATUS_SUCCESS)
 	    {
 	      int matches = 1;
@@ -291,54 +288,13 @@  _nss_files_gethostbyname3_r (const char *name, int af, struct hostent *result,
 		}
 	    }
 
-	  if (status == NSS_STATUS_TRYAGAIN)
-	    {
-	      size_t newsize = 2 * tmp_buflen;
-	      if (tmp_buffer_malloced)
-		{
-		  char *newp = realloc (tmp_buffer, newsize);
-		  if (newp != NULL)
-		    {
-		      assert ((((uintptr_t) newp)
-			       & (__alignof__ (struct hostent_data) - 1))
-			      == 0);
-		      tmp_buffer = newp;
-		      tmp_buflen = newsize;
-		      goto again;
-		    }
-		}
-	      else if (!__libc_use_alloca (buflen + newsize))
-		{
-		  tmp_buffer = malloc (newsize);
-		  if (tmp_buffer != NULL)
-		    {
-		      assert ((((uintptr_t) tmp_buffer)
-			       & (__alignof__ (struct hostent_data) - 1))
-			      == 0);
-		      tmp_buffer_malloced = true;
-		      tmp_buflen = newsize;
-		      goto again;
-		    }
-		}
-	      else
-		{
-		  tmp_buffer
-		    = extend_alloca (tmp_buffer, tmp_buflen,
-				     newsize
-				     + __alignof__ (struct hostent_data));
-		  tmp_buffer = (char *) (((uintptr_t) tmp_buffer
-					  + __alignof__ (struct hostent_data)
-					  - 1)
-					 & ~(__alignof__ (struct hostent_data)
-					     - 1));
-		  goto again;
-		}
-	    }
+	  if (status == NSS_STATUS_TRYAGAIN
+	      && scratch_buffer_grow (&tmpbuf))
+	    goto again;
 	  else
 	    status = NSS_STATUS_SUCCESS;
 	out:
-	  if (tmp_buffer_malloced)
-	    free (tmp_buffer);
+	  scratch_buffer_free (&tmpbuf);
 	}
 
       if (! keep_stream)
diff --git a/nss/nss_files/files-initgroups.c b/nss/nss_files/files-initgroups.c
index 084d36b..abd2bc7 100644
--- a/nss/nss_files/files-initgroups.c
+++ b/nss/nss_files/files-initgroups.c
@@ -16,7 +16,6 @@ 
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
-#include <alloca.h>
 #include <errno.h>
 #include <grp.h>
 #include <nss.h>
@@ -25,6 +24,7 @@ 
 #include <sys/param.h>
 #include <stdbool.h>
 #include <stdlib.h>
+#include <scratch_buffer.h>
 
 enum nss_status
 _nss_files_initgroups_dyn (const char *user, gid_t group, long int *start,
@@ -46,9 +46,8 @@  _nss_files_initgroups_dyn (const char *user, gid_t group, long int *start,
   enum nss_status status = NSS_STATUS_SUCCESS;
   bool any = false;
 
-  size_t buflen = 1024;
-  void *buffer = alloca (buflen);
-  bool buffer_use_malloc = false;
+  struct scratch_buffer tmpbuf;
+  scratch_buffer_init (&tmpbuf);
 
   gid_t *groups = *groupsp;
 
@@ -67,26 +66,16 @@  _nss_files_initgroups_dyn (const char *user, gid_t group, long int *start,
 	}
 
       struct group grp;
-      int res = _nss_files_parse_grent (line, &grp, buffer, buflen, errnop);
+      int res = _nss_files_parse_grent (line, &grp,
+					tmpbuf.data, tmpbuf.length, errnop);
       if (res == -1)
 	{
-	  size_t newbuflen = 2 * buflen;
-	  if (buffer_use_malloc || ! __libc_use_alloca (buflen + newbuflen))
+	  if (!scratch_buffer_grow (&tmpbuf))
 	    {
-	      void *newbuf = realloc (buffer_use_malloc ? buffer : NULL,
-				      newbuflen);
-	      if (newbuf == NULL)
-		{
-		  *errnop = ENOMEM;
-		  status = NSS_STATUS_TRYAGAIN;
-		  goto out;
-		}
-	      buffer = newbuf;
-	      buflen = newbuflen;
-	      buffer_use_malloc = true;
+	      *errnop = ENOMEM;
+	      status = NSS_STATUS_TRYAGAIN;
+	      goto out;
 	    }
-	  else
-	    buffer = extend_alloca (buffer, buflen, newbuflen);
 	  /* Reread current line, the parser has clobbered it.  */
 	  fsetpos (stream, &pos);
 	  continue;
@@ -132,8 +121,7 @@  _nss_files_initgroups_dyn (const char *user, gid_t group, long int *start,
 
  out:
   /* Free memory.  */
-  if (buffer_use_malloc)
-    free (buffer);
+  scratch_buffer_free (&tmpbuf);
   free (line);
 
   fclose (stream);