[05/18] posix: Rewrite to use struct scratch_buffer instead of extend_alloca

Message ID 1502463044-4042-6-git-send-email-adhemerval.zanella@linaro.org
State New
Headers show
Series
  • Untitled series #3282
Related show

Commit Message

Adhemerval Zanella Aug. 11, 2017, 2:50 p.m.
From: Florian Weimer <fweimer@redhat.com>


This patch removes a lot of boilerplate code to manager buffers for
getpwnam_r.

Checked on x86_64-linux-gnu.

	[BZ #18023]
	* posix/glob.c (glob): Use struct scratch_buffer instead of
	extend_alloca.
---
 posix/glob.c | 147 +++++++++++------------------------------------------------
 1 file changed, 26 insertions(+), 121 deletions(-)

-- 
2.7.4

Comments

Paul Eggert Sept. 1, 2017, 11:50 p.m. | #1
Thanks, I merged that patch into Gnulib; see:

http://lists.gnu.org/archive/html/bug-gnulib/2017-09/msg00002.html

This means Gnulib starts sharing scratch_buffer.h etc. with glibc, which 
entails some minor and safe changes to those files on the glibc side. 
Plus, glibc glob.c can be simplified slightly now. Please see the 
attached patch, which I hope can be folded into the next iteration of 
this glibc patchset.
From 05cc71685fb0e177233655c4d499ad223ffe9a6f Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert@cs.ucla.edu>

Date: Fri, 1 Sep 2017 16:37:15 -0700
Subject: [PATCH] Merge glob-related changes from Gnulib

* include/scratch_buffer.h (struct scratch_buffer):
Use portable method to align buffer, instead of relying
on GCC's __attribute__ ((aligned (...))), so that this
can be compiled with non-GCC compilers when used as
part of Gnulib.
* malloc/scratch_buffer_grow.c:
* malloc/scratch_buffer_grow_preserve.c:
* malloc/scratch_buffer_set_array_size.c:
Include <libc-config.h> first thing, if !_LIBC.
Remove stray top-level ";" that non-GCC compilers reject.
* misc/sys/cdefs.h: Do not include <bits/wordsize.h> and
<bits/long-double.h> if __WORDSIZE is already defined, so that
Gnulib-using code does not include these nonexistent files.
* posix/glob.c: Minor simplifications due to Gnulib changes:
do not include <config.h>, and do not define __set_errno.
does that via another method for glob.c.
---
 include/scratch_buffer.h               | 3 +--
 malloc/scratch_buffer_grow.c           | 6 +++++-
 malloc/scratch_buffer_grow_preserve.c  | 6 +++++-
 malloc/scratch_buffer_set_array_size.c | 6 +++++-
 misc/sys/cdefs.h                       | 8 ++++++--
 posix/glob.c                           | 8 --------
 6 files changed, 22 insertions(+), 15 deletions(-)

diff --git a/include/scratch_buffer.h b/include/scratch_buffer.h
index dd17a4a7e1..bb04662eb2 100644
--- a/include/scratch_buffer.h
+++ b/include/scratch_buffer.h
@@ -66,8 +66,7 @@
 struct scratch_buffer {
   void *data;    /* Pointer to the beginning of the scratch area.  */
   size_t length; /* Allocated space at the data pointer, in bytes.  */
-  char __space[1024]
-    __attribute__ ((aligned (__alignof__ (max_align_t))));
+  max_align_t __space[(1023 + sizeof (max_align_t)) / sizeof (max_align_t)];
 };
 
 /* Initializes *BUFFER so that BUFFER->data points to BUFFER->__space
diff --git a/malloc/scratch_buffer_grow.c b/malloc/scratch_buffer_grow.c
index 22bae506a1..d2df028654 100644
--- a/malloc/scratch_buffer_grow.c
+++ b/malloc/scratch_buffer_grow.c
@@ -16,6 +16,10 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
+#ifndef _LIBC
+# include <libc-config.h>
+#endif
+
 #include <scratch_buffer.h>
 #include <errno.h>
 
@@ -49,4 +53,4 @@ __libc_scratch_buffer_grow (struct scratch_buffer *buffer)
   buffer->length = new_length;
   return true;
 }
-libc_hidden_def (__libc_scratch_buffer_grow);
+libc_hidden_def (__libc_scratch_buffer_grow)
diff --git a/malloc/scratch_buffer_grow_preserve.c b/malloc/scratch_buffer_grow_preserve.c
index 18543ef85b..9268615311 100644
--- a/malloc/scratch_buffer_grow_preserve.c
+++ b/malloc/scratch_buffer_grow_preserve.c
@@ -16,6 +16,10 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
+#ifndef _LIBC
+# include <libc-config.h>
+#endif
+
 #include <scratch_buffer.h>
 #include <errno.h>
 #include <string.h>
@@ -60,4 +64,4 @@ __libc_scratch_buffer_grow_preserve (struct scratch_buffer *buffer)
   buffer->length = new_length;
   return true;
 }
-libc_hidden_def (__libc_scratch_buffer_grow_preserve);
+libc_hidden_def (__libc_scratch_buffer_grow_preserve)
diff --git a/malloc/scratch_buffer_set_array_size.c b/malloc/scratch_buffer_set_array_size.c
index 8ab6d9d300..6fcc115340 100644
--- a/malloc/scratch_buffer_set_array_size.c
+++ b/malloc/scratch_buffer_set_array_size.c
@@ -16,6 +16,10 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
+#ifndef _LIBC
+# include <libc-config.h>
+#endif
+
 #include <scratch_buffer.h>
 #include <errno.h>
 #include <limits.h>
@@ -57,4 +61,4 @@ __libc_scratch_buffer_set_array_size (struct scratch_buffer *buffer,
   buffer->length = new_length;
   return true;
 }
-libc_hidden_def (__libc_scratch_buffer_set_array_size);
+libc_hidden_def (__libc_scratch_buffer_set_array_size)
diff --git a/misc/sys/cdefs.h b/misc/sys/cdefs.h
index cfd39d5302..d4dd8d0418 100644
--- a/misc/sys/cdefs.h
+++ b/misc/sys/cdefs.h
@@ -415,8 +415,12 @@
       [!!sizeof (struct { int __error_if_negative: (expr) ? 2 : -1; })]
 #endif
 
-#include <bits/wordsize.h>
-#include <bits/long-double.h>
+/* The #ifndef lets Gnulib avoid including these on non-glibc
+   platforms, where the includes typically do not exist.  */
+#ifndef __WORDSIZE
+# include <bits/wordsize.h>
+# include <bits/long-double.h>
+#endif
 
 #if defined __LONG_DOUBLE_MATH_OPTIONAL && defined __NO_LONG_DOUBLE_MATH
 # define __LDBL_COMPAT 1
diff --git a/posix/glob.c b/posix/glob.c
index c0ee4dacb5..7ddc2c8d70 100644
--- a/posix/glob.c
+++ b/posix/glob.c
@@ -15,10 +15,6 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
-#ifndef _LIBC
-# include <config.h>
-#endif
-
 #include <glob.h>
 
 #include <errno.h>
@@ -39,10 +35,6 @@
 #endif
 
 #include <errno.h>
-#ifndef __set_errno
-# define __set_errno(val) errno = (val)
-#endif
-
 #include <dirent.h>
 #include <stdlib.h>
 #include <string.h>
-- 
2.13.5
Paul Eggert Sept. 2, 2017, 10:40 a.m. | #2
Adhemerval Zanella wrote:
> +		  p = getpwnam (pwtmpbuf.data);


That won't work on non-glibc platforms that lack getpwnam_r, as the argument 
should be 'name'. I installed the attached patch to Gnulib to fix this.
From 88855bf9f1cfc2e5165e4200bf62aa949e76db90 Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert@cs.ucla.edu>

Date: Sat, 2 Sep 2017 03:37:46 -0700
Subject: [PATCH] glob: fix typo in recent change

* lib/glob.c (glob) [!HAVE_GETPWNAM_R && !_LIBC]:
Fix recently-introduced typo.
---
 ChangeLog  | 4 ++++
 lib/glob.c | 2 +-
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/ChangeLog b/ChangeLog
index 867662d..4dd0367 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,9 @@
 2017-09-02  Paul Eggert  <eggert@cs.ucla.edu>
 
+	glob: fix typo in recent change
+	* lib/glob.c (glob) [!HAVE_GETPWNAM_R && !_LIBC]:
+	Fix recently-introduced typo.
+
 	glob: don't save and restore errno unnecessarily
 	* lib/glob.c (glob): Don't save and restore errno
 	merely because we have getpwnam_r.
diff --git a/lib/glob.c b/lib/glob.c
index 8de2d5f..f1b30ee 100644
--- a/lib/glob.c
+++ b/lib/glob.c
@@ -658,7 +658,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
                         }
                     }
 # else
-                  p = getpwnam (pwtmpbuf.data);
+                  p = getpwnam (name);
 # endif
                   if (p != NULL)
                     {
-- 
2.7.4

Patch

diff --git a/posix/glob.c b/posix/glob.c
index 7b6b426..99e9c54 100644
--- a/posix/glob.c
+++ b/posix/glob.c
@@ -89,12 +89,8 @@ 
 #include <fnmatch.h>
 
 #include <glob_internal.h>
+#include <scratch_buffer.h>
 
-#ifdef _SC_GETPW_R_SIZE_MAX
-# define GETPW_R_SIZE_MAX()	sysconf (_SC_GETPW_R_SIZE_MAX)
-#else
-# define GETPW_R_SIZE_MAX()	(-1)
-#endif
 #ifdef _SC_LOGIN_NAME_MAX
 # define GET_LOGIN_NAME_MAX()	sysconf (_SC_LOGIN_NAME_MAX)
 #else
@@ -696,97 +692,43 @@  glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
 	      if (success)
 		{
 		  struct passwd *p;
-		  char *malloc_pwtmpbuf = NULL;
-		  char *pwtmpbuf;
 #   if defined HAVE_GETPWNAM_R || defined _LIBC
-		  long int pwbuflenmax = GETPW_R_SIZE_MAX ();
-		  size_t pwbuflen = pwbuflenmax;
 		  struct passwd pwbuf;
 		  int save = errno;
+		  struct scratch_buffer pwtmpbuf;
+		  scratch_buffer_init (&pwtmpbuf);
 
-#    ifndef _LIBC
-                  if (! (0 < pwbuflenmax && pwbuflenmax <= SIZE_MAX))
-		    /* `sysconf' does not support _SC_GETPW_R_SIZE_MAX.
-		       Try a moderate value.  */
-		    pwbuflen = 1024;
-#    endif
-		  if (glob_use_alloca (alloca_used, pwbuflen))
-		    pwtmpbuf = alloca_account (pwbuflen, alloca_used);
-		  else
-		    {
-		      pwtmpbuf = malloc (pwbuflen);
-		      if (pwtmpbuf == NULL)
-			{
-			  if (__glibc_unlikely (malloc_name))
-			    free (name);
-			  retval = GLOB_NOSPACE;
-			  goto out;
-			}
-		      malloc_pwtmpbuf = pwtmpbuf;
-		    }
-
-		  while (getpwnam_r (name, &pwbuf, pwtmpbuf, pwbuflen, &p)
+		  while (getpwnam_r (name, &pwbuf,
+				     pwtmpbuf.data, pwtmpbuf.length, &p)
 			 != 0)
 		    {
-		      size_t newlen;
-		      bool v;
 		      if (errno != ERANGE)
 			{
 			  p = NULL;
 			  break;
 			}
-		      v = size_add_wrapv (pwbuflen, pwbuflen, &newlen);
-		      if (!v && malloc_pwtmpbuf == NULL
-			  && glob_use_alloca (alloca_used, newlen))
-			pwtmpbuf = extend_alloca_account (pwtmpbuf, pwbuflen,
-							  newlen, alloca_used);
-		      else
+		      if (!scratch_buffer_grow (&pwtmpbuf))
 			{
-			  char *newp = (v ? NULL
-					: realloc (malloc_pwtmpbuf, newlen));
-			  if (newp == NULL)
-			    {
-			      free (malloc_pwtmpbuf);
-			      if (__glibc_unlikely (malloc_name))
-				free (name);
-			      retval = GLOB_NOSPACE;
-			      goto out;
-			    }
-			  malloc_pwtmpbuf = pwtmpbuf = newp;
+			  retval = GLOB_NOSPACE;
+			  goto out;
 			}
-		      pwbuflen = newlen;
 		      __set_errno (save);
 		    }
 #   else
-		  p = getpwnam (name);
+		  p = getpwnam (pwtmpbuf.data);
 #   endif
-		  if (__glibc_unlikely (malloc_name))
-		    free (name);
 		  if (p != NULL)
 		    {
-		      if (malloc_pwtmpbuf == NULL)
-			home_dir = p->pw_dir;
-		      else
+		      home_dir = strdup (p->pw_dir);
+		      malloc_home_dir = 1;
+		      if (home_dir == NULL)
 			{
-			  size_t home_dir_len = strlen (p->pw_dir) + 1;
-			  if (glob_use_alloca (alloca_used, home_dir_len))
-			    home_dir = alloca_account (home_dir_len,
-						       alloca_used);
-			  else
-			    {
-			      home_dir = malloc (home_dir_len);
-			      if (home_dir == NULL)
-				{
-				  free (pwtmpbuf);
-				  retval = GLOB_NOSPACE;
-				  goto out;
-				}
-			      malloc_home_dir = 1;
-			    }
-			  memcpy (home_dir, p->pw_dir, home_dir_len);
+			  scratch_buffer_free (&pwtmpbuf);
+			  retval = GLOB_NOSPACE;
+			  goto out;
 			}
 		    }
-		  free (malloc_pwtmpbuf);
+		  scratch_buffer_free (&pwtmpbuf);
 		}
 	      else
 		{
@@ -924,59 +866,25 @@  glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
 	  /* Look up specific user's home directory.  */
 	  {
 	    struct passwd *p;
-	    char *malloc_pwtmpbuf = NULL;
+	    struct scratch_buffer pwtmpbuf;
+	    scratch_buffer_init (&pwtmpbuf);
+
 #  if defined HAVE_GETPWNAM_R || defined _LIBC
-	    long int buflenmax = GETPW_R_SIZE_MAX ();
-	    size_t buflen = buflenmax;
-	    char *pwtmpbuf;
 	    struct passwd pwbuf;
 	    int save = errno;
 
-#   ifndef _LIBC
-	    if (! (0 <= buflenmax && buflenmax <= SIZE_MAX))
-	      /* Perhaps 'sysconf' does not support _SC_GETPW_R_SIZE_MAX.  Try a
-		 moderate value.  */
-	      buflen = 1024;
-#   endif
-	    if (glob_use_alloca (alloca_used, buflen))
-	      pwtmpbuf = alloca_account (buflen, alloca_used);
-	    else
-	      {
-		pwtmpbuf = malloc (buflen);
-		if (pwtmpbuf == NULL)
-		  {
-		  nomem_getpw:
-		    if (__glibc_unlikely (malloc_user_name))
-		      free (user_name);
-		    retval = GLOB_NOSPACE;
-		    goto out;
-		  }
-		malloc_pwtmpbuf = pwtmpbuf;
-	      }
-
-	    while (getpwnam_r (user_name, &pwbuf, pwtmpbuf, buflen, &p) != 0)
+	    while (getpwnam_r (user_name, &pwbuf,
+			       pwtmpbuf.data, pwtmpbuf.length, &p) != 0)
 	      {
-		size_t newlen;
-		bool v;
 		if (errno != ERANGE)
 		  {
 		    p = NULL;
 		    break;
 		  }
-		v = size_add_wrapv (buflen, buflen, &newlen);
-		if (!v && malloc_pwtmpbuf == NULL
-		    && glob_use_alloca (alloca_used, newlen))
-		  pwtmpbuf = extend_alloca_account (pwtmpbuf, buflen,
-						    newlen, alloca_used);
-		else
+		if (!scratch_buffer_grow (&pwtmpbuf))
 		  {
-		    char *newp = v ? NULL : realloc (malloc_pwtmpbuf, newlen);
-		    if (newp == NULL)
-		      {
-			free (malloc_pwtmpbuf);
-			goto nomem_getpw;
-		      }
-		    malloc_pwtmpbuf = pwtmpbuf = newp;
+		    retval = GLOB_NOSPACE;
+		    goto out;
 		  }
 		__set_errno (save);
 	      }
@@ -1005,7 +913,7 @@  glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
 		    dirname = malloc (home_len + rest_len + 1);
 		    if (dirname == NULL)
 		      {
-			free (malloc_pwtmpbuf);
+			scratch_buffer_free (&pwtmpbuf);
 			retval = GLOB_NOSPACE;
 			goto out;
 		      }
@@ -1016,13 +924,9 @@  glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
 
 		dirlen = home_len + rest_len;
 		dirname_modified = 1;
-
-		free (malloc_pwtmpbuf);
 	      }
 	    else
 	      {
-		free (malloc_pwtmpbuf);
-
 		if (flags & GLOB_TILDE_CHECK)
 		  {
 		  /* We have to regard it as an error if we cannot find the
@@ -1031,6 +935,7 @@  glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
 		    goto out;
 		  }
 	      }
+	    scratch_buffer_free (&pwtmpbuf);
 	  }
 	}
 # endif	/* Not Amiga && not WINDOWS32.  */