Florian Weimer wrote:
This configure test is invalid because __libc_scratch_buffer_grow is a
GLIBC_PRIVATE symbol not part of the ABI.

You really need to rename those __libc_* functions because they are in
the internal glibc namespace.

Done by installing the first attached patch into Gnulib. This doesn't need any change to glibc: though it renames the Gnulib files that correspond to glibc, it does not change their contents.

It is an annoyance, though, that Gnulib-using apps now need another copy of the functions in question. How about publicizing that part of the glibc API, to avoid the duplication?

While looking into the above problem, I noticed a portability issue with platforms lacking getpwnam_r. Fixed in Gnulib in the 2nd attached patch.

And while looking into *that* problem, I noticed that the code needlessly saves and restores errno on platforms that have getpwnam_r. Fixed in Gnulib in the 3rd attached patch.

The last two patches should be ported back to glibc.

struct scratch_buffer depends on a GNU C extension:
assignment to an object changes its dynamic type.  It is not standard C.
  Standard C only allows one way to allocate untyped memory, and that is
malloc.

That should not be a problem, as Gnulib code regularly breaks those standard-C rules when it comes to memory allocation. The old glob.c broke those rules too, and the change should not make us any worse in that department. The code should continue to work on all practical platforms that I know about; if you are aware of any realistic counterexamples please let us know.
From dca11d0f59e9610bc3cf000c82429609ba787b73 Mon Sep 17 00:00:00 2001
From: Paul Eggert <egg...@cs.ucla.edu>
Date: Sat, 2 Sep 2017 01:21:03 -0700
Subject: [PATCH 1/3] =?UTF-8?q?scratch=5Fbuffer:=20don=E2=80=99t=20use=20p?=
 =?UTF-8?q?rivate=20glibc=20API?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Suggested by Florian Weimer in:
http://lists.gnu.org/archive/html/bug-gnulib/2017-09/msg00004.html
* lib/scratch_buffer.h: Rename to lib/malloc/scratch_buffer.h.
* lib/scratch_buffer_grow.c: Rename to
lib/malloc/scratch_buffer_grow.c.
* lib/scratch_buffer_grow_preserve.c: Rename to
lib/malloc/scratch_buffer_grow_preserve.c.
* lib/scratch_buffer_set_array_size.c: Rename to
lib/malloc/scratch_buffer_set_array_size.c.
* lib/scratch_buffer.h: New file.
* modules/scratch_buffer (Files, Makefile.am):
Adjust to source-file renaming.
---
 ChangeLog                                  |  16 ++++
 lib/malloc/scratch_buffer.h                | 135 ++++++++++++++++++++++++++++
 lib/malloc/scratch_buffer_grow.c           |  56 ++++++++++++
 lib/malloc/scratch_buffer_grow_preserve.c  |  67 ++++++++++++++
 lib/malloc/scratch_buffer_set_array_size.c |  64 +++++++++++++
 lib/scratch_buffer.h                       | 139 +----------------------------
 lib/scratch_buffer_grow.c                  |  56 ------------
 lib/scratch_buffer_grow_preserve.c         |  67 --------------
 lib/scratch_buffer_set_array_size.c        |  64 -------------
 modules/scratch_buffer                     |  16 ++--
 10 files changed, 349 insertions(+), 331 deletions(-)
 create mode 100644 lib/malloc/scratch_buffer.h
 create mode 100644 lib/malloc/scratch_buffer_grow.c
 create mode 100644 lib/malloc/scratch_buffer_grow_preserve.c
 create mode 100644 lib/malloc/scratch_buffer_set_array_size.c
 delete mode 100644 lib/scratch_buffer_grow.c
 delete mode 100644 lib/scratch_buffer_grow_preserve.c
 delete mode 100644 lib/scratch_buffer_set_array_size.c

diff --git a/ChangeLog b/ChangeLog
index a61d775..1159480 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+2017-09-02  Paul Eggert  <egg...@cs.ucla.edu>
+
+	scratch_buffer: don’t use private glibc API
+	Suggested by Florian Weimer in:
+	http://lists.gnu.org/archive/html/bug-gnulib/2017-09/msg00004.html
+	* lib/scratch_buffer.h: Rename to lib/malloc/scratch_buffer.h.
+	* lib/scratch_buffer_grow.c: Rename to
+	lib/malloc/scratch_buffer_grow.c.
+	* lib/scratch_buffer_grow_preserve.c: Rename to
+	lib/malloc/scratch_buffer_grow_preserve.c.
+	* lib/scratch_buffer_set_array_size.c: Rename to
+	lib/malloc/scratch_buffer_set_array_size.c.
+	* lib/scratch_buffer.h: New file.
+	* modules/scratch_buffer (Files, Makefile.am):
+	Adjust to source-file renaming.
+
 2017-09-01  Paul Eggert  <egg...@cs.ucla.edu>
 
 	glob: use scratch_buffer instead of extend_alloca
diff --git a/lib/malloc/scratch_buffer.h b/lib/malloc/scratch_buffer.h
new file mode 100644
index 0000000..bb04662
--- /dev/null
+++ b/lib/malloc/scratch_buffer.h
@@ -0,0 +1,135 @@
+/* Variable-sized buffer with on-stack default allocation.
+   Copyright (C) 2015-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _SCRATCH_BUFFER_H
+#define _SCRATCH_BUFFER_H
+
+/* Scratch buffers with a default stack allocation and fallback to
+   heap allocation.  It is expected that this function is used in this
+   way:
+
+     struct scratch_buffer tmpbuf;
+     scratch_buffer_init (&tmpbuf);
+
+     while (!function_that_uses_buffer (tmpbuf.data, tmpbuf.length))
+       if (!scratch_buffer_grow (&tmpbuf))
+	 return -1;
+
+     scratch_buffer_free (&tmpbuf);
+     return 0;
+
+   The allocation functions (scratch_buffer_grow,
+   scratch_buffer_grow_preserve, scratch_buffer_set_array_size) make
+   sure that the heap allocation, if any, is freed, so that the code
+   above does not have a memory leak.  The buffer still remains in a
+   state that can be deallocated using scratch_buffer_free, so a loop
+   like this is valid as well:
+
+     struct scratch_buffer tmpbuf;
+     scratch_buffer_init (&tmpbuf);
+
+     while (!function_that_uses_buffer (tmpbuf.data, tmpbuf.length))
+       if (!scratch_buffer_grow (&tmpbuf))
+	 break;
+
+     scratch_buffer_free (&tmpbuf);
+
+   scratch_buffer_grow and scratch_buffer_grow_preserve are guaranteed
+   to grow the buffer by at least 512 bytes.  This means that when
+   using the scratch buffer as a backing store for a non-character
+   array whose element size, in bytes, is 512 or smaller, the scratch
+   buffer only has to grow once to make room for at least one more
+   element.
+*/
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdlib.h>
+
+/* Scratch buffer.  Must be initialized with scratch_buffer_init
+   before its use.  */
+struct scratch_buffer {
+  void *data;    /* Pointer to the beginning of the scratch area.  */
+  size_t length; /* Allocated space at the data pointer, in bytes.  */
+  max_align_t __space[(1023 + sizeof (max_align_t)) / sizeof (max_align_t)];
+};
+
+/* Initializes *BUFFER so that BUFFER->data points to BUFFER->__space
+   and BUFFER->length reflects the available space.  */
+static inline void
+scratch_buffer_init (struct scratch_buffer *buffer)
+{
+  buffer->data = buffer->__space;
+  buffer->length = sizeof (buffer->__space);
+}
+
+/* Deallocates *BUFFER (if it was heap-allocated).  */
+static inline void
+scratch_buffer_free (struct scratch_buffer *buffer)
+{
+  if (buffer->data != buffer->__space)
+    free (buffer->data);
+}
+
+/* Grow *BUFFER by some arbitrary amount.  The buffer contents is NOT
+   preserved.  Return true on success, false on allocation failure (in
+   which case the old buffer is freed).  On success, the new buffer is
+   larger than the previous size.  On failure, *BUFFER is deallocated,
+   but remains in a free-able state, and errno is set.  */
+bool __libc_scratch_buffer_grow (struct scratch_buffer *buffer);
+libc_hidden_proto (__libc_scratch_buffer_grow)
+
+/* Alias for __libc_scratch_buffer_grow.  */
+static __always_inline bool
+scratch_buffer_grow (struct scratch_buffer *buffer)
+{
+  return __glibc_likely (__libc_scratch_buffer_grow (buffer));
+}
+
+/* Like __libc_scratch_buffer_grow, but preserve the old buffer
+   contents on success, as a prefix of the new buffer.  */
+bool __libc_scratch_buffer_grow_preserve (struct scratch_buffer *buffer);
+libc_hidden_proto (__libc_scratch_buffer_grow_preserve)
+
+/* Alias for __libc_scratch_buffer_grow_preserve.  */
+static __always_inline bool
+scratch_buffer_grow_preserve (struct scratch_buffer *buffer)
+{
+  return __glibc_likely (__libc_scratch_buffer_grow_preserve (buffer));
+}
+
+/* Grow *BUFFER so that it can store at least NELEM elements of SIZE
+   bytes.  The buffer contents are NOT preserved.  Both NELEM and SIZE
+   can be zero.  Return true on success, false on allocation failure
+   (in which case the old buffer is freed, but *BUFFER remains in a
+   free-able state, and errno is set).  It is unspecified whether this
+   function can reduce the array size.  */
+bool __libc_scratch_buffer_set_array_size (struct scratch_buffer *buffer,
+					   size_t nelem, size_t size);
+libc_hidden_proto (__libc_scratch_buffer_set_array_size)
+
+/* Alias for __libc_scratch_set_array_size.  */
+static __always_inline bool
+scratch_buffer_set_array_size (struct scratch_buffer *buffer,
+			       size_t nelem, size_t size)
+{
+  return __glibc_likely (__libc_scratch_buffer_set_array_size
+			 (buffer, nelem, size));
+}
+
+#endif /* _SCRATCH_BUFFER_H */
diff --git a/lib/malloc/scratch_buffer_grow.c b/lib/malloc/scratch_buffer_grow.c
new file mode 100644
index 0000000..d2df028
--- /dev/null
+++ b/lib/malloc/scratch_buffer_grow.c
@@ -0,0 +1,56 @@
+/* Variable-sized buffer with on-stack default allocation.
+   Copyright (C) 2015-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   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>
+
+bool
+__libc_scratch_buffer_grow (struct scratch_buffer *buffer)
+{
+  void *new_ptr;
+  size_t new_length = buffer->length * 2;
+
+  /* Discard old buffer.  */
+  scratch_buffer_free (buffer);
+
+  /* Check for overflow.  */
+  if (__glibc_likely (new_length >= buffer->length))
+    new_ptr = malloc (new_length);
+  else
+    {
+      __set_errno (ENOMEM);
+      new_ptr = NULL;
+    }
+
+  if (__glibc_unlikely (new_ptr == NULL))
+    {
+      /* Buffer must remain valid to free.  */
+      scratch_buffer_init (buffer);
+      return false;
+    }
+
+  /* Install new heap-based buffer.  */
+  buffer->data = new_ptr;
+  buffer->length = new_length;
+  return true;
+}
+libc_hidden_def (__libc_scratch_buffer_grow)
diff --git a/lib/malloc/scratch_buffer_grow_preserve.c b/lib/malloc/scratch_buffer_grow_preserve.c
new file mode 100644
index 0000000..9268615
--- /dev/null
+++ b/lib/malloc/scratch_buffer_grow_preserve.c
@@ -0,0 +1,67 @@
+/* Variable-sized buffer with on-stack default allocation.
+   Copyright (C) 2015-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   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>
+
+bool
+__libc_scratch_buffer_grow_preserve (struct scratch_buffer *buffer)
+{
+  size_t new_length = 2 * buffer->length;
+  void *new_ptr;
+
+  if (buffer->data == buffer->__space)
+    {
+      /* Move buffer to the heap.  No overflow is possible because
+	 buffer->length describes a small buffer on the stack.  */
+      new_ptr = malloc (new_length);
+      if (new_ptr == NULL)
+	return false;
+      memcpy (new_ptr, buffer->__space, buffer->length);
+    }
+  else
+    {
+      /* Buffer was already on the heap.  Check for overflow.  */
+      if (__glibc_likely (new_length >= buffer->length))
+	new_ptr = realloc (buffer->data, new_length);
+      else
+	{
+	  __set_errno (ENOMEM);
+	  new_ptr = NULL;
+	}
+
+      if (__glibc_unlikely (new_ptr == NULL))
+	{
+	  /* Deallocate, but buffer must remain valid to free.  */
+	  free (buffer->data);
+	  scratch_buffer_init (buffer);
+	  return false;
+	}
+    }
+
+  /* Install new heap-based buffer.  */
+  buffer->data = new_ptr;
+  buffer->length = new_length;
+  return true;
+}
+libc_hidden_def (__libc_scratch_buffer_grow_preserve)
diff --git a/lib/malloc/scratch_buffer_set_array_size.c b/lib/malloc/scratch_buffer_set_array_size.c
new file mode 100644
index 0000000..6fcc115
--- /dev/null
+++ b/lib/malloc/scratch_buffer_set_array_size.c
@@ -0,0 +1,64 @@
+/* Variable-sized buffer with on-stack default allocation.
+   Copyright (C) 2015-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   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>
+
+bool
+__libc_scratch_buffer_set_array_size (struct scratch_buffer *buffer,
+				      size_t nelem, size_t size)
+{
+  size_t new_length = nelem * size;
+
+  /* Avoid overflow check if both values are small. */
+  if ((nelem | size) >> (sizeof (size_t) * CHAR_BIT / 2) != 0
+      && nelem != 0 && size != new_length / nelem)
+    {
+      /* Overflow.  Discard the old buffer, but it must remain valid
+	 to free.  */
+      scratch_buffer_free (buffer);
+      scratch_buffer_init (buffer);
+      __set_errno (ENOMEM);
+      return false;
+    }
+
+  if (new_length <= buffer->length)
+    return true;
+
+  /* Discard old buffer.  */
+  scratch_buffer_free (buffer);
+
+  char *new_ptr = malloc (new_length);
+  if (new_ptr == NULL)
+    {
+      /* Buffer must remain valid to free.  */
+      scratch_buffer_init (buffer);
+      return false;
+    }
+
+  /* Install new heap-based buffer.  */
+  buffer->data = new_ptr;
+  buffer->length = new_length;
+  return true;
+}
+libc_hidden_def (__libc_scratch_buffer_set_array_size)
diff --git a/lib/scratch_buffer.h b/lib/scratch_buffer.h
index bb04662..52f0ed6 100644
--- a/lib/scratch_buffer.h
+++ b/lib/scratch_buffer.h
@@ -1,135 +1,4 @@
-/* Variable-sized buffer with on-stack default allocation.
-   Copyright (C) 2015-2017 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <http://www.gnu.org/licenses/>.  */
-
-#ifndef _SCRATCH_BUFFER_H
-#define _SCRATCH_BUFFER_H
-
-/* Scratch buffers with a default stack allocation and fallback to
-   heap allocation.  It is expected that this function is used in this
-   way:
-
-     struct scratch_buffer tmpbuf;
-     scratch_buffer_init (&tmpbuf);
-
-     while (!function_that_uses_buffer (tmpbuf.data, tmpbuf.length))
-       if (!scratch_buffer_grow (&tmpbuf))
-	 return -1;
-
-     scratch_buffer_free (&tmpbuf);
-     return 0;
-
-   The allocation functions (scratch_buffer_grow,
-   scratch_buffer_grow_preserve, scratch_buffer_set_array_size) make
-   sure that the heap allocation, if any, is freed, so that the code
-   above does not have a memory leak.  The buffer still remains in a
-   state that can be deallocated using scratch_buffer_free, so a loop
-   like this is valid as well:
-
-     struct scratch_buffer tmpbuf;
-     scratch_buffer_init (&tmpbuf);
-
-     while (!function_that_uses_buffer (tmpbuf.data, tmpbuf.length))
-       if (!scratch_buffer_grow (&tmpbuf))
-	 break;
-
-     scratch_buffer_free (&tmpbuf);
-
-   scratch_buffer_grow and scratch_buffer_grow_preserve are guaranteed
-   to grow the buffer by at least 512 bytes.  This means that when
-   using the scratch buffer as a backing store for a non-character
-   array whose element size, in bytes, is 512 or smaller, the scratch
-   buffer only has to grow once to make room for at least one more
-   element.
-*/
-
-#include <stdbool.h>
-#include <stddef.h>
-#include <stdlib.h>
-
-/* Scratch buffer.  Must be initialized with scratch_buffer_init
-   before its use.  */
-struct scratch_buffer {
-  void *data;    /* Pointer to the beginning of the scratch area.  */
-  size_t length; /* Allocated space at the data pointer, in bytes.  */
-  max_align_t __space[(1023 + sizeof (max_align_t)) / sizeof (max_align_t)];
-};
-
-/* Initializes *BUFFER so that BUFFER->data points to BUFFER->__space
-   and BUFFER->length reflects the available space.  */
-static inline void
-scratch_buffer_init (struct scratch_buffer *buffer)
-{
-  buffer->data = buffer->__space;
-  buffer->length = sizeof (buffer->__space);
-}
-
-/* Deallocates *BUFFER (if it was heap-allocated).  */
-static inline void
-scratch_buffer_free (struct scratch_buffer *buffer)
-{
-  if (buffer->data != buffer->__space)
-    free (buffer->data);
-}
-
-/* Grow *BUFFER by some arbitrary amount.  The buffer contents is NOT
-   preserved.  Return true on success, false on allocation failure (in
-   which case the old buffer is freed).  On success, the new buffer is
-   larger than the previous size.  On failure, *BUFFER is deallocated,
-   but remains in a free-able state, and errno is set.  */
-bool __libc_scratch_buffer_grow (struct scratch_buffer *buffer);
-libc_hidden_proto (__libc_scratch_buffer_grow)
-
-/* Alias for __libc_scratch_buffer_grow.  */
-static __always_inline bool
-scratch_buffer_grow (struct scratch_buffer *buffer)
-{
-  return __glibc_likely (__libc_scratch_buffer_grow (buffer));
-}
-
-/* Like __libc_scratch_buffer_grow, but preserve the old buffer
-   contents on success, as a prefix of the new buffer.  */
-bool __libc_scratch_buffer_grow_preserve (struct scratch_buffer *buffer);
-libc_hidden_proto (__libc_scratch_buffer_grow_preserve)
-
-/* Alias for __libc_scratch_buffer_grow_preserve.  */
-static __always_inline bool
-scratch_buffer_grow_preserve (struct scratch_buffer *buffer)
-{
-  return __glibc_likely (__libc_scratch_buffer_grow_preserve (buffer));
-}
-
-/* Grow *BUFFER so that it can store at least NELEM elements of SIZE
-   bytes.  The buffer contents are NOT preserved.  Both NELEM and SIZE
-   can be zero.  Return true on success, false on allocation failure
-   (in which case the old buffer is freed, but *BUFFER remains in a
-   free-able state, and errno is set).  It is unspecified whether this
-   function can reduce the array size.  */
-bool __libc_scratch_buffer_set_array_size (struct scratch_buffer *buffer,
-					   size_t nelem, size_t size);
-libc_hidden_proto (__libc_scratch_buffer_set_array_size)
-
-/* Alias for __libc_scratch_set_array_size.  */
-static __always_inline bool
-scratch_buffer_set_array_size (struct scratch_buffer *buffer,
-			       size_t nelem, size_t size)
-{
-  return __glibc_likely (__libc_scratch_buffer_set_array_size
-			 (buffer, nelem, size));
-}
-
-#endif /* _SCRATCH_BUFFER_H */
+#define __libc_scratch_buffer_grow gl_scratch_buffer_grow
+#define __libc_scratch_buffer_grow_preserve gl_scratch_buffer_grow_preserve
+#define __libc_scratch_buffer_set_array_size gl_scratch_buffer_set_array_size
+#include <malloc/scratch_buffer.h>
diff --git a/lib/scratch_buffer_grow.c b/lib/scratch_buffer_grow.c
deleted file mode 100644
index d2df028..0000000
--- a/lib/scratch_buffer_grow.c
+++ /dev/null
@@ -1,56 +0,0 @@
-/* Variable-sized buffer with on-stack default allocation.
-   Copyright (C) 2015-2017 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   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>
-
-bool
-__libc_scratch_buffer_grow (struct scratch_buffer *buffer)
-{
-  void *new_ptr;
-  size_t new_length = buffer->length * 2;
-
-  /* Discard old buffer.  */
-  scratch_buffer_free (buffer);
-
-  /* Check for overflow.  */
-  if (__glibc_likely (new_length >= buffer->length))
-    new_ptr = malloc (new_length);
-  else
-    {
-      __set_errno (ENOMEM);
-      new_ptr = NULL;
-    }
-
-  if (__glibc_unlikely (new_ptr == NULL))
-    {
-      /* Buffer must remain valid to free.  */
-      scratch_buffer_init (buffer);
-      return false;
-    }
-
-  /* Install new heap-based buffer.  */
-  buffer->data = new_ptr;
-  buffer->length = new_length;
-  return true;
-}
-libc_hidden_def (__libc_scratch_buffer_grow)
diff --git a/lib/scratch_buffer_grow_preserve.c b/lib/scratch_buffer_grow_preserve.c
deleted file mode 100644
index 9268615..0000000
--- a/lib/scratch_buffer_grow_preserve.c
+++ /dev/null
@@ -1,67 +0,0 @@
-/* Variable-sized buffer with on-stack default allocation.
-   Copyright (C) 2015-2017 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   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>
-
-bool
-__libc_scratch_buffer_grow_preserve (struct scratch_buffer *buffer)
-{
-  size_t new_length = 2 * buffer->length;
-  void *new_ptr;
-
-  if (buffer->data == buffer->__space)
-    {
-      /* Move buffer to the heap.  No overflow is possible because
-	 buffer->length describes a small buffer on the stack.  */
-      new_ptr = malloc (new_length);
-      if (new_ptr == NULL)
-	return false;
-      memcpy (new_ptr, buffer->__space, buffer->length);
-    }
-  else
-    {
-      /* Buffer was already on the heap.  Check for overflow.  */
-      if (__glibc_likely (new_length >= buffer->length))
-	new_ptr = realloc (buffer->data, new_length);
-      else
-	{
-	  __set_errno (ENOMEM);
-	  new_ptr = NULL;
-	}
-
-      if (__glibc_unlikely (new_ptr == NULL))
-	{
-	  /* Deallocate, but buffer must remain valid to free.  */
-	  free (buffer->data);
-	  scratch_buffer_init (buffer);
-	  return false;
-	}
-    }
-
-  /* Install new heap-based buffer.  */
-  buffer->data = new_ptr;
-  buffer->length = new_length;
-  return true;
-}
-libc_hidden_def (__libc_scratch_buffer_grow_preserve)
diff --git a/lib/scratch_buffer_set_array_size.c b/lib/scratch_buffer_set_array_size.c
deleted file mode 100644
index 6fcc115..0000000
--- a/lib/scratch_buffer_set_array_size.c
+++ /dev/null
@@ -1,64 +0,0 @@
-/* Variable-sized buffer with on-stack default allocation.
-   Copyright (C) 2015-2017 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   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>
-
-bool
-__libc_scratch_buffer_set_array_size (struct scratch_buffer *buffer,
-				      size_t nelem, size_t size)
-{
-  size_t new_length = nelem * size;
-
-  /* Avoid overflow check if both values are small. */
-  if ((nelem | size) >> (sizeof (size_t) * CHAR_BIT / 2) != 0
-      && nelem != 0 && size != new_length / nelem)
-    {
-      /* Overflow.  Discard the old buffer, but it must remain valid
-	 to free.  */
-      scratch_buffer_free (buffer);
-      scratch_buffer_init (buffer);
-      __set_errno (ENOMEM);
-      return false;
-    }
-
-  if (new_length <= buffer->length)
-    return true;
-
-  /* Discard old buffer.  */
-  scratch_buffer_free (buffer);
-
-  char *new_ptr = malloc (new_length);
-  if (new_ptr == NULL)
-    {
-      /* Buffer must remain valid to free.  */
-      scratch_buffer_init (buffer);
-      return false;
-    }
-
-  /* Install new heap-based buffer.  */
-  buffer->data = new_ptr;
-  buffer->length = new_length;
-  return true;
-}
-libc_hidden_def (__libc_scratch_buffer_set_array_size)
diff --git a/modules/scratch_buffer b/modules/scratch_buffer
index 7502d70..e59dd62 100644
--- a/modules/scratch_buffer
+++ b/modules/scratch_buffer
@@ -3,9 +3,10 @@ Variable-sized buffer with on-stack default allocation.
 
 Files:
 lib/scratch_buffer.h
-lib/scratch_buffer_grow.c
-lib/scratch_buffer_grow_preserve.c
-lib/scratch_buffer_set_array_size.c
+lib/malloc/scratch_buffer.h
+lib/malloc/scratch_buffer_grow.c
+lib/malloc/scratch_buffer_grow_preserve.c
+lib/malloc/scratch_buffer_set_array_size.c
 
 Depends-on:
 libc-config
@@ -13,14 +14,11 @@ stdbool
 stddef
 
 configure.ac:
-AC_CHECK_FUNCS_ONCE([__libc_scratch_buffer_grow])
-if test "$ac_cv_func___libc_scratch_buffer_grow" != yes; then
-  AC_LIBOBJ([scratch_buffer_grow])
-  AC_LIBOBJ([scratch_buffer_grow_preserve])
-  AC_LIBOBJ([scratch_buffer_set_array_size])
-fi
 
 Makefile.am:
+lib_SOURCES += malloc/scratch_buffer_grow.c \
+               malloc/scratch_buffer_grow_preserve.c \
+               malloc/scratch_buffer_set_array_size.c
 
 Include:
 <scratch_buffer.h>
-- 
2.7.4

From 742b1c14418dd3085c2e49aa05300399fb791360 Mon Sep 17 00:00:00 2001
From: Paul Eggert <egg...@cs.ucla.edu>
Date: Sat, 2 Sep 2017 02:00:40 -0700
Subject: [PATCH 2/3] glob: don't assume getpwnam_r

* lib/glob.c (glob): Port recent patches to platforms
lacking getpwnam_r.
---
 ChangeLog  | 4 ++++
 lib/glob.c | 4 ++--
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 1159480..4314e91 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,9 @@
 2017-09-02  Paul Eggert  <egg...@cs.ucla.edu>
 
+	glob: don't assume getpwnam_r
+	* lib/glob.c (glob): Port recent patches to platforms
+	lacking getpwnam_r.
+
 	scratch_buffer: don’t use private glibc API
 	Suggested by Florian Weimer in:
 	http://lists.gnu.org/archive/html/bug-gnulib/2017-09/msg00004.html
diff --git a/lib/glob.c b/lib/glob.c
index 596ae6c..e9cf775 100644
--- a/lib/glob.c
+++ b/lib/glob.c
@@ -637,11 +637,11 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
               if (success)
                 {
                   struct passwd *p;
-# if defined HAVE_GETPWNAM_R || defined _LIBC
-                  struct passwd pwbuf;
                   int save = errno;
                   struct scratch_buffer pwtmpbuf;
                   scratch_buffer_init (&pwtmpbuf);
+# if defined HAVE_GETPWNAM_R || defined _LIBC
+                  struct passwd pwbuf;
 
                   while (getpwnam_r (name, &pwbuf,
                                      pwtmpbuf.data, pwtmpbuf.length, &p)
-- 
2.7.4

From 8ac17a6ad40103e78e2905878c8d3d64b2f82894 Mon Sep 17 00:00:00 2001
From: Paul Eggert <egg...@cs.ucla.edu>
Date: Sat, 2 Sep 2017 02:05:09 -0700
Subject: [PATCH 3/3] glob: don't save and restore errno unnecessarily

* lib/glob.c (glob): Don't save and restore errno
merely because we have getpwnam_r.
---
 ChangeLog  | 4 ++++
 lib/glob.c | 4 ----
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 4314e91..867662d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,9 @@
 2017-09-02  Paul Eggert  <egg...@cs.ucla.edu>
 
+	glob: don't save and restore errno unnecessarily
+	* lib/glob.c (glob): Don't save and restore errno
+	merely because we have getpwnam_r.
+
 	glob: don't assume getpwnam_r
 	* lib/glob.c (glob): Port recent patches to platforms
 	lacking getpwnam_r.
diff --git a/lib/glob.c b/lib/glob.c
index e9cf775..8de2d5f 100644
--- a/lib/glob.c
+++ b/lib/glob.c
@@ -637,7 +637,6 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
               if (success)
                 {
                   struct passwd *p;
-                  int save = errno;
                   struct scratch_buffer pwtmpbuf;
                   scratch_buffer_init (&pwtmpbuf);
 # if defined HAVE_GETPWNAM_R || defined _LIBC
@@ -657,7 +656,6 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
                           retval = GLOB_NOSPACE;
                           goto out;
                         }
-                      __set_errno (save);
                     }
 # else
                   p = getpwnam (pwtmpbuf.data);
@@ -815,7 +813,6 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
 
 #  if defined HAVE_GETPWNAM_R || defined _LIBC
             struct passwd pwbuf;
-            int save = errno;
 
             while (getpwnam_r (user_name, &pwbuf,
                                pwtmpbuf.data, pwtmpbuf.length, &p) != 0)
@@ -830,7 +827,6 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
                     retval = GLOB_NOSPACE;
                     goto out;
                   }
-                __set_errno (save);
               }
 #  else
             p = getpwnam (user_name);
-- 
2.7.4

Reply via email to