[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#917620: stretch-pu: package glibc/2.24-11+deb9u4



Package: release.debian.org
Severity: normal
Tags: d-i stretch
User: release.debian.org@packages.debian.org
Usertags: pu

Dear stable release managers,

I would like to upload a new glibc package for the next stretch point
release. It mostly consists in pulling the release/2.24/master upstream
branch, which bring fixes security and important bugs. You will find the
diff against the version currently in stretch attached.

The diff might looks big, however a big part of it adds new tests to
the testsuite along the fixes. They do not end-up the in generated
packages. All the changes are in buster for quite some time, with the
exception of local-condvar-do-not-use-requeue-for-pshared-condvars.patch
to fix bug #904158. It has been fixed upstream with a large rewrite and
thus can't be exported easily. The patch is small and straightforward
though.

Thanks for considering, and don't hesitate to ask for more details if
needed.

Thanks,
Aurelien

-- System Information:
Debian Release: buster/sid
  APT prefers testing
  APT policy: (990, 'testing'), (500, 'unstable'), (1, 'experimental')
Architecture: amd64 (x86_64)
Foreign Architectures: i386

Kernel: Linux 4.18.0-2-amd64 (SMP w/4 CPU cores)
Locale: LANG=fr_FR.UTF-8, LC_CTYPE=fr_FR.UTF-8 (charmap=UTF-8), LANGUAGE= (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash
Init: systemd (via /run/systemd/system)
LSM: AppArmor: enabled
diff --git a/debian/changelog b/debian/changelog
index 2d249d44..71b70e53 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,37 @@
+glibc (2.24-11+deb9u4) UNRELEASED; urgency=medium
+
+  [ Aurelien Jarno ]
+  * debian/patches/git-updates.diff: update from upstream stable branch:
+    - Fix buffer overflow in glob with GLOB_TILDE (CVE-2017-15670).  Closes:
+      #879501.
+    - Fix memory leak in glob with GLOB_TILDE (CVE-2017-15671).  Closes:
+      #879500.
+    - Fix a buffer overflow in glob with GLOB_TILDE in unescaping
+      (CVE-2017-15804).  Closes: #879955.
+    - Fix a memory leak in ld.so (CVE-2017-1000408).  Closes: #884132.
+    - Fix a buffer overflow in ld.so (CVE-2017-1000409).  Closes: #884133.
+    - Fixes incorrect RPATH/RUNPATH handling for SUID binaries
+      (CVE-2017-16997).  Closes: #884615.
+    - Fix a data corruption in SSE2-optimized memmove implementation for
+      i386 (CVE-2017-18269).
+    - Fix a stack-based buffer overflow in the realpath function
+      (CVE-2018-11236).  Closes: #899071.
+    - Fix a buffer overflow in the AVX-512-optimized implementation of the
+      mempcpy function (CVE-2018-11237).  Closes: #899070.
+    - Fix stack guard size accounting and reduce stack usage during
+      unwinding to avoid segmentation faults on CPUs with AVX512-F.  Closes:
+      #903554.
+    - Fix a use after free in pthread_create().  Closes: #916925.
+  * debian/debhelper.in/libc.postinst, script.in/nsscheck.sh: check for
+    postgresql in NSS check.  Closes: #710275.
+
+  [ Sebastian Andrzej Siewior ]
+  * patches/any/local-condvar-do-not-use-requeue-for-pshared-condvars.patch:
+    patch to fix pthread_cond_wait() in the pshared case on non-x86.  Closes:
+    #904158.
+
+ -- Aurelien Jarno <aurel32@debian.org>  Wed, 15 Aug 2018 11:01:50 +0200
+
 glibc (2.24-11+deb9u3) stretch; urgency=medium
 
   [ Aurelien Jarno ]
diff --git a/debian/debhelper.in/libc.postinst b/debian/debhelper.in/libc.postinst
index 7378872b..61ed74ec 100644
--- a/debian/debhelper.in/libc.postinst
+++ b/debian/debhelper.in/libc.postinst
@@ -78,8 +78,8 @@ then
 	    check="$check boa cucipop courier-authdaemon cron cups exim"
 	    check="$check exim4-base dovecot-common cucipop incron lprng lpr"
 	    check="$check lpr-ppd mysql-server nis openbsd-inetd"
-	    check="$check openldapd proftpd postfix postfix-tls rsync samba"
-	    check="$check sasl2-bin slapd smail sendmail snmpd ssh"
+	    check="$check openldapd postgresql-common proftpd postfix postfix-tls"
+	    check="$check rsync samba sasl2-bin slapd smail sendmail snmpd ssh"
 	    check="$check spamassassin vsftpd wu-ftpd wu-ftpd-academ wwwoffle"
 	    check="$check webmin dropbear gdm"
 	    # NSS services check: 
diff --git a/debian/patches/any/local-condvar-do-not-use-requeue-for-pshared-condvars.patch b/debian/patches/any/local-condvar-do-not-use-requeue-for-pshared-condvars.patch
new file mode 100644
index 00000000..f9814c28
--- /dev/null
+++ b/debian/patches/any/local-condvar-do-not-use-requeue-for-pshared-condvars.patch
@@ -0,0 +1,76 @@
+From: John Ogness <john.ogness@linutronix.de>
+Date: Wed, 16 May 2018 22:34:41 +0200
+Subject: [PATCH] condvar: do not use requeue for pshared condvars
+
+With commit e42a990eccb (Update.) condvars were changed to not
+store the mutex address when pshared. Instead, ~0l is stored.
+This value is checked for in USE_REQUEUE_PI() to determine if
+requeue should be used.
+
+pthread_cond_signal() and pthread_cond_broadcast() both use
+USE_REQUEUE_PI() with the mutex address stored on the condvar.
+
+However, pthread_cond_wait() and pthread_cond_timedwait() use
+USE_REQUEUE_PI() on the mutex address passed in from the caller
+(even though that address is *not* stored on the condvar in the
+pshared case). The result is that in the pshared case, the
+wait functions are using requeue and the wake functions are
+not! This is not allowed by the kernel (the waking futex call
+returns EINVAL).
+
+Modify the wait functions to use USE_REQUEUE_PI() on the mutex
+address stored on the condvar, thus mirroring the behavior of
+the wake functions.
+
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Acked-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Reviewed-by: Kurt Kanzenbach <kurt@linutronix.de>
+Signed-off-by: Kurt Kanzenbach <kurt@linutronix.de>
+---
+ nptl/pthread_cond_timedwait.c | 4 +++-
+ nptl/pthread_cond_wait.c      | 4 +++-
+ 2 files changed, 6 insertions(+), 2 deletions(-)
+
+--- a/nptl/pthread_cond_timedwait.c
++++ b/nptl/pthread_cond_timedwait.c
+@@ -163,6 +163,8 @@ __pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex,
+    to check just the former.  */
+ #if (defined lll_futex_timed_wait_requeue_pi \
+      && defined __ASSUME_REQUEUE_PI)
++      pthread_mutex_t *mut = cond->__data.__mutex;
++
+       /* If pi_flag remained 1 then it means that we had the lock and the mutex
+ 	 but a spurious waker raced ahead of us.  Give back the mutex before
+ 	 going into wait again.  */
+@@ -171,7 +173,7 @@ __pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex,
+ 	  __pthread_mutex_cond_lock_adjust (mutex);
+ 	  __pthread_mutex_unlock_usercnt (mutex, 0);
+ 	}
+-      pi_flag = USE_REQUEUE_PI (mutex);
++      pi_flag = USE_REQUEUE_PI (mut);
+ 
+       if (pi_flag)
+ 	{
+--- a/nptl/pthread_cond_wait.c
++++ b/nptl/pthread_cond_wait.c
+@@ -162,6 +162,8 @@ __pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex)
+ 
+ #if (defined lll_futex_wait_requeue_pi \
+      && defined __ASSUME_REQUEUE_PI)
++      pthread_mutex_t *mut = cond->__data.__mutex;
++
+       /* If pi_flag remained 1 then it means that we had the lock and the mutex
+ 	 but a spurious waker raced ahead of us.  Give back the mutex before
+ 	 going into wait again.  */
+@@ -170,7 +172,7 @@ __pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex)
+ 	  __pthread_mutex_cond_lock_adjust (mutex);
+ 	  __pthread_mutex_unlock_usercnt (mutex, 0);
+ 	}
+-      pi_flag = USE_REQUEUE_PI (mutex);
++      pi_flag = USE_REQUEUE_PI (mut);
+ 
+       if (pi_flag)
+ 	{
+-- 
+2.15.1
+
diff --git a/debian/patches/git-updates.diff b/debian/patches/git-updates.diff
index ee3057f8..c4d622e3 100644
--- a/debian/patches/git-updates.diff
+++ b/debian/patches/git-updates.diff
@@ -1,10 +1,242 @@
 GIT update of git://sourceware.org/git/glibc.git/release/2.24/master from glibc-2.24
 
 diff --git a/ChangeLog b/ChangeLog
-index c44c926094..9be47cd9ec 100644
+index c44c926094..cbf1876cae 100644
 --- a/ChangeLog
 +++ b/ChangeLog
-@@ -1,3 +1,747 @@
+@@ -1,3 +1,979 @@
++2016-01-28  Carlos O'Donell  <carlos@redhat.com>
++	    Alexey Makhalov <amakhalov@vmware.com>
++	    Florian Weimer <fweimer@redhat.com>
++
++	[BZ #20116]
++	* nptl/pthread_create.c: Document concurrency notes.
++	Enhance thread creation notes.
++	(create_thread): Use bool *stopped_start.
++	(START_THREAD_DEFN): Comment ownership of PD.
++	(__pthread_create_2_1): Add local bool stopped_start and use
++	that instead of pd->stopped_start where appropriate.
++	* nptl/createthread.c (create_thread): Use bool *stopped_start.
++	* sysdeps/nacl/createthread.c (create_thread): Use bool *stopped_start.
++	* sysdeps/unix/sysv/linux/createthread.c (create_thread): Likewise.
++	* nptl/tst-create-detached.c: New file.
++	* nptl/Makefile (tests): Add tst-create-detached.
++	* nptl/pthread_getschedparam.c (__pthread_getschedparam):
++	Reference the enhanced thread creation notes.
++	* nptl/pthread_setschedparam.c (__pthread_setschedparam): Likewise.
++	* nptl/pthread_setschedprio.c (pthread_setschedprio): Likewise.
++	* nptl/tpp.c (__pthread_tpp_change_priority): Likewise.
++	(__pthread_current_priority): Likewise.
++	* support/Makefile (libsupport-routines): Add xpthread_attr_destroy
++	xpthread_attr_init, xpthread_attr_setdetachstate, and
++	xpthread_attr_setstacksize.
++	* support/xpthread_attr_destroy.c: New file.
++	* support/xpthread_attr_init.c: New file.
++	* support/xpthread_attr_setdetachstate.c: New file.
++	* support/xpthread_attr_setstacksize.c: New file.
++	* support/xthread.h: Define prototypes for xpthread_attr_destroy
++	xpthread_attr_init, xpthread_attr_setdetachstate, and
++	xpthread_attr_setstacksize.
++
++2018-01-11  Florian Weimer  <fweimer@redhat.com>
++
++	* sysdeps/gnu/unwind-resume.c (__libgcc_s_init): Update comment
++	and error message.
++
++2018-01-16  Florian Weimer  <fweimer@redhat.com>
++
++	* nptl/Makefile (CFLAGS-tst-minstack-throw.o): Compile in C++11
++	mode with GNU extensions.
++
++2018-01-11  Florian Weimer  <fweimer@redhat.com>
++
++	[BZ #22636]
++	* nptl/Makefile (tests): Add tst-minstack-cancel, tst-minstack-exit.
++	* nptl/tst-minstack-cancel.c, nptl/tst-minstack-exit.c: New files.
++
++2018-01-10  Florian Weimer  <fweimer@redhat.com>
++
++	[BZ #22636]
++	* sysdeps/nptl/unwind-forcedunwind.c (pthread_cancel_init): Open
++	libgcc.so with RTLD_NOW, to avoid lazy binding during unwind.
++
++2018-01-08  Szabolcs Nagy  <szabolcs.nagy@arm.com>
++
++	[BZ #22637]
++	* nptl/descr.h (stackblock, stackblock_size): Update comments.
++	* nptl/allocatestack.c (allocate_stack): Add guardsize to stacksize.
++	* nptl/nptl-init.c (__pthread_get_minstack): Remove guardsize from
++	stacksize.
++	* nptl/pthread_getattr_np.c (pthread_getattr_np): Likewise.
++
++2018-05-23  Andreas Schwab  <schwab@suse.de>
++
++	[BZ #23196]
++	CVE-2018-11237
++	* sysdeps/x86_64/multiarch/memmove-avx512-no-vzeroupper.S
++	(L(preloop_large)): Save initial destination pointer in %r11 and
++	use it instead of %rax after the loop.
++	* string/test-mempcpy.c (MIN_PAGE_SIZE): Define.
++
++2018-05-09  Paul Pluzhnikov  <ppluzhnikov@google.com>
++
++	[BZ #22786]
++	CVE-2018-11236
++	* stdlib/canonicalize.c (__realpath): Fix overflow in path length
++	computation.
++	* stdlib/Makefile (test-bz22786): New test.
++	* stdlib/test-bz22786.c: New test.
++
++2018-03-23  Andrew Senkevich  <andrew.senkevich@intel.com>
++	    Max Horn  <max@quendi.de>
++
++	[BZ #22644]
++	CVE-2017-18269
++	* sysdeps/i386/i686/multiarch/memcpy-sse2-unaligned.S: Fixed
++	branch conditions.
++	* string/test-memmove.c (do_test2): New testcase.
++
++2018-09-06  Stefan Liebler  <stli@linux.ibm.com>
++
++	* sysdeps/unix/sysv/linux/spawni.c (maybe_script_execute):
++	Increment size of new_argv by one.
++
++2018-01-19  H.J. Lu  <hongjiu.lu@intel.com>
++
++	[BZ #22715]
++	* sysdeps/x86_64/dl-trampoline.h (_dl_runtime_profile): Properly
++	align La_x86_64_retval to VEC_SIZE.
++
++2017-12-30  Aurelien Jarno  <aurelien@aurel32.net>
++	    Dmitry V. Levin  <ldv@altlinux.org>
++
++	[BZ #22625]
++	* elf/dl-load.c (fillin_rpath): Check for empty tokens before dynamic
++	string token expansion. Check for NULL pointer or empty string possibly
++	returned by expand_dynamic_string_token.
++	(decompose_rpath): Check for empty path after dynamic string
++	token expansion.
++
++2017-12-18  Dmitry V. Levin  <ldv@altlinux.org>
++
++	[BZ #22627]
++	* elf/dl-load.c (_dl_init_paths): Remove _dl_dst_substitute preparatory
++	code and invocation.
++
++2017-12-14  Florian Weimer  <fweimer@redhat.com>
++
++	[BZ #22607]
++	CVE-2017-1000409
++	* elf/dl-load.c (_dl_init_paths): Compute number of components in
++	the expanded path string.
++
++2017-12-14  Florian Weimer  <fweimer@redhat.com>
++
++	[BZ #22606]
++	CVE-2017-1000408
++	* elf/dl-load.c (system_dirs): Update comment.
++	(nsystem_dirs_len): Use array_length.
++	(_dl_init_paths): Use nsystem_dirs_len to compute the array size.
++
++2017-11-02  Florian Weimer  <fweimer@redhat.com>
++
++	Add array_length and array_end macros.
++	* include/array_length.h: New file.
++
++2017-11-02  Florian Weimer  <fweimer@redhat.com>
++
++	[BZ #22332]
++	* posix/tst-glob-tilde.c (do_noescape): New variable.
++	(one_test): Process it.
++	(do_test): Set do_noescape.  Add unescaping test case.
++
++2017-10-22  Paul Eggert <eggert@cs.ucla.edu>
++
++	[BZ #22332]
++	* posix/glob.c (__glob): Fix buffer overflow during GLOB_TILDE
++	unescaping.
++
++2017-10-21  Florian Weimer  <fweimer@redhat.com>
++
++	* posix/Makefile (tests): Add tst-glob-tilde.
++	(tests-special): Add tst-glob-tilde-mem.out
++	(tst-glob-tilde-ENV): Set MALLOC_TRACE.
++	(tst-glob-tilde-mem.out): Add mtrace check.
++	* posix/tst-glob-tilde.c: New file.
++
++2017-10-20  Paul Eggert <eggert@cs.ucla.edu>
++
++	[BZ #22320]
++	CVE-2017-15670
++	* posix/glob.c (__glob): Fix one-byte overflow.
++
++2017-09-08  Adhemerval Zanella  <adhemerval.zanella@linaro.org>
++
++	[BZ #1062]
++	CVE-2017-15671
++	* posix/Makefile (routines): Add globfree, globfree64, and
++	glob_pattern_p.
++	* posix/flexmember.h: New file.
++	* posix/glob_internal.h: Likewise.
++	* posix/glob_pattern_p.c: Likewise.
++	* posix/globfree.c: Likewise.
++	* posix/globfree64.c: Likewise.
++	* sysdeps/gnu/globfree64.c: Likewise.
++	* sysdeps/unix/sysv/linux/alpha/globfree.c: Likewise.
++	* sysdeps/unix/sysv/linux/mips/mips64/n64/globfree64.c: Likewise.
++	* sysdeps/unix/sysv/linux/oldglob.c: Likewise.
++	* sysdeps/unix/sysv/linux/wordsize-64/globfree64.c: Likewise.
++	* sysdeps/unix/sysv/linux/x86_64/x32/globfree.c: Likewise.
++	* sysdeps/wordsize-64/globfree.c: Likewise.
++	* sysdeps/wordsize-64/globfree64.c: Likewise.
++	* posix/glob.c (HAVE_CONFIG_H): Use !_LIBC instead.
++	[NDEBUG): Remove comments.
++	(GLOB_ONLY_P, _AMIGA, VMS): Remove define.
++	(dirent_type): New type.  Use uint_fast8_t not
++	uint8_t, as C99 does not require uint8_t.
++	(DT_UNKNOWN, DT_DIR, DT_LNK): New macros.
++	(struct readdir_result): Use dirent_type.  Do not define skip_entry
++	unless it is needed; this saves a byte on platforms lacking d_ino.
++	(readdir_result_type, readdir_result_skip_entry):
++	New functions, replacing ...
++	(readdir_result_might_be_symlink, readdir_result_might_be_dir):
++	 these functions, which were removed.  This makes the callers
++	easier to read.  All callers changed.
++	(D_INO_TO_RESULT): Now empty if there is no d_ino.
++	(size_add_wrapv, glob_use_alloca): New static functions.
++	(glob, glob_in_dir): Check for size_t overflow in several places,
++	and fix some size_t checks that were not quite right.
++	Remove old code using SHELL since Bash no longer
++	uses this.
++	(glob, prefix_array): Separate MS code better.
++	(glob_in_dir): Remove old Amiga and VMS code.
++	(globfree, __glob_pattern_type, __glob_pattern_p): Move to
++	separate files.
++	(glob_in_dir): Do not rely on undefined behavior in accessing
++	struct members beyond their bounds.  Use a flexible array member
++	instead
++	(link_stat): Rename from link_exists2_p and return -1/0 instead of
++	0/1.  Caller changed.
++	(glob): Fix memory leaks.
++	* posix/glob64 (globfree64): Move to separate file.
++	* sysdeps/gnu/glob64.c (NO_GLOB_PATTERN_P): Remove define.
++	(globfree64): Remove hidden alias.
++	* sysdeps/unix/sysv/linux/Makefile (sysdeps_routines): Add
++	oldglob.
++	* sysdeps/unix/sysv/linux/alpha/glob.c (__new_globfree): Move to
++	separate file.
++	* sysdeps/unix/sysv/linux/i386/glob64.c (NO_GLOB_PATTERN_P): Remove
++	define.
++	Move compat code to separate file.
++	* sysdeps/wordsize-64/glob.c (globfree): Move definitions to
++	separate file.
++
++2017-08-20  H.J. Lu  <hongjiu.lu@intel.com>
++
++	[BZ #18822]
++	* sysdeps/unix/sysv/linux/i386/glob64.c (__old_glob64): Add
++	libc_hidden_proto and libc_hidden_def.
++
 +2017-10-22  H.J. Lu  <hongjiu.lu@intel.com>
 +
 +	[BZ #21265]
@@ -807,10 +1039,10 @@ index 03fd89c13e..ee379f5852 100644
  
  ifndef avoid-generated
 diff --git a/NEWS b/NEWS
-index b0447e7169..9a9e487ee6 100644
+index b0447e7169..d5868b2e09 100644
 --- a/NEWS
 +++ b/NEWS
-@@ -5,6 +5,34 @@ See the end for copying conditions.
+@@ -5,6 +5,83 @@ See the end for copying conditions.
  Please send GNU C library bug reports via <http://sourceware.org/bugzilla/>
  using `glibc' in the "product" field.
  
@@ -830,8 +1062,48 @@ index b0447e7169..9a9e487ee6 100644
 +  question type which is outside the range of valid question type values.
 +  (CVE-2015-5180)
 +
++* CVE-2017-15670: The glob function, when invoked with GLOB_TILDE, suffered
++  from a one-byte overflow during ~ operator processing (either on the stack
++  or the heap, depending on the length of the user name).
++
++* CVE-2017-15671: The glob function, when invoked with GLOB_TILDE,
++  would sometimes fail to free memory allocated during ~ operator
++  processing, leading to a memory leak and, potentially, to a denial
++  of service.
++
++* CVE-2017-15804: The glob function, when invoked with GLOB_TILDE and
++  without GLOB_NOESCAPE, could write past the end of a buffer while
++  unescaping user names.  Reported by Tim Rühsen.
++
++* CVE-2017-1000408: Incorrect array size computation in _dl_init_paths leads
++  to the allocation of too much memory.  (This is not a security bug per se,
++  it is mentioned here only because of the CVE assignment.)  Reported by
++  Qualys.
++
++* CVE-2017-1000409: Buffer overflow in _dl_init_paths due to miscomputation
++  of the number of search path components.  (This is not a security
++  vulnerability per se because no trust boundary is crossed if the fix for
++  CVE-2017-1000366 has been applied, but it is mentioned here only because
++  of the CVE assignment.)  Reported by Qualys.
++
++  CVE-2017-16997: Incorrect handling of RPATH or RUNPATH containing $ORIGIN
++  for AT_SECURE or SUID binaries could be used to load libraries from the
++  current directory.
++
++  CVE-2017-18269: An SSE2-based memmove implementation for the i386
++  architecture could corrupt memory.  Reported by Max Horn.
++
++  CVE-2018-11236: Very long pathname arguments to realpath function could
++  result in an integer overflow and buffer overflow.  Reported by Alexey
++  Izbyshev.
++
++  CVE-2018-11237: The mempcpy implementation for the Intel Xeon Phi
++  architecture could write beyond the target buffer, resulting in a buffer
++  overflow.  Reported by Andreas Schwab.
++
 +The following bugs are resolved with this release:
 +
++  [20116] nptl: use after free in pthread_create
 +  [20790] Fix rpcgen buffer overrun
 +  [20978] Fix strlen on null pointer in nss_nisplus
 +  [21209] Ignore and remove LD_HWCAP_MASK for AT_SECURE programs
@@ -841,6 +1113,15 @@ index b0447e7169..9a9e487ee6 100644
 +  [21609] x86-64: Align the stack in __tls_get_addr
 +  [21624] Unsafe alloca allows local attackers to alias stack and heap (CVE-2017-1000366)
 +  [21654] nss: Fix invalid cast in group merging
++  [22636] PTHREAD_STACK_MIN is too small on x86-64
++  [22637] nptl: Fix stack guard size accounting
++  [22644] string: memmove-sse2-unaligned on 32bit x86 produces garbage when
++    crossing 2GB threshold (CVE-2017-18269)
++  [22715] x86-64: Properly align La_x86_64_retval to VEC_SIZE
++  [22786] libc: Stack buffer overflow in realpath() if input size is close
++    to SSIZE_MAX (CVE-2018-11236)
++  [23196] string: __mempcpy_avx512_no_vzeroupper mishandles large copies
++    (CVE-2018-11237)
 +
  Version 2.24
  
@@ -1143,6 +1424,167 @@ index 687d7de874..9f93ab7628 100644
  
    _dl_close_worker (map, false);
  
+diff --git a/elf/dl-load.c b/elf/dl-load.c
+index c0d6249373..1f774e139f 100644
+--- a/elf/dl-load.c
++++ b/elf/dl-load.c
+@@ -37,6 +37,7 @@
+ #include <sysdep.h>
+ #include <stap-probe.h>
+ #include <libc-internal.h>
++#include <array_length.h>
+ 
+ #include <dl-dst.h>
+ #include <dl-load.h>
+@@ -103,7 +104,9 @@ static size_t ncapstr attribute_relro;
+ static size_t max_capstrlen attribute_relro;
+ 
+ 
+-/* Get the generated information about the trusted directories.  */
++/* Get the generated information about the trusted directories.  Use
++   an array of concatenated strings to avoid relocations.  See
++   gen-trusted-dirs.awk.  */
+ #include "trusted-dirs.h"
+ 
+ static const char system_dirs[] = SYSTEM_DIRS;
+@@ -111,9 +114,7 @@ static const size_t system_dirs_len[] =
+ {
+   SYSTEM_DIRS_LEN
+ };
+-#define nsystem_dirs_len \
+-  (sizeof (system_dirs_len) / sizeof (system_dirs_len[0]))
+-
++#define nsystem_dirs_len array_length (system_dirs_len)
+ 
+ static bool
+ is_trusted_path (const char *path, size_t len)
+@@ -433,31 +434,40 @@ fillin_rpath (char *rpath, struct r_search_path_elem **result, const char *sep,
+ {
+   char *cp;
+   size_t nelems = 0;
+-  char *to_free;
+ 
+   while ((cp = __strsep (&rpath, sep)) != NULL)
+     {
+       struct r_search_path_elem *dirp;
++      char *to_free = NULL;
++      size_t len = 0;
+ 
+-      to_free = cp = expand_dynamic_string_token (l, cp, 1);
++      /* `strsep' can pass an empty string.  */
++      if (*cp != '\0')
++	{
++	  to_free = cp = expand_dynamic_string_token (l, cp, 1);
+ 
+-      size_t len = strlen (cp);
++	  /* expand_dynamic_string_token can return NULL in case of empty
++	     path or memory allocation failure.  */
++	  if (cp == NULL)
++	    continue;
+ 
+-      /* `strsep' can pass an empty string.  This has to be
+-	 interpreted as `use the current directory'. */
+-      if (len == 0)
+-	{
+-	  static const char curwd[] = "./";
+-	  cp = (char *) curwd;
+-	}
++	  /* Compute the length after dynamic string token expansion and
++	     ignore empty paths.  */
++	  len = strlen (cp);
++	  if (len == 0)
++	    {
++	      free (to_free);
++	      continue;
++	    }
+ 
+-      /* Remove trailing slashes (except for "/").  */
+-      while (len > 1 && cp[len - 1] == '/')
+-	--len;
++	  /* Remove trailing slashes (except for "/").  */
++	  while (len > 1 && cp[len - 1] == '/')
++	    --len;
+ 
+-      /* Now add one if there is none so far.  */
+-      if (len > 0 && cp[len - 1] != '/')
+-	cp[len++] = '/';
++	  /* Now add one if there is none so far.  */
++	  if (len > 0 && cp[len - 1] != '/')
++	    cp[len++] = '/';
++	}
+ 
+       /* Make sure we don't use untrusted directories if we run SUID.  */
+       if (__glibc_unlikely (check_trusted) && !is_trusted_path (cp, len))
+@@ -621,6 +631,14 @@ decompose_rpath (struct r_search_path_struct *sps,
+      necessary.  */
+   free (copy);
+ 
++  /* There is no path after expansion.  */
++  if (result[0] == NULL)
++    {
++      free (result);
++      sps->dirs = (struct r_search_path_elem **) -1;
++      return false;
++    }
++
+   sps->dirs = result;
+   /* The caller will change this value if we haven't used a real malloc.  */
+   sps->malloced = 1;
+@@ -688,9 +706,8 @@ _dl_init_paths (const char *llp)
+ 		 + ncapstr * sizeof (enum r_dir_status))
+ 		/ sizeof (struct r_search_path_elem));
+ 
+-  rtld_search_dirs.dirs[0] = (struct r_search_path_elem *)
+-    malloc ((sizeof (system_dirs) / sizeof (system_dirs[0]))
+-	    * round_size * sizeof (struct r_search_path_elem));
++  rtld_search_dirs.dirs[0] = malloc (nsystem_dirs_len * round_size
++				     * sizeof (*rtld_search_dirs.dirs[0]));
+   if (rtld_search_dirs.dirs[0] == NULL)
+     {
+       errstring = N_("cannot create cache for search path");
+@@ -776,37 +793,14 @@ _dl_init_paths (const char *llp)
+ 
+   if (llp != NULL && *llp != '\0')
+     {
+-      size_t nllp;
+-      const char *cp = llp;
+-      char *llp_tmp;
+-
+-#ifdef SHARED
+-      /* Expand DSTs.  */
+-      size_t cnt = DL_DST_COUNT (llp, 1);
+-      if (__glibc_likely (cnt == 0))
+-	llp_tmp = strdupa (llp);
+-      else
+-	{
+-	  /* Determine the length of the substituted string.  */
+-	  size_t total = DL_DST_REQUIRED (l, llp, strlen (llp), cnt);
+-
+-	  /* Allocate the necessary memory.  */
+-	  llp_tmp = (char *) alloca (total + 1);
+-	  llp_tmp = _dl_dst_substitute (l, llp, llp_tmp, 1);
+-	}
+-#else
+-      llp_tmp = strdupa (llp);
+-#endif
++      char *llp_tmp = strdupa (llp);
+ 
+       /* Decompose the LD_LIBRARY_PATH contents.  First determine how many
+ 	 elements it has.  */
+-      nllp = 1;
+-      while (*cp)
+-	{
+-	  if (*cp == ':' || *cp == ';')
+-	    ++nllp;
+-	  ++cp;
+-	}
++      size_t nllp = 1;
++      for (const char *cp = llp_tmp; *cp != '\0'; ++cp)
++	if (*cp == ':' || *cp == ';')
++	  ++nllp;
+ 
+       env_path_list.dirs = (struct r_search_path_elem **)
+ 	malloc ((nllp + 1) * sizeof (struct r_search_path_elem *));
 diff --git a/elf/rtld.c b/elf/rtld.c
 index 647661ca45..8f56d6edd3 100644
 --- a/elf/rtld.c
@@ -1729,6 +2171,48 @@ index 2e735ede4c..7c0deed9ae 100644
 +#define T_QUERY_A_AND_AAAA 439963904
  
  #endif
+diff --git a/include/array_length.h b/include/array_length.h
+new file mode 100644
+index 0000000000..cb4a8b2a56
+--- /dev/null
++++ b/include/array_length.h
+@@ -0,0 +1,36 @@
++/* The array_length and array_end macros.
++   Copyright (C) 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 _ARRAY_LENGTH_H
++#define _ARRAY_LENGTH_H
++
++/* array_length (VAR) is the number of elements in the array VAR.  VAR
++   must evaluate to an array, not a pointer.  */
++#define array_length(var)                                               \
++  __extension__ ({                                                      \
++    _Static_assert (!__builtin_types_compatible_p                       \
++                    (__typeof (var), __typeof (&(var)[0])),             \
++                    "argument must be an array");                       \
++    sizeof (var) / sizeof ((var)[0]);                                   \
++  })
++
++/* array_end (VAR) is a pointer one past the end of the array VAR.
++   VAR must evaluate to an array, not a pointer.  */
++#define array_end(var) (&(var)[array_length (var)])
++
++#endif /* _ARRAY_LENGTH_H */
 diff --git a/io/fts.h b/io/fts.h
 index 127a0d2721..b6b45206c8 100644
 --- a/io/fts.h
@@ -1997,7 +2481,7 @@ index 7f698b4e6d..cb5acce01d 100644
        *errnop = EINVAL;
        return NSS_STATUS_UNAVAIL;
 diff --git a/nptl/Makefile b/nptl/Makefile
-index 0d8aadebed..fa925819ca 100644
+index 0d8aadebed..6928477501 100644
 --- a/nptl/Makefile
 +++ b/nptl/Makefile
 @@ -268,7 +268,7 @@ tests = tst-typesizes \
@@ -2009,8 +2493,20 @@ index 0d8aadebed..fa925819ca 100644
  	tst-exit1 tst-exit2 tst-exit3 \
  	tst-stdio1 tst-stdio2 \
  	tst-stack1 tst-stack2 tst-stack3 tst-stack4 tst-pthread-getattr \
+@@ -290,7 +290,10 @@ tests = tst-typesizes \
+ 	tst-initializers1 $(addprefix tst-initializers1-,\
+ 			    c89 gnu89 c99 gnu99 c11 gnu11) \
+ 	tst-bad-schedattr \
+-	tst-thread_local1 tst-mutex-errorcheck tst-robust10
++	tst-thread_local1 tst-mutex-errorcheck tst-robust10 \
++	tst-minstack-cancel tst-minstack-exit \
++	tst-create-detached
++
+ xtests = tst-setuid1 tst-setuid1-static tst-setuid2 \
+ 	tst-mutexpp1 tst-mutexpp6 tst-mutexpp10
+ test-srcs = tst-oddstacklimit
 diff --git a/nptl/allocatestack.c b/nptl/allocatestack.c
-index 6b42b11d5a..7365ca606b 100644
+index 6b42b11d5a..9aba97fe7c 100644
 --- a/nptl/allocatestack.c
 +++ b/nptl/allocatestack.c
 @@ -440,9 +440,6 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
@@ -2023,7 +2519,18 @@ index 6b42b11d5a..7365ca606b 100644
        /* Don't allow setxid until cloned.  */
        pd->setxid_futex = -1;
  
-@@ -579,9 +576,6 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
+@@ -487,6 +484,10 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
+       /* Make sure the size of the stack is enough for the guard and
+ 	 eventually the thread descriptor.  */
+       guardsize = (attr->guardsize + pagesize_m1) & ~pagesize_m1;
++      if (guardsize < attr->guardsize || size + guardsize < guardsize)
++	/* Arithmetic overflow.  */
++	return EINVAL;
++      size += guardsize;
+       if (__builtin_expect (size < ((guardsize + __static_tls_size
+ 				     + MINIMAL_REST_STACK + pagesize_m1)
+ 				    & ~pagesize_m1),
+@@ -579,9 +580,6 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
  	  /* Don't allow setxid until cloned.  */
  	  pd->setxid_futex = -1;
  
@@ -2033,7 +2540,7 @@ index 6b42b11d5a..7365ca606b 100644
  	  /* Allocate the DTV for this thread.  */
  	  if (_dl_allocate_tls (TLS_TPADJ (pd)) == NULL)
  	    {
-@@ -875,9 +869,6 @@ __reclaim_stacks (void)
+@@ -875,9 +873,6 @@ __reclaim_stacks (void)
  	  /* This marks the stack as free.  */
  	  curp->tid = 0;
  
@@ -2043,7 +2550,7 @@ index 6b42b11d5a..7365ca606b 100644
  	  /* Account for the size of the stack.  */
  	  stack_cache_actsize += curp->stackblock_size;
  
-@@ -903,13 +894,6 @@ __reclaim_stacks (void)
+@@ -903,13 +898,6 @@ __reclaim_stacks (void)
  	}
      }
  
@@ -2057,7 +2564,7 @@ index 6b42b11d5a..7365ca606b 100644
    /* Add the stack of all running threads to the cache.  */
    list_splice (&stack_used, &stack_cache);
  
-@@ -1054,9 +1038,9 @@ setxid_signal_thread (struct xid_command *cmdp, struct pthread *t)
+@@ -1054,9 +1042,9 @@ setxid_signal_thread (struct xid_command *cmdp, struct pthread *t)
      return 0;
  
    int val;
@@ -2069,8 +2576,33 @@ index 6b42b11d5a..7365ca606b 100644
  
    /* If this failed, it must have had not started yet or else exited.  */
    if (!INTERNAL_SYSCALL_ERROR_P (val, err))
+diff --git a/nptl/createthread.c b/nptl/createthread.c
+index ba2f9c7167..328f85865d 100644
+--- a/nptl/createthread.c
++++ b/nptl/createthread.c
+@@ -25,16 +25,14 @@
+ 
+ static int
+ create_thread (struct pthread *pd, const struct pthread_attr *attr,
+-	       bool stopped_start, STACK_VARIABLES_PARMS, bool *thread_ran)
++	       bool *stopped_start, STACK_VARIABLES_PARMS, bool *thread_ran)
+ {
+   /* If the implementation needs to do some tweaks to the thread after
+      it has been created at the OS level, it can set STOPPED_START here.  */
+ 
+-  pd->stopped_start = stopped_start;
+-  if (__glibc_unlikely (stopped_start))
+-    /* We make sure the thread does not run far by forcing it to get a
+-       lock.  We lock it here too so that the new thread cannot continue
+-       until we tell it to.  */
++  pd->stopped_start = *stopped_start;
++  if (__glibc_unlikely (*stopped_start))
++    /* See CONCURRENCY NOTES in nptl/pthread_create.c.  */
+     lll_lock (pd->lock, LLL_PRIVATE);
+ 
+   return ENOSYS;
 diff --git a/nptl/descr.h b/nptl/descr.h
-index 8e4938deb5..bc92abf010 100644
+index 8e4938deb5..7e62c3cb23 100644
 --- a/nptl/descr.h
 +++ b/nptl/descr.h
 @@ -167,8 +167,8 @@ struct pthread
@@ -2084,8 +2616,20 @@ index 8e4938deb5..bc92abf010 100644
  
    /* List of robust mutexes the thread is holding.  */
  #ifdef __PTHREAD_MUTEX_HAVE_PREV
+@@ -363,9 +363,9 @@ struct pthread
+   /* Machine-specific unwind info.  */
+   struct _Unwind_Exception exc;
+ 
+-  /* If nonzero pointer to area allocated for the stack and its
+-     size.  */
++  /* If nonzero, pointer to the area allocated for the stack and guard. */
+   void *stackblock;
++  /* Size of the stackblock area including the guard.  */
+   size_t stackblock_size;
+   /* Size of the included guard area.  */
+   size_t guardsize;
 diff --git a/nptl/nptl-init.c b/nptl/nptl-init.c
-index bdbdfedcef..48fab50c4e 100644
+index bdbdfedcef..4dabb64722 100644
 --- a/nptl/nptl-init.c
 +++ b/nptl/nptl-init.c
 @@ -184,18 +184,12 @@ __nptl_set_robust (struct pthread *self)
@@ -2129,6 +2673,16 @@ index bdbdfedcef..48fab50c4e 100644
        || si->si_code != SI_TKILL)
      return;
  
+@@ -504,8 +493,5 @@ strong_alias (__pthread_initialize_minimal_internal,
+ size_t
+ __pthread_get_minstack (const pthread_attr_t *attr)
+ {
+-  struct pthread_attr *iattr = (struct pthread_attr *) attr;
+-
+-  return (GLRO(dl_pagesize) + __static_tls_size + PTHREAD_STACK_MIN
+-	  + iattr->guardsize);
++  return GLRO(dl_pagesize) + __static_tls_size + PTHREAD_STACK_MIN;
+ }
 diff --git a/nptl/pthread_cancel.c b/nptl/pthread_cancel.c
 index 1419baf988..89d02e1741 100644
 --- a/nptl/pthread_cancel.c
@@ -2166,11 +2720,309 @@ index 1419baf988..89d02e1741 100644
  	  if (INTERNAL_SYSCALL_ERROR_P (val, err))
  	    result = INTERNAL_SYSCALL_ERRNO (val, err);
  #else
+diff --git a/nptl/pthread_create.c b/nptl/pthread_create.c
+index a834063ad5..44b17bec86 100644
+--- a/nptl/pthread_create.c
++++ b/nptl/pthread_create.c
+@@ -54,25 +54,141 @@ unsigned int __nptl_nthreads = 1;
+ /* Code to allocate and deallocate a stack.  */
+ #include "allocatestack.c"
+ 
+-/* createthread.c defines this function, and two macros:
++/* CONCURRENCY NOTES:
++
++   Understanding who is the owner of the 'struct pthread' or 'PD'
++   (refers to the value of the 'struct pthread *pd' function argument)
++   is critically important in determining exactly which operations are
++   allowed and which are not and when, particularly when it comes to the
++   implementation of pthread_create, pthread_join, pthread_detach, and
++   other functions which all operate on PD.
++
++   The owner of PD is responsible for freeing the final resources
++   associated with PD, and may examine the memory underlying PD at any
++   point in time until it frees it back to the OS or to reuse by the
++   runtime.
++
++   The thread which calls pthread_create is called the creating thread.
++   The creating thread begins as the owner of PD.
++
++   During startup the new thread may examine PD in coordination with the
++   owner thread (which may be itself).
++
++   The four cases of ownership transfer are:
++
++   (1) Ownership of PD is released to the process (all threads may use it)
++       after the new thread starts in a joinable state
++       i.e. pthread_create returns a usable pthread_t.
++
++   (2) Ownership of PD is released to the new thread starting in a detached
++       state.
++
++   (3) Ownership of PD is dynamically released to a running thread via
++       pthread_detach.
++
++   (4) Ownership of PD is acquired by the thread which calls pthread_join.
++
++   Implementation notes:
++
++   The PD->stopped_start and thread_ran variables are used to determine
++   exactly which of the four ownership states we are in and therefore
++   what actions can be taken.  For example after (2) we cannot read or
++   write from PD anymore since the thread may no longer exist and the
++   memory may be unmapped.  The most complicated cases happen during
++   thread startup:
++
++   (a) If the created thread is in a detached (PTHREAD_CREATE_DETACHED),
++       or joinable (default PTHREAD_CREATE_JOINABLE) state and
++       STOPPED_START is true, then the creating thread has ownership of
++       PD until the PD->lock is released by pthread_create.  If any
++       errors occur we are in states (c), (d), or (e) below.
++
++   (b) If the created thread is in a detached state
++       (PTHREAD_CREATED_DETACHED), and STOPPED_START is false, then the
++       creating thread has ownership of PD until it invokes the OS
++       kernel's thread creation routine.  If this routine returns
++       without error, then the created thread owns PD; otherwise, see
++       (c) and (e) below.
++
++   (c) If the detached thread setup failed and THREAD_RAN is true, then
++       the creating thread releases ownership to the new thread by
++       sending a cancellation signal.  All threads set THREAD_RAN to
++       true as quickly as possible after returning from the OS kernel's
++       thread creation routine.
++
++   (d) If the joinable thread setup failed and THREAD_RAN is true, then
++       then the creating thread retains ownership of PD and must cleanup
++       state.  Ownership cannot be released to the process via the
++       return of pthread_create since a non-zero result entails PD is
++       undefined and therefore cannot be joined to free the resources.
++       We privately call pthread_join on the thread to finish handling
++       the resource shutdown (Or at least we should, see bug 19511).
++
++   (e) If the thread creation failed and THREAD_RAN is false, then the
++       creating thread retains ownership of PD and must cleanup state.
++       No waiting for the new thread is required because it never
++       started.
++
++   The nptl_db interface:
++
++   The interface with nptl_db requires that we enqueue PD into a linked
++   list and then call a function which the debugger will trap.  The PD
++   will then be dequeued and control returned to the thread.  The caller
++   at the time must have ownership of PD and such ownership remains
++   after control returns to thread. The enqueued PD is removed from the
++   linked list by the nptl_db callback td_thr_event_getmsg.  The debugger
++   must ensure that the thread does not resume execution, otherwise
++   ownership of PD may be lost and examining PD will not be possible.
++
++   Note that the GNU Debugger as of (December 10th 2015) commit
++   c2c2a31fdb228d41ce3db62b268efea04bd39c18 no longer uses
++   td_thr_event_getmsg and several other related nptl_db interfaces. The
++   principal reason for this is that nptl_db does not support non-stop
++   mode where other threads can run concurrently and modify runtime
++   structures currently in use by the debugger and the nptl_db
++   interface.
++
++   Axioms:
++
++   * The create_thread function can never set stopped_start to false.
++   * The created thread can read stopped_start but never write to it.
++   * The variable thread_ran is set some time after the OS thread
++     creation routine returns, how much time after the thread is created
++     is unspecified, but it should be as quickly as possible.
++
++*/
++
++/* CREATE THREAD NOTES:
++
++   createthread.c defines the create_thread function, and two macros:
+    START_THREAD_DEFN and START_THREAD_SELF (see below).
+ 
+-   create_thread is obliged to initialize PD->stopped_start.  It
+-   should be true if the STOPPED_START parameter is true, or if
+-   create_thread needs the new thread to synchronize at startup for
+-   some other implementation reason.  If PD->stopped_start will be
+-   true, then create_thread is obliged to perform the operation
+-   "lll_lock (PD->lock, LLL_PRIVATE)" before starting the thread.
++   create_thread must initialize PD->stopped_start.  It should be true
++   if the STOPPED_START parameter is true, or if create_thread needs the
++   new thread to synchronize at startup for some other implementation
++   reason.  If STOPPED_START will be true, then create_thread is obliged
++   to lock PD->lock before starting the thread.  Then pthread_create
++   unlocks PD->lock which synchronizes-with START_THREAD_DEFN in the
++   child thread which does an acquire/release of PD->lock as the last
++   action before calling the user entry point.  The goal of all of this
++   is to ensure that the required initial thread attributes are applied
++   (by the creating thread) before the new thread runs user code.  Note
++   that the the functions pthread_getschedparam, pthread_setschedparam,
++   pthread_setschedprio, __pthread_tpp_change_priority, and
++   __pthread_current_priority reuse the same lock, PD->lock, for a
++   similar purpose e.g. synchronizing the setting of similar thread
++   attributes.  These functions are never called before the thread is
++   created, so don't participate in startup syncronization, but given
++   that the lock is present already and in the unlocked state, reusing
++   it saves space.
+ 
+    The return value is zero for success or an errno code for failure.
+    If the return value is ENOMEM, that will be translated to EAGAIN,
+    so create_thread need not do that.  On failure, *THREAD_RAN should
+    be set to true iff the thread actually started up and then got
+-   cancelled before calling user code (*PD->start_routine), in which
+-   case it is responsible for doing its own cleanup.  */
+-
++   canceled before calling user code (*PD->start_routine).  */
+ static int create_thread (struct pthread *pd, const struct pthread_attr *attr,
+-			  bool stopped_start, STACK_VARIABLES_PARMS,
++			  bool *stopped_start, STACK_VARIABLES_PARMS,
+ 			  bool *thread_ran);
+ 
+ #include <createthread.c>
+@@ -314,12 +430,19 @@ START_THREAD_DEFN
+       /* Store the new cleanup handler info.  */
+       THREAD_SETMEM (pd, cleanup_jmp_buf, &unwind_buf);
+ 
++      /* We are either in (a) or (b), and in either case we either own
++         PD already (2) or are about to own PD (1), and so our only
++	 restriction would be that we can't free PD until we know we
++	 have ownership (see CONCURRENCY NOTES above).  */
+       if (__glibc_unlikely (pd->stopped_start))
+ 	{
+ 	  int oldtype = CANCEL_ASYNC ();
+ 
+ 	  /* Get the lock the parent locked to force synchronization.  */
+ 	  lll_lock (pd->lock, LLL_PRIVATE);
++
++	  /* We have ownership of PD now.  */
++
+ 	  /* And give it up right away.  */
+ 	  lll_unlock (pd->lock, LLL_PRIVATE);
+ 
+@@ -378,7 +501,8 @@ START_THREAD_DEFN
+ 							   pd, pd->nextevent));
+ 	    }
+ 
+-	  /* Now call the function to signal the event.  */
++	  /* Now call the function which signals the event.  See
++	     CONCURRENCY NOTES for the nptl_db interface comments.  */
+ 	  __nptl_death_event ();
+ 	}
+     }
+@@ -642,19 +766,28 @@ __pthread_create_2_1 (pthread_t *newthread, const pthread_attr_t *attr,
+      that cares whether the thread count is correct.  */
+   atomic_increment (&__nptl_nthreads);
+ 
+-  bool thread_ran = false;
++  /* Our local value of stopped_start and thread_ran can be accessed at
++     any time. The PD->stopped_start may only be accessed if we have
++     ownership of PD (see CONCURRENCY NOTES above).  */
++  bool stopped_start = false; bool thread_ran = false;
+ 
+   /* Start the thread.  */
+   if (__glibc_unlikely (report_thread_creation (pd)))
+     {
+-      /* Create the thread.  We always create the thread stopped
+-	 so that it does not get far before we tell the debugger.  */
+-      retval = create_thread (pd, iattr, true, STACK_VARIABLES_ARGS,
+-			      &thread_ran);
++      stopped_start = true;
++
++      /* We always create the thread stopped at startup so we can
++	 notify the debugger.  */
++      retval = create_thread (pd, iattr, &stopped_start,
++			      STACK_VARIABLES_ARGS, &thread_ran);
+       if (retval == 0)
+ 	{
+-	  /* create_thread should have set this so that the logic below can
+-	     test it.  */
++	  /* We retain ownership of PD until (a) (see CONCURRENCY NOTES
++	     above).  */
++
++	  /* Assert stopped_start is true in both our local copy and the
++	     PD copy.  */
++	  assert (stopped_start);
+ 	  assert (pd->stopped_start);
+ 
+ 	  /* Now fill in the information about the new thread in
+@@ -671,26 +804,30 @@ __pthread_create_2_1 (pthread_t *newthread, const pthread_attr_t *attr,
+ 						       pd, pd->nextevent)
+ 		 != 0);
+ 
+-	  /* Now call the function which signals the event.  */
++	  /* Now call the function which signals the event.  See
++	     CONCURRENCY NOTES for the nptl_db interface comments.  */
+ 	  __nptl_create_event ();
+ 	}
+     }
+   else
+-    retval = create_thread (pd, iattr, false, STACK_VARIABLES_ARGS,
+-			    &thread_ran);
++    retval = create_thread (pd, iattr, &stopped_start,
++			    STACK_VARIABLES_ARGS, &thread_ran);
+ 
+   if (__glibc_unlikely (retval != 0))
+     {
+-      /* If thread creation "failed", that might mean that the thread got
+-	 created and ran a little--short of running user code--but then
+-	 create_thread cancelled it.  In that case, the thread will do all
+-	 its own cleanup just like a normal thread exit after a successful
+-	 creation would do.  */
+-
+       if (thread_ran)
+-	assert (pd->stopped_start);
++	/* State (c) or (d) and we may not have PD ownership (see
++	   CONCURRENCY NOTES above).  We can assert that STOPPED_START
++	   must have been true because thread creation didn't fail, but
++	   thread attribute setting did.  */
++	/* See bug 19511 which explains why doing nothing here is a
++	   resource leak for a joinable thread.  */
++	assert (stopped_start);
+       else
+ 	{
++	  /* State (e) and we have ownership of PD (see CONCURRENCY
++	     NOTES above).  */
++
+ 	  /* Oops, we lied for a second.  */
+ 	  atomic_decrement (&__nptl_nthreads);
+ 
+@@ -710,10 +847,14 @@ __pthread_create_2_1 (pthread_t *newthread, const pthread_attr_t *attr,
+     }
+   else
+     {
+-      if (pd->stopped_start)
+-	/* The thread blocked on this lock either because we're doing TD_CREATE
+-	   event reporting, or for some other reason that create_thread chose.
+-	   Now let it run free.  */
++      /* We don't know if we have PD ownership.  Once we check the local
++         stopped_start we'll know if we're in state (a) or (b) (see
++	 CONCURRENCY NOTES above).  */
++      if (stopped_start)
++	/* State (a), we own PD. The thread blocked on this lock either
++	   because we're doing TD_CREATE event reporting, or for some
++	   other reason that create_thread chose.  Now let it run
++	   free.  */
+ 	lll_unlock (pd->lock, LLL_PRIVATE);
+ 
+       /* We now have for sure more than one thread.  The main thread might
 diff --git a/nptl/pthread_getattr_np.c b/nptl/pthread_getattr_np.c
-index fb906f0484..32d7484bf8 100644
+index fb906f0484..c2dfa13fa9 100644
 --- a/nptl/pthread_getattr_np.c
 +++ b/nptl/pthread_getattr_np.c
-@@ -68,7 +68,6 @@ pthread_getattr_np (pthread_t thread_id, pthread_attr_t *attr)
+@@ -57,9 +57,12 @@ pthread_getattr_np (pthread_t thread_id, pthread_attr_t *attr)
+   /* The sizes are subject to alignment.  */
+   if (__glibc_likely (thread->stackblock != NULL))
+     {
+-      iattr->stacksize = thread->stackblock_size;
++      /* The stack size reported to the user should not include the
++	 guard size.  */
++      iattr->stacksize = thread->stackblock_size - thread->guardsize;
+ #if _STACK_GROWS_DOWN
+-      iattr->stackaddr = (char *) thread->stackblock + iattr->stacksize;
++      iattr->stackaddr = (char *) thread->stackblock
++			 + thread->stackblock_size;
+ #else
+       iattr->stackaddr = (char *) thread->stackblock;
+ #endif
+@@ -68,7 +71,6 @@ pthread_getattr_np (pthread_t thread_id, pthread_attr_t *attr)
      {
        /* No stack information available.  This must be for the initial
  	 thread.  Get the info in some magical way.  */
@@ -2178,6 +3030,205 @@ index fb906f0484..32d7484bf8 100644
  
        /* Stack size limit.  */
        struct rlimit rl;
+diff --git a/nptl/pthread_getschedparam.c b/nptl/pthread_getschedparam.c
+index b887881baf..de71171a08 100644
+--- a/nptl/pthread_getschedparam.c
++++ b/nptl/pthread_getschedparam.c
+@@ -35,6 +35,7 @@ __pthread_getschedparam (pthread_t threadid, int *policy,
+ 
+   int result = 0;
+ 
++  /* See CREATE THREAD NOTES in nptl/pthread_create.c.  */
+   lll_lock (pd->lock, LLL_PRIVATE);
+ 
+   /* The library is responsible for maintaining the values at all
+diff --git a/nptl/pthread_setschedparam.c b/nptl/pthread_setschedparam.c
+index dfb52b9dbf..dcb520f1c8 100644
+--- a/nptl/pthread_setschedparam.c
++++ b/nptl/pthread_setschedparam.c
+@@ -36,6 +36,7 @@ __pthread_setschedparam (pthread_t threadid, int policy,
+ 
+   int result = 0;
+ 
++  /* See CREATE THREAD NOTES in nptl/pthread_create.c.  */
+   lll_lock (pd->lock, LLL_PRIVATE);
+ 
+   struct sched_param p;
+diff --git a/nptl/pthread_setschedprio.c b/nptl/pthread_setschedprio.c
+index cefc6481d6..8134b50560 100644
+--- a/nptl/pthread_setschedprio.c
++++ b/nptl/pthread_setschedprio.c
+@@ -38,6 +38,7 @@ pthread_setschedprio (pthread_t threadid, int prio)
+   struct sched_param param;
+   param.sched_priority = prio;
+ 
++  /* See CREATE THREAD NOTES in nptl/pthread_create.c.  */
+   lll_lock (pd->lock, LLL_PRIVATE);
+ 
+   /* If the thread should have higher priority because of some
+diff --git a/nptl/tpp.c b/nptl/tpp.c
+index e175bf4d53..223bd6bbee 100644
+--- a/nptl/tpp.c
++++ b/nptl/tpp.c
+@@ -114,6 +114,7 @@ __pthread_tpp_change_priority (int previous_prio, int new_prio)
+   if (priomax == newpriomax)
+     return 0;
+ 
++  /* See CREATE THREAD NOTES in nptl/pthread_create.c.  */
+   lll_lock (self->lock, LLL_PRIVATE);
+ 
+   tpp->priomax = newpriomax;
+@@ -165,6 +166,7 @@ __pthread_current_priority (void)
+ 
+   int result = 0;
+ 
++  /* See CREATE THREAD NOTES in nptl/pthread_create.c.  */
+   lll_lock (self->lock, LLL_PRIVATE);
+ 
+   if ((self->flags & ATTR_FLAG_SCHED_SET) == 0)
+diff --git a/nptl/tst-create-detached.c b/nptl/tst-create-detached.c
+new file mode 100644
+index 0000000000..ea93e441c7
+--- /dev/null
++++ b/nptl/tst-create-detached.c
+@@ -0,0 +1,137 @@
++/* Bug 20116: Test rapid creation of detached threads.
++   Copyright (C) 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; see the file COPYING.LIB.  If
++   not, see <http://www.gnu.org/licenses/>.  */
++
++/* The goal of the test is to trigger a failure if the parent touches
++   any part of the thread descriptor after the detached thread has
++   exited.  We test this by creating many detached threads with large
++   stacks.  The stacks quickly fill the the stack cache and subsequent
++   threads will start to cause the thread stacks to be immediately
++   unmapped to satisfy the stack cache max.  With the stacks being
++   unmapped the parent's read of any part of the thread descriptor will
++   trigger a segfault.  That segfault is what we are trying to cause,
++   since any segfault is a defect in the implementation.  */
++
++#include <pthread.h>
++#include <stdio.h>
++#include <errno.h>
++#include <unistd.h>
++#include <stdbool.h>
++#include <sys/resource.h>
++#include <support/xthread.h>
++
++/* Number of threads to create.  */
++enum { threads_to_create = 100000 };
++
++/* Number of threads which should spawn other threads.  */
++enum { creator_threads  = 2 };
++
++/* Counter of threads created so far.  This is incremented by all the
++   running creator threads.  */
++static unsigned threads_created;
++
++/* Thread callback which does nothing, so that the thread exits
++   immediatedly.  */
++static void *
++do_nothing (void *arg)
++{
++  return NULL;
++}
++
++/* Attribute indicating that the thread should be created in a detached
++   fashion.  */
++static pthread_attr_t detached;
++
++/* Barrier to synchronize initialization.  */
++static pthread_barrier_t barrier;
++
++static void *
++creator_thread (void *arg)
++{
++  int ret;
++  xpthread_barrier_wait (&barrier);
++
++  while (true)
++    {
++      pthread_t thr;
++      /* Thread creation will fail if the kernel does not free old
++	 threads quickly enough, so we do not report errors.  */
++      ret = pthread_create (&thr, &detached, do_nothing, NULL);
++      if (ret == 0 && __atomic_add_fetch (&threads_created, 1, __ATOMIC_SEQ_CST)
++          >= threads_to_create)
++        break;
++    }
++
++  return NULL;
++}
++
++static int
++do_test (void)
++{
++  /* Limit the size of the process, so that memory allocation will
++     fail without impacting the entire system.  */
++  {
++    struct rlimit limit;
++    if (getrlimit (RLIMIT_AS, &limit) != 0)
++      {
++        printf ("FAIL: getrlimit (RLIMIT_AS) failed: %m\n");
++        return 1;
++      }
++    /* This limit, 800MB, is just a heuristic. Any value can be
++       picked.  */
++    long target = 800 * 1024 * 1024;
++    if (limit.rlim_cur == RLIM_INFINITY || limit.rlim_cur > target)
++      {
++        limit.rlim_cur = target;
++        if (setrlimit (RLIMIT_AS, &limit) != 0)
++          {
++            printf ("FAIL: setrlimit (RLIMIT_AS) failed: %m\n");
++            return 1;
++          }
++      }
++  }
++
++  xpthread_attr_init (&detached);
++
++  xpthread_attr_setdetachstate (&detached, PTHREAD_CREATE_DETACHED);
++
++  /* A large thread stack seems beneficial for reproducing a race
++     condition in detached thread creation.  The goal is to reach the
++     limit of the runtime thread stack cache such that the detached
++     thread's stack is unmapped after exit and causes a segfault when
++     the parent reads the thread descriptor data stored on the the
++     unmapped stack.  */
++  xpthread_attr_setstacksize (&detached, 16 * 1024 * 1024);
++
++  xpthread_barrier_init (&barrier, NULL, creator_threads);
++
++  pthread_t threads[creator_threads];
++
++  for (int i = 0; i < creator_threads; ++i)
++    threads[i] = xpthread_create (NULL, creator_thread, NULL);
++
++  for (int i = 0; i < creator_threads; ++i)
++    xpthread_join (threads[i]);
++
++  xpthread_attr_destroy (&detached);
++
++  xpthread_barrier_destroy (&barrier);
++
++  return 0;
++}
++
++#include <support/test-driver.c>
 diff --git a/nptl/tst-exec5.c b/nptl/tst-exec5.c
 new file mode 100644
 index 0000000000..4327d8d41c
@@ -2380,58 +3431,164 @@ index 0000000000..4327d8d41c
 +
 +  return 0;
 +}
-diff --git a/nptl/tst-once5.cc b/nptl/tst-once5.cc
-index 978d8271bd..513ac53f6f 100644
---- a/nptl/tst-once5.cc
-+++ b/nptl/tst-once5.cc
-@@ -75,5 +75,7 @@ do_test (void)
-   return result;
- }
- 
-+// The test currently hangs and is XFAILed.  Reduce the timeout.
-+#define TIMEOUT 1
- #define TEST_FUNCTION do_test ()
- #include "../test-skeleton.c"
-diff --git a/nptl_db/structs.def b/nptl_db/structs.def
-index a9b621b126..1cb6a46391 100644
---- a/nptl_db/structs.def
-+++ b/nptl_db/structs.def
-@@ -48,7 +48,6 @@ DB_STRUCT (pthread)
- DB_STRUCT_FIELD (pthread, list)
- DB_STRUCT_FIELD (pthread, report_events)
- DB_STRUCT_FIELD (pthread, tid)
--DB_STRUCT_FIELD (pthread, pid)
- DB_STRUCT_FIELD (pthread, start_routine)
- DB_STRUCT_FIELD (pthread, cancelhandling)
- DB_STRUCT_FIELD (pthread, schedpolicy)
-diff --git a/nptl_db/td_ta_thr_iter.c b/nptl_db/td_ta_thr_iter.c
-index a990fed150..9e5059956b 100644
---- a/nptl_db/td_ta_thr_iter.c
-+++ b/nptl_db/td_ta_thr_iter.c
-@@ -76,48 +76,28 @@ iterate_thread_list (td_thragent_t *ta, td_thr_iter_f *callback,
-       if (ps_pdread (ta->ph, addr, copy, ta->ta_sizeof_pthread) != PS_OK)
- 	return TD_ERR;
- 
--      /* Verify that this thread's pid field matches the child PID.
--	 If its pid field is negative, it's about to do a fork or it
--	 is the sole thread in a fork child.  */
--      psaddr_t pid;
--      err = DB_GET_FIELD_LOCAL (pid, ta, copy, pthread, pid, 0);
--      if (err == TD_OK && (pid_t) (uintptr_t) pid < 0)
--	{
--	  if (-(pid_t) (uintptr_t) pid == match_pid)
--	    /* It is about to do a fork, but is really still the parent PID.  */
--	    pid = (psaddr_t) (uintptr_t) match_pid;
--	  else
--	    /* It must be a fork child, whose new PID is in the tid field.  */
--	    err = DB_GET_FIELD_LOCAL (pid, ta, copy, pthread, tid, 0);
--	}
-+      err = DB_GET_FIELD_LOCAL (schedpolicy, ta, copy, pthread,
-+				schedpolicy, 0);
-       if (err != TD_OK)
- 	break;
-+      err = DB_GET_FIELD_LOCAL (schedprio, ta, copy, pthread,
-+				schedparam_sched_priority, 0);
+diff --git a/nptl/tst-minstack-cancel.c b/nptl/tst-minstack-cancel.c
+new file mode 100644
+index 0000000000..a306320e88
+--- /dev/null
++++ b/nptl/tst-minstack-cancel.c
+@@ -0,0 +1,48 @@
++/* Test cancellation with a minimal stack size.
++   Copyright (C) 2018 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/>.  */
++
++/* Note: This test is similar to tst-minstack-exit, but is separate to
++   avoid spurious test passes due to warm-up effects.  */
++
++#include <limits.h>
++#include <unistd.h>
++#include <support/check.h>
++#include <support/xthread.h>
++
++static void *
++threadfunc (void *closure)
++{
++  while (1)
++    pause ();
++  return NULL;
++}
++
++static int
++do_test (void)
++{
++  pthread_attr_t attr;
++  xpthread_attr_init (&attr);
++  xpthread_attr_setstacksize (&attr, PTHREAD_STACK_MIN);
++  pthread_t thr = xpthread_create (&attr, threadfunc, NULL);
++  xpthread_cancel (thr);
++  TEST_VERIFY (xpthread_join (thr) == PTHREAD_CANCELED);
++  xpthread_attr_destroy (&attr);
++  return 0;
++}
++
++#include <support/test-driver.c>
+diff --git a/nptl/tst-minstack-exit.c b/nptl/tst-minstack-exit.c
+new file mode 100644
+index 0000000000..9c7e9a4dfe
+--- /dev/null
++++ b/nptl/tst-minstack-exit.c
+@@ -0,0 +1,46 @@
++/* Test that pthread_exit works with the minimum stack size.
++   Copyright (C) 2018 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/>.  */
++
++/* Note: This test is similar to tst-minstack-cancel, but is separate
++   to avoid spurious test passes due to warm-up effects.  */
++
++#include <limits.h>
++#include <unistd.h>
++#include <support/check.h>
++#include <support/xthread.h>
++
++static void *
++threadfunc (void *closure)
++{
++  pthread_exit (threadfunc);
++  return NULL;
++}
++
++static int
++do_test (void)
++{
++  pthread_attr_t attr;
++  xpthread_attr_init (&attr);
++  xpthread_attr_setstacksize (&attr, PTHREAD_STACK_MIN);
++  pthread_t thr = xpthread_create (&attr, threadfunc, NULL);
++  TEST_VERIFY (xpthread_join (thr) == threadfunc);
++  xpthread_attr_destroy (&attr);
++  return 0;
++}
++
++#include <support/test-driver.c>
+diff --git a/nptl/tst-once5.cc b/nptl/tst-once5.cc
+index 978d8271bd..513ac53f6f 100644
+--- a/nptl/tst-once5.cc
++++ b/nptl/tst-once5.cc
+@@ -75,5 +75,7 @@ do_test (void)
+   return result;
+ }
+ 
++// The test currently hangs and is XFAILed.  Reduce the timeout.
++#define TIMEOUT 1
+ #define TEST_FUNCTION do_test ()
+ #include "../test-skeleton.c"
+diff --git a/nptl_db/structs.def b/nptl_db/structs.def
+index a9b621b126..1cb6a46391 100644
+--- a/nptl_db/structs.def
++++ b/nptl_db/structs.def
+@@ -48,7 +48,6 @@ DB_STRUCT (pthread)
+ DB_STRUCT_FIELD (pthread, list)
+ DB_STRUCT_FIELD (pthread, report_events)
+ DB_STRUCT_FIELD (pthread, tid)
+-DB_STRUCT_FIELD (pthread, pid)
+ DB_STRUCT_FIELD (pthread, start_routine)
+ DB_STRUCT_FIELD (pthread, cancelhandling)
+ DB_STRUCT_FIELD (pthread, schedpolicy)
+diff --git a/nptl_db/td_ta_thr_iter.c b/nptl_db/td_ta_thr_iter.c
+index a990fed150..9e5059956b 100644
+--- a/nptl_db/td_ta_thr_iter.c
++++ b/nptl_db/td_ta_thr_iter.c
+@@ -76,48 +76,28 @@ iterate_thread_list (td_thragent_t *ta, td_thr_iter_f *callback,
+       if (ps_pdread (ta->ph, addr, copy, ta->ta_sizeof_pthread) != PS_OK)
+ 	return TD_ERR;
+ 
+-      /* Verify that this thread's pid field matches the child PID.
+-	 If its pid field is negative, it's about to do a fork or it
+-	 is the sole thread in a fork child.  */
+-      psaddr_t pid;
+-      err = DB_GET_FIELD_LOCAL (pid, ta, copy, pthread, pid, 0);
+-      if (err == TD_OK && (pid_t) (uintptr_t) pid < 0)
+-	{
+-	  if (-(pid_t) (uintptr_t) pid == match_pid)
+-	    /* It is about to do a fork, but is really still the parent PID.  */
+-	    pid = (psaddr_t) (uintptr_t) match_pid;
+-	  else
+-	    /* It must be a fork child, whose new PID is in the tid field.  */
+-	    err = DB_GET_FIELD_LOCAL (pid, ta, copy, pthread, tid, 0);
+-	}
++      err = DB_GET_FIELD_LOCAL (schedpolicy, ta, copy, pthread,
++				schedpolicy, 0);
+       if (err != TD_OK)
+ 	break;
++      err = DB_GET_FIELD_LOCAL (schedprio, ta, copy, pthread,
++				schedparam_sched_priority, 0);
 +      if (err != TD_OK)
 +	break;
 +
@@ -3273,6 +4430,51 @@ index 49d1f23904..e046577b08 100644
 -
 -#~ msgid "cannot create internal descriptors"
 -#~ msgstr "kan inte skapa interna deskriptorer"
+diff --git a/posix/Makefile b/posix/Makefile
+index 5b0e298f75..82a4020c76 100644
+--- a/posix/Makefile
++++ b/posix/Makefile
+@@ -43,7 +43,7 @@ routines :=								      \
+ 	getpgid setpgid getpgrp bsd-getpgrp setpgrp getsid setsid	      \
+ 	getresuid getresgid setresuid setresgid				      \
+ 	pathconf sysconf fpathconf					      \
+-	glob glob64 fnmatch regex					      \
++	glob glob64 globfree globfree64 glob_pattern_p fnmatch regex	      \
+ 	confstr								      \
+ 	getopt getopt1 getopt_init					      \
+ 	sched_setp sched_getp sched_sets sched_gets sched_yield sched_primax  \
+@@ -90,7 +90,7 @@ tests		:= tstgetopt testfnm runtests runptests	     \
+ 		   bug-getopt5 tst-getopt_long1 bug-regex34 bug-regex35 \
+ 		   tst-pathconf tst-getaddrinfo4 tst-rxspencer-no-utf8 \
+ 		   tst-fnmatch3 bug-regex36 tst-getaddrinfo5 \
+-		   tst-posix_spawn-fd
++		   tst-posix_spawn-fd tst-glob-tilde
+ xtests		:= bug-ga2
+ ifeq (yes,$(build-shared))
+ test-srcs	:= globtest
+@@ -133,7 +133,8 @@ tests-special += $(objpfx)bug-regex2-mem.out $(objpfx)bug-regex14-mem.out \
+ 		 $(objpfx)tst-rxspencer-no-utf8-mem.out $(objpfx)tst-pcre-mem.out \
+ 		 $(objpfx)tst-boost-mem.out $(objpfx)tst-getconf.out \
+ 		 $(objpfx)bug-glob2-mem.out $(objpfx)tst-vfork3-mem.out \
+-		 $(objpfx)tst-fnmatch-mem.out $(objpfx)bug-regex36-mem.out
++		 $(objpfx)tst-fnmatch-mem.out $(objpfx)bug-regex36-mem.out \
++		 $(objpfx)tst-glob-tilde-mem.out
+ xtests-special += $(objpfx)bug-ga2-mem.out
+ endif
+ 
+@@ -340,6 +341,12 @@ $(objpfx)bug-glob2-mem.out: $(objpfx)bug-glob2.out
+ 	$(common-objpfx)malloc/mtrace $(objpfx)bug-glob2.mtrace > $@; \
+ 	$(evaluate-test)
+ 
++tst-glob-tilde-ENV = MALLOC_TRACE=$(objpfx)tst-glob-tilde.mtrace
++
++$(objpfx)tst-glob-tilde-mem.out: $(objpfx)tst-glob-tilde.out
++	$(common-objpfx)malloc/mtrace $(objpfx)tst-glob-tilde.mtrace > $@; \
++	$(evaluate-test)
++
+ $(inst_libexecdir)/getconf: $(inst_bindir)/getconf \
+ 			    $(objpfx)getconf.speclist FORCE
+ 	$(addprefix $(..)./scripts/mkinstalldirs ,\
 diff --git a/posix/execvpe.c b/posix/execvpe.c
 index d933f9c92a..7cdb06a611 100644
 --- a/posix/execvpe.c
@@ -3326,6 +4528,1880 @@ index d933f9c92a..7cdb06a611 100644
  
        __execve (buffer, argv, envp);
  
+diff --git a/posix/flexmember.h b/posix/flexmember.h
+new file mode 100644
+index 0000000000..107c1f09e9
+--- /dev/null
++++ b/posix/flexmember.h
+@@ -0,0 +1,45 @@
++/* Sizes of structs with flexible array members.
++
++   Copyright 2016-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/>.
++
++   Written by Paul Eggert.  */
++
++#include <stddef.h>
++
++/* Nonzero multiple of alignment of TYPE, suitable for FLEXSIZEOF below.
++   On older platforms without _Alignof, use a pessimistic bound that is
++   safe in practice even if FLEXIBLE_ARRAY_MEMBER is 1.
++   On newer platforms, use _Alignof to get a tighter bound.  */
++
++#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 201112
++# define FLEXALIGNOF(type) (sizeof (type) & ~ (sizeof (type) - 1))
++#else
++# define FLEXALIGNOF(type) _Alignof (type)
++#endif
++
++/* Upper bound on the size of a struct of type TYPE with a flexible
++   array member named MEMBER that is followed by N bytes of other data.
++   This is not simply sizeof (TYPE) + N, since it may require
++   alignment on unusually picky C11 platforms, and
++   FLEXIBLE_ARRAY_MEMBER may be 1 on pre-C11 platforms.
++   Yield a value less than N if and only if arithmetic overflow occurs.  */
++
++#define FLEXSIZEOF(type, member, n) \
++   ((offsetof (type, member) + FLEXALIGNOF (type) - 1 + (n)) \
++    & ~ (FLEXALIGNOF (type) - 1))
+diff --git a/posix/glob.c b/posix/glob.c
+index ea4b0b61eb..f3fa807700 100644
+--- a/posix/glob.c
++++ b/posix/glob.c
+@@ -15,7 +15,7 @@
+    License along with the GNU C Library; if not, see
+    <http://www.gnu.org/licenses/>.  */
+ 
+-#ifdef	HAVE_CONFIG_H
++#ifndef _LIBC
+ # include <config.h>
+ #endif
+ 
+@@ -27,29 +27,15 @@
+ #include <stdbool.h>
+ #include <stddef.h>
+ #include <stdint.h>
+-
+-/* Outcomment the following line for production quality code.  */
+-/* #define NDEBUG 1 */
+ #include <assert.h>
++#include <unistd.h>
+ 
+-#include <stdio.h>		/* Needed on stupid SunOS for assert.  */
+-
+-#if !defined _LIBC || !defined GLOB_ONLY_P
+-#if defined HAVE_UNISTD_H || defined _LIBC
+-# include <unistd.h>
+-# ifndef POSIX
+-#  ifdef _POSIX_VERSION
+-#   define POSIX
+-#  endif
+-# endif
++#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
++# define WINDOWS32
+ #endif
+ 
+-#include <pwd.h>
+-
+-#if defined HAVE_STDINT_H || defined _LIBC
+-# include <stdint.h>
+-#elif !defined UINTPTR_MAX
+-# define UINTPTR_MAX (~((size_t) 0))
++#ifndef WINDOWS32
++# include <pwd.h>
+ #endif
+ 
+ #include <errno.h>
+@@ -57,24 +43,7 @@
+ # define __set_errno(val) errno = (val)
+ #endif
+ 
+-#if defined HAVE_DIRENT_H || defined __GNU_LIBRARY__
+-# include <dirent.h>
+-#else
+-# define dirent direct
+-# ifdef HAVE_SYS_NDIR_H
+-#  include <sys/ndir.h>
+-# endif
+-# ifdef HAVE_SYS_DIR_H
+-#  include <sys/dir.h>
+-# endif
+-# ifdef HAVE_NDIR_H
+-#  include <ndir.h>
+-# endif
+-# ifdef HAVE_VMSDIR_H
+-#  include "vmsdir.h"
+-# endif /* HAVE_VMSDIR_H */
+-#endif
+-
++#include <dirent.h>
+ #include <stdlib.h>
+ #include <string.h>
+ #include <alloca.h>
+@@ -87,27 +56,29 @@
+ # define opendir(name) __opendir (name)
+ # define readdir(str) __readdir64 (str)
+ # define getpwnam_r(name, bufp, buf, len, res) \
+-   __getpwnam_r (name, bufp, buf, len, res)
++    __getpwnam_r (name, bufp, buf, len, res)
+ # ifndef __stat64
+ #  define __stat64(fname, buf) __xstat64 (_STAT_VER, fname, buf)
+ # endif
+ # define struct_stat64		struct stat64
++# define FLEXIBLE_ARRAY_MEMBER
+ #else /* !_LIBC */
+-# include "getlogin_r.h"
+-# include "mempcpy.h"
+-# include "stat-macros.h"
+-# include "strdup.h"
+-# define __stat64(fname, buf)	stat (fname, buf)
+-# define struct_stat64		struct stat
+-# define __stat(fname, buf)	stat (fname, buf)
+-# define __alloca		alloca
+-# define __readdir		readdir
+-# define __readdir64		readdir64
+-# define __glob_pattern_p	glob_pattern_p
++# define __getlogin_r(buf, len) getlogin_r (buf, len)
++# define __stat64(fname, buf)   stat (fname, buf)
++# define __fxstatat64(_, d, f, st, flag) fstatat (d, f, st, flag)
++# define struct_stat64          struct stat
++# ifndef __MVS__
++#  define __alloca              alloca
++# endif
++# define __readdir              readdir
++# define COMPILE_GLOB64
+ #endif /* _LIBC */
+ 
+ #include <fnmatch.h>
+ 
++#include <flexmember.h>
++#include <glob_internal.h>
++
+ #ifdef _SC_GETPW_R_SIZE_MAX
+ # define GETPW_R_SIZE_MAX()	sysconf (_SC_GETPW_R_SIZE_MAX)
+ #else
+@@ -121,61 +92,59 @@
+ 
+ static const char *next_brace_sub (const char *begin, int flags) __THROWNL;
+ 
++typedef uint_fast8_t dirent_type;
++
++#if !defined _LIBC && !defined HAVE_STRUCT_DIRENT_D_TYPE
++/* Any distinct values will do here.
++   Undef any existing macros out of the way.  */
++# undef DT_UNKNOWN
++# undef DT_DIR
++# undef DT_LNK
++# define DT_UNKNOWN 0
++# define DT_DIR 1
++# define DT_LNK 2
++#endif
++
+ /* A representation of a directory entry which does not depend on the
+    layout of struct dirent, or the size of ino_t.  */
+ struct readdir_result
+ {
+   const char *name;
+-# if defined _DIRENT_HAVE_D_TYPE || defined HAVE_STRUCT_DIRENT_D_TYPE
+-  uint8_t type;
+-# endif
++#if defined _DIRENT_HAVE_D_TYPE || defined HAVE_STRUCT_DIRENT_D_TYPE
++  dirent_type type;
++#endif
++#if defined _LIBC || defined D_INO_IN_DIRENT
+   bool skip_entry;
++#endif
+ };
+ 
+-# if defined _DIRENT_HAVE_D_TYPE || defined HAVE_STRUCT_DIRENT_D_TYPE
+-/* Initializer based on the d_type member of struct dirent.  */
+-#  define D_TYPE_TO_RESULT(source) (source)->d_type,
+-
+-/* True if the directory entry D might be a symbolic link.  */
+-static bool
+-readdir_result_might_be_symlink (struct readdir_result d)
+-{
+-  return d.type == DT_UNKNOWN || d.type == DT_LNK;
+-}
+-
+-/* True if the directory entry D might be a directory.  */
+-static bool
+-readdir_result_might_be_dir (struct readdir_result d)
+-{
+-  return d.type == DT_DIR || readdir_result_might_be_symlink (d);
+-}
+-# else /* defined _DIRENT_HAVE_D_TYPE || defined HAVE_STRUCT_DIRENT_D_TYPE */
+-#  define D_TYPE_TO_RESULT(source)
+-
+-/* If we do not have type information, symbolic links and directories
+-   are always a possibility.  */
+-
+-static bool
+-readdir_result_might_be_symlink (struct readdir_result d)
++/* Initialize and return type member of struct readdir_result.  */
++static dirent_type
++readdir_result_type (struct readdir_result d)
+ {
+-  return true;
++#if defined _DIRENT_HAVE_D_TYPE || defined HAVE_STRUCT_DIRENT_D_TYPE
++# define D_TYPE_TO_RESULT(source) (source)->d_type,
++  return d.type;
++#else
++# define D_TYPE_TO_RESULT(source)
++  return DT_UNKNOWN;
++#endif
+ }
+ 
++/* Initialize and return skip_entry member of struct readdir_result.  */
+ static bool
+-readdir_result_might_be_dir (struct readdir_result d)
++readdir_result_skip_entry (struct readdir_result d)
+ {
+-  return true;
+-}
+-
+-# endif /* defined _DIRENT_HAVE_D_TYPE || defined HAVE_STRUCT_DIRENT_D_TYPE */
+-
+-# if (defined POSIX || defined WINDOWS32) && !defined __GNU_LIBRARY__
+ /* Initializer for skip_entry.  POSIX does not require that the d_ino
+    field be present, and some systems do not provide it. */
+-#  define D_INO_TO_RESULT(source) false,
+-# else
+-#  define D_INO_TO_RESULT(source) (source)->d_ino == 0,
+-# endif
++#if defined _LIBC || defined D_INO_IN_DIRENT
++# define D_INO_TO_RESULT(source) (source)->d_ino == 0,
++  return d.skip_entry;
++#else
++# define D_INO_TO_RESULT(source)
++  return false;
++#endif
++}
+ 
+ /* Construct an initializer for a struct readdir_result object from a
+    struct dirent *.  No copy of the name is made.  */
+@@ -186,8 +155,6 @@ readdir_result_might_be_dir (struct readdir_result d)
+     D_INO_TO_RESULT (source)		   \
+   }
+ 
+-#endif /* !defined _LIBC || !defined GLOB_ONLY_P */
+-
+ /* Call gl_readdir on STREAM.  This macro can be overridden to reduce
+    type safety if an old interface version needs to be supported.  */
+ #ifndef GL_READDIR
+@@ -225,18 +192,55 @@ convert_dirent64 (const struct dirent64 *source)
+ }
+ #endif
+ 
++#ifndef _LIBC
++/* The results of opendir() in this file are not used with dirfd and fchdir,
++   and we do not leak fds to any single-threaded code that could use stdio,
++   therefore save some unnecessary recursion in fchdir.c and opendir_safer.c.
++   FIXME - if the kernel ever adds support for multi-thread safety for
++   avoiding standard fds, then we should use opendir_safer.  */
++# ifdef GNULIB_defined_opendir
++#  undef opendir
++# endif
++# ifdef GNULIB_defined_closedir
++#  undef closedir
++# endif
+ 
+-#ifndef attribute_hidden
+-# define attribute_hidden
++/* Just use malloc.  */
++# define __libc_use_alloca(n) false
++# define alloca_account(len, avar) ((void) (len), (void) (avar), (void *) 0)
++# define extend_alloca_account(buf, len, newlen, avar) \
++    ((void) (buf), (void) (len), (void) (newlen), (void) (avar), (void *) 0)
+ #endif
+ 
++/* Set *R = A + B.  Return true if the answer is mathematically
++   incorrect due to overflow; in this case, *R is the low order
++   bits of the correct answer.  */
++
++static bool
++size_add_wrapv (size_t a, size_t b, size_t *r)
++{
++#if 5 <= __GNUC__ && !defined __ICC
++  return __builtin_add_overflow (a, b, r);
++#else
++  *r = a + b;
++  return *r < a;
++#endif
++}
++
++static bool
++glob_use_alloca (size_t alloca_used, size_t len)
++{
++  size_t size;
++  return (!size_add_wrapv (alloca_used, len, &size)
++          && __libc_use_alloca (size));
++}
++
+ static int glob_in_dir (const char *pattern, const char *directory,
+ 			int flags, int (*errfunc) (const char *, int),
+ 			glob_t *pglob, size_t alloca_used);
+ extern int __glob_pattern_type (const char *pattern, int quote)
+     attribute_hidden;
+ 
+-#if !defined _LIBC || !defined GLOB_ONLY_P
+ static int prefix_array (const char *prefix, char **array, size_t n) __THROWNL;
+ static int collated_compare (const void *, const void *) __THROWNL;
+ 
+@@ -265,16 +269,15 @@ next_brace_sub (const char *cp, int flags)
+   return *cp != '\0' ? cp : NULL;
+ }
+ 
+-#endif /* !defined _LIBC || !defined GLOB_ONLY_P */
+ 
+ /* Do glob searching for PATTERN, placing results in PGLOB.
+    The bits defined above may be set in FLAGS.
+    If a directory cannot be opened or read and ERRFUNC is not nil,
+    it is called with the pathname that caused the error, and the
+-   `errno' value from the failing call; if it returns non-zero
+-   `glob' returns GLOB_ABORTED; if it returns zero, the error is ignored.
++   'errno' value from the failing call; if it returns non-zero
++   'glob' returns GLOB_ABORTED; if it returns zero, the error is ignored.
+    If memory cannot be allocated for PGLOB, GLOB_NOSPACE is returned.
+-   Otherwise, `glob' returns zero.  */
++   Otherwise, 'glob' returns zero.  */
+ int
+ #ifdef GLOB_ATTRIBUTE
+ GLOB_ATTRIBUTE
+@@ -292,9 +295,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
+   int malloc_dirname = 0;
+   glob_t dirs;
+   int retval = 0;
+-#ifdef _LIBC
+   size_t alloca_used = 0;
+-#endif
+ 
+   if (pattern == NULL || pglob == NULL || (flags & ~__GLOB_FLAGS) != 0)
+     {
+@@ -308,7 +309,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
+     flags |= GLOB_ONLYDIR;
+ 
+   if (!(flags & GLOB_DOOFFS))
+-    /* Have to do this so `globfree' knows where to start freeing.  It
++    /* Have to do this so 'globfree' knows where to start freeing.  It
+        also makes all the code that uses gl_offs simpler. */
+     pglob->gl_offs = 0;
+ 
+@@ -350,14 +351,12 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
+ 	  size_t rest_len;
+ 	  char *onealt;
+ 	  size_t pattern_len = strlen (pattern) - 1;
+-#ifdef _LIBC
+-	  int alloca_onealt = __libc_use_alloca (alloca_used + pattern_len);
++	  int alloca_onealt = glob_use_alloca (alloca_used, pattern_len);
+ 	  if (alloca_onealt)
+ 	    onealt = alloca_account (pattern_len, alloca_used);
+ 	  else
+-#endif
+ 	    {
+-	      onealt = (char *) malloc (pattern_len);
++	      onealt = malloc (pattern_len);
+ 	      if (onealt == NULL)
+ 		{
+ 		  if (!(flags & GLOB_APPEND))
+@@ -377,11 +376,9 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
+ 	  next = next_brace_sub (begin + 1, flags);
+ 	  if (next == NULL)
+ 	    {
+-	      /* It is an illegal expression.  */
++	      /* It is an invalid expression.  */
+ 	    illegal_brace:
+-#ifdef _LIBC
+ 	      if (__glibc_unlikely (!alloca_onealt))
+-#endif
+ 		free (onealt);
+ 	      return glob (pattern, flags & ~GLOB_BRACE, errfunc, pglob);
+ 	    }
+@@ -429,9 +426,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
+ 	      /* If we got an error, return it.  */
+ 	      if (result && result != GLOB_NOMATCH)
+ 		{
+-#ifdef _LIBC
+ 		  if (__glibc_unlikely (!alloca_onealt))
+-#endif
+ 		    free (onealt);
+ 		  if (!(flags & GLOB_APPEND))
+ 		    {
+@@ -450,9 +445,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
+ 	      assert (next != NULL);
+ 	    }
+ 
+-#ifdef _LIBC
+ 	  if (__glibc_unlikely (!alloca_onealt))
+-#endif
+ 	    free (onealt);
+ 
+ 	  if (pglob->gl_pathc != firstc)
+@@ -489,14 +482,16 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
+ 
+   /* Find the filename.  */
+   filename = strrchr (pattern, '/');
++
+ #if defined __MSDOS__ || defined WINDOWS32
+-  /* The case of "d:pattern".  Since `:' is not allowed in
++  /* The case of "d:pattern".  Since ':' is not allowed in
+      file names, we can safely assume that wherever it
+      happens in pattern, it signals the filename part.  This
+      is so we could some day support patterns like "[a-z]:foo".  */
+   if (filename == NULL)
+     filename = strchr (pattern, ':');
+ #endif /* __MSDOS__ || WINDOWS32 */
++
+   dirname_modified = 0;
+   if (filename == NULL)
+     {
+@@ -521,11 +516,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
+ 	    }
+ 
+ 	  filename = pattern;
+-#ifdef _AMIGA
+-	  dirname = (char *) "";
+-#else
+ 	  dirname = (char *) ".";
+-#endif
+ 	  dirlen = 0;
+ 	}
+     }
+@@ -549,22 +540,21 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
+ 	  char *drive_spec;
+ 
+ 	  ++dirlen;
+-	  drive_spec = (char *) __alloca (dirlen + 1);
++	  drive_spec = __alloca (dirlen + 1);
+ 	  *((char *) mempcpy (drive_spec, pattern, dirlen)) = '\0';
+ 	  /* For now, disallow wildcards in the drive spec, to
+ 	     prevent infinite recursion in glob.  */
+ 	  if (__glob_pattern_p (drive_spec, !(flags & GLOB_NOESCAPE)))
+ 	    return GLOB_NOMATCH;
+-	  /* If this is "d:pattern", we need to copy `:' to DIRNAME
++	  /* If this is "d:pattern", we need to copy ':' to DIRNAME
+ 	     as well.  If it's "d:/pattern", don't remove the slash
+ 	     from "d:/", since "d:" and "d:/" are not the same.*/
+ 	}
+ #endif
+-#ifdef _LIBC
+-      if (__libc_use_alloca (alloca_used + dirlen + 1))
++
++      if (glob_use_alloca (alloca_used, dirlen + 1))
+ 	newp = alloca_account (dirlen + 1, alloca_used);
+       else
+-#endif
+ 	{
+ 	  newp = malloc (dirlen + 1);
+ 	  if (newp == NULL)
+@@ -575,14 +565,17 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
+       dirname = newp;
+       ++filename;
+ 
+-      if (filename[0] == '\0'
+ #if defined __MSDOS__ || defined WINDOWS32
+-	  && dirname[dirlen - 1] != ':'
+-	  && (dirlen < 3 || dirname[dirlen - 2] != ':'
+-	      || dirname[dirlen - 1] != '/')
++      bool drive_root = (dirlen > 1
++                         && (dirname[dirlen - 1] == ':'
++                             || (dirlen > 2 && dirname[dirlen - 2] == ':'
++                                 && dirname[dirlen - 1] == '/')));
++#else
++      bool drive_root = false;
+ #endif
+-	  && dirlen > 1)
+-	/* "pattern/".  Expand "pattern", appending slashes.  */
++
++      if (filename[0] == '\0' && dirlen > 1 && !drive_root)
++        /* "pattern/".  Expand "pattern", appending slashes.  */
+ 	{
+ 	  int orig_flags = flags;
+ 	  if (!(flags & GLOB_NOESCAPE) && dirname[dirlen - 1] == '\\')
+@@ -615,7 +608,6 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
+ 	}
+     }
+ 
+-#ifndef VMS
+   if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && dirname[0] == '~')
+     {
+       if (dirname[1] == '\0' || dirname[1] == '/'
+@@ -625,100 +617,127 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
+ 	  /* Look up home directory.  */
+ 	  char *home_dir = getenv ("HOME");
+ 	  int malloc_home_dir = 0;
+-# ifdef _AMIGA
+-	  if (home_dir == NULL || home_dir[0] == '\0')
+-	    home_dir = "SYS:";
+-# else
+-#  ifdef WINDOWS32
+-	  if (home_dir == NULL || home_dir[0] == '\0')
+-	    home_dir = "c:/users/default"; /* poor default */
+-#  else
+ 	  if (home_dir == NULL || home_dir[0] == '\0')
+ 	    {
++#ifdef WINDOWS32
++	      /* Windows NT defines HOMEDRIVE and HOMEPATH.  But give
++		 preference to HOME, because the user can change HOME.  */
++	      const char *home_drive = getenv ("HOMEDRIVE");
++	      const char *home_path = getenv ("HOMEPATH");
++
++	      if (home_drive != NULL && home_path != NULL)
++		{
++		  size_t home_drive_len = strlen (home_drive);
++		  size_t home_path_len = strlen (home_path);
++		  char *mem = alloca (home_drive_len + home_path_len + 1);
++
++		  memcpy (mem, home_drive, home_drive_len);
++		  memcpy (mem + home_drive_len, home_path, home_path_len + 1);
++		  home_dir = mem;
++		}
++	      else
++		home_dir = "c:/users/default"; /* poor default */
++#else
+ 	      int success;
+ 	      char *name;
++	      int malloc_name = 0;
+ 	      size_t buflen = GET_LOGIN_NAME_MAX () + 1;
+ 
+ 	      if (buflen == 0)
+-		/* `sysconf' does not support _SC_LOGIN_NAME_MAX.  Try
++		/* 'sysconf' does not support _SC_LOGIN_NAME_MAX.  Try
+ 		   a moderate value.  */
+ 		buflen = 20;
+-	      name = alloca_account (buflen, alloca_used);
++	      if (glob_use_alloca (alloca_used, buflen))
++		name = alloca_account (buflen, alloca_used);
++	      else
++		{
++		  name = malloc (buflen);
++		  if (name == NULL)
++		    {
++		      retval = GLOB_NOSPACE;
++		      goto out;
++		    }
++		  malloc_name = 1;
++		}
+ 
+ 	      success = __getlogin_r (name, buflen) == 0;
+ 	      if (success)
+ 		{
+ 		  struct passwd *p;
+-#   if defined HAVE_GETPWNAM_R || defined _LIBC
+-		  long int pwbuflen = GETPW_R_SIZE_MAX ();
++		  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 malloc_pwtmpbuf = 0;
+ 		  int save = errno;
+ 
+-#    ifndef _LIBC
+-		  if (pwbuflen == -1)
+-		    /* `sysconf' does not support _SC_GETPW_R_SIZE_MAX.
++#  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 (__libc_use_alloca (alloca_used + pwbuflen))
++#  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 = 1;
++		      malloc_pwtmpbuf = pwtmpbuf;
+ 		    }
+ 
+ 		  while (getpwnam_r (name, &pwbuf, pwtmpbuf, pwbuflen, &p)
+ 			 != 0)
+ 		    {
++		      size_t newlen;
++		      bool v;
+ 		      if (errno != ERANGE)
+ 			{
+ 			  p = NULL;
+ 			  break;
+ 			}
+-
+-		      if (!malloc_pwtmpbuf
+-			  && __libc_use_alloca (alloca_used
+-						+ 2 * pwbuflen))
++		      v = size_add_wrapv (pwbuflen, pwbuflen, &newlen);
++		      if (!v && malloc_pwtmpbuf == NULL
++			  && glob_use_alloca (alloca_used, newlen))
+ 			pwtmpbuf = extend_alloca_account (pwtmpbuf, pwbuflen,
+-							  2 * pwbuflen,
+-							  alloca_used);
++							  newlen, alloca_used);
+ 		      else
+ 			{
+-			  char *newp = realloc (malloc_pwtmpbuf
+-						? pwtmpbuf : NULL,
+-						2 * pwbuflen);
++			  char *newp = (v ? NULL
++					: realloc (malloc_pwtmpbuf, newlen));
+ 			  if (newp == NULL)
+ 			    {
+-			      if (__glibc_unlikely (malloc_pwtmpbuf))
+-				free (pwtmpbuf);
++			      free (malloc_pwtmpbuf);
++			      if (__glibc_unlikely (malloc_name))
++				free (name);
+ 			      retval = GLOB_NOSPACE;
+ 			      goto out;
+ 			    }
+-			  pwtmpbuf = newp;
+-			  pwbuflen = 2 * pwbuflen;
+-			  malloc_pwtmpbuf = 1;
++			  malloc_pwtmpbuf = pwtmpbuf = newp;
+ 			}
++		      pwbuflen = newlen;
+ 		      __set_errno (save);
+ 		    }
+-#   else
++# else
+ 		  p = getpwnam (name);
+-#   endif
++# endif
++		  if (__glibc_unlikely (malloc_name))
++		    free (name);
+ 		  if (p != NULL)
+ 		    {
+-		      if (!malloc_pwtmpbuf)
++		      if (malloc_pwtmpbuf == NULL)
+ 			home_dir = p->pw_dir;
+ 		      else
+ 			{
+ 			  size_t home_dir_len = strlen (p->pw_dir) + 1;
+-			  if (__libc_use_alloca (alloca_used + home_dir_len))
++			  if (glob_use_alloca (alloca_used, home_dir_len))
+ 			    home_dir = alloca_account (home_dir_len,
+ 						       alloca_used);
+ 			  else
+@@ -733,26 +752,32 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
+ 			      malloc_home_dir = 1;
+ 			    }
+ 			  memcpy (home_dir, p->pw_dir, home_dir_len);
+-
+-			  free (pwtmpbuf);
+ 			}
+ 		    }
++		  free (malloc_pwtmpbuf);
+ 		}
++	      else
++		{
++		  if (__glibc_unlikely (malloc_name))
++		    free (name);
++		}
++#endif /* WINDOWS32 */
+ 	    }
+ 	  if (home_dir == NULL || home_dir[0] == '\0')
+ 	    {
++	      if (__glibc_unlikely (malloc_home_dir))
++		free (home_dir);
+ 	      if (flags & GLOB_TILDE_CHECK)
+ 		{
+-		  if (__glibc_unlikely (malloc_home_dir))
+-		    free (home_dir);
+ 		  retval = GLOB_NOMATCH;
+ 		  goto out;
+ 		}
+ 	      else
+-		home_dir = (char *) "~"; /* No luck.  */
++		{
++		  home_dir = (char *) "~"; /* No luck.  */
++		  malloc_home_dir = 0;
++		}
+ 	    }
+-#  endif /* WINDOWS32 */
+-# endif
+ 	  /* Now construct the full directory.  */
+ 	  if (dirname[1] == '\0')
+ 	    {
+@@ -767,8 +792,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
+ 	    {
+ 	      char *newp;
+ 	      size_t home_len = strlen (home_dir);
+-	      int use_alloca = __libc_use_alloca (alloca_used
+-						  + home_len + dirlen);
++	      int use_alloca = glob_use_alloca (alloca_used, home_len + dirlen);
+ 	      if (use_alloca)
+ 		newp = alloca_account (home_len + dirlen, alloca_used);
+ 	      else
+@@ -792,12 +816,15 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
+ 	      dirname = newp;
+ 	      dirlen += home_len - 1;
+ 	      malloc_dirname = !use_alloca;
++
++	      if (__glibc_unlikely (malloc_home_dir))
++		free (home_dir);
+ 	    }
+ 	  dirname_modified = 1;
+ 	}
+-# if !defined _AMIGA && !defined WINDOWS32
+       else
+ 	{
++#ifndef WINDOWS32
+ 	  char *end_name = strchr (dirname, '/');
+ 	  char *user_name;
+ 	  int malloc_user_name = 0;
+@@ -819,7 +846,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
+ 	  else
+ 	    {
+ 	      char *newp;
+-	      if (__libc_use_alloca (alloca_used + (end_name - dirname)))
++	      if (glob_use_alloca (alloca_used, end_name - dirname))
+ 		newp = alloca_account (end_name - dirname, alloca_used);
+ 	      else
+ 		{
+@@ -836,11 +863,11 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
+ 		  char *p = mempcpy (newp, dirname + 1,
+ 				     unescape - dirname - 1);
+ 		  char *q = unescape;
+-		  while (*q != '\0')
++		  while (q != end_name)
+ 		    {
+ 		      if (*q == '\\')
+ 			{
+-			  if (q[1] == '\0')
++			  if (q + 1 == end_name)
+ 			    {
+ 			      /* "~fo\\o\\" unescape to user_name "foo\\",
+ 				 but "~fo\\o\\/" unescape to user_name
+@@ -856,7 +883,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
+ 		  *p = '\0';
+ 		}
+ 	      else
+-		*((char *) mempcpy (newp, dirname + 1, end_name - dirname))
++		*((char *) mempcpy (newp, dirname + 1, end_name - dirname - 1))
+ 		  = '\0';
+ 	      user_name = newp;
+ 	    }
+@@ -864,20 +891,21 @@ 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;
+ #  if defined HAVE_GETPWNAM_R || defined _LIBC
+-	    long int buflen = GETPW_R_SIZE_MAX ();
++	    long int buflenmax = GETPW_R_SIZE_MAX ();
++	    size_t buflen = buflenmax;
+ 	    char *pwtmpbuf;
+-	    int malloc_pwtmpbuf = 0;
+ 	    struct passwd pwbuf;
+ 	    int save = errno;
+ 
+ #   ifndef _LIBC
+-	    if (buflen == -1)
+-	      /* `sysconf' does not support _SC_GETPW_R_SIZE_MAX.  Try a
++	    if (! (0 <= buflenmax && buflenmax <= SIZE_MAX))
++	      /* Perhaps 'sysconf' does not support _SC_GETPW_R_SIZE_MAX.  Try a
+ 		 moderate value.  */
+ 	      buflen = 1024;
+ #   endif
+-	    if (__libc_use_alloca (alloca_used + buflen))
++	    if (glob_use_alloca (alloca_used, buflen))
+ 	      pwtmpbuf = alloca_account (buflen, alloca_used);
+ 	    else
+ 	      {
+@@ -890,32 +918,32 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
+ 		    retval = GLOB_NOSPACE;
+ 		    goto out;
+ 		  }
+-		malloc_pwtmpbuf = 1;
++		malloc_pwtmpbuf = pwtmpbuf;
+ 	      }
+ 
+ 	    while (getpwnam_r (user_name, &pwbuf, pwtmpbuf, buflen, &p) != 0)
+ 	      {
++		size_t newlen;
++		bool v;
+ 		if (errno != ERANGE)
+ 		  {
+ 		    p = NULL;
+ 		    break;
+ 		  }
+-		if (!malloc_pwtmpbuf
+-		    && __libc_use_alloca (alloca_used + 2 * buflen))
++		v = size_add_wrapv (buflen, buflen, &newlen);
++		if (!v && malloc_pwtmpbuf == NULL
++		    && glob_use_alloca (alloca_used, newlen))
+ 		  pwtmpbuf = extend_alloca_account (pwtmpbuf, buflen,
+-						    2 * buflen, alloca_used);
++						    newlen, alloca_used);
+ 		else
+ 		  {
+-		    char *newp = realloc (malloc_pwtmpbuf ? pwtmpbuf : NULL,
+-					  2 * buflen);
++		    char *newp = v ? NULL : realloc (malloc_pwtmpbuf, newlen);
+ 		    if (newp == NULL)
+ 		      {
+-			if (__glibc_unlikely (malloc_pwtmpbuf))
+-			  free (pwtmpbuf);
++			free (malloc_pwtmpbuf);
+ 			goto nomem_getpw;
+ 		      }
+-		    pwtmpbuf = newp;
+-		    malloc_pwtmpbuf = 1;
++		    malloc_pwtmpbuf = pwtmpbuf = newp;
+ 		  }
+ 		__set_errno (save);
+ 	      }
+@@ -936,7 +964,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
+ 		  free (dirname);
+ 		malloc_dirname = 0;
+ 
+-		if (__libc_use_alloca (alloca_used + home_len + rest_len + 1))
++		if (glob_use_alloca (alloca_used, home_len + rest_len + 1))
+ 		  dirname = alloca_account (home_len + rest_len + 1,
+ 					    alloca_used);
+ 		else
+@@ -944,8 +972,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
+ 		    dirname = malloc (home_len + rest_len + 1);
+ 		    if (dirname == NULL)
+ 		      {
+-			if (__glibc_unlikely (malloc_pwtmpbuf))
+-			  free (pwtmpbuf);
++			free (malloc_pwtmpbuf);
+ 			retval = GLOB_NOSPACE;
+ 			goto out;
+ 		      }
+@@ -957,24 +984,24 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
+ 		dirlen = home_len + rest_len;
+ 		dirname_modified = 1;
+ 
+-		if (__glibc_unlikely (malloc_pwtmpbuf))
+-		  free (pwtmpbuf);
++		free (malloc_pwtmpbuf);
+ 	      }
+ 	    else
+ 	      {
+-		if (__glibc_unlikely (malloc_pwtmpbuf))
+-		  free (pwtmpbuf);
++		free (malloc_pwtmpbuf);
+ 
+ 		if (flags & GLOB_TILDE_CHECK)
+-		  /* We have to regard it as an error if we cannot find the
+-		     home directory.  */
+-		  return GLOB_NOMATCH;
++		  {
++		    /* We have to regard it as an error if we cannot find the
++		       home directory.  */
++		    retval = GLOB_NOMATCH;
++		    goto out;
++		  }
+ 	      }
+ 	  }
++#endif /* !WINDOWS32 */
+ 	}
+-# endif	/* Not Amiga && not WINDOWS32.  */
+     }
+-#endif	/* Not VMS.  */
+ 
+   /* Now test whether we looked for "~" or "~NAME".  In this case we
+      can give the answer now.  */
+@@ -993,19 +1020,18 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
+ 	  size_t newcount = pglob->gl_pathc + pglob->gl_offs;
+ 	  char **new_gl_pathv;
+ 
+-	  if (newcount > UINTPTR_MAX - (1 + 1)
+-	      || newcount + 1 + 1 > ~((size_t) 0) / sizeof (char *))
++	  if (newcount > SIZE_MAX / sizeof (char *) - 2)
+ 	    {
+ 	    nospace:
+ 	      free (pglob->gl_pathv);
+ 	      pglob->gl_pathv = NULL;
+ 	      pglob->gl_pathc = 0;
+-	      return GLOB_NOSPACE;
++	      retval = GLOB_NOSPACE;
++	      goto out;
+ 	    }
+ 
+-	  new_gl_pathv
+-	    = (char **) realloc (pglob->gl_pathv,
+-				 (newcount + 1 + 1) * sizeof (char *));
++	  new_gl_pathv = realloc (pglob->gl_pathv,
++				  (newcount + 2) * sizeof (char *));
+ 	  if (new_gl_pathv == NULL)
+ 	    goto nospace;
+ 	  pglob->gl_pathv = new_gl_pathv;
+@@ -1019,12 +1045,19 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
+ 	      p = mempcpy (pglob->gl_pathv[newcount], dirname, dirlen);
+ 	      p[0] = '/';
+ 	      p[1] = '\0';
++	      if (__glibc_unlikely (malloc_dirname))
++		free (dirname);
+ 	    }
+ 	  else
+ 	    {
+-	      pglob->gl_pathv[newcount] = strdup (dirname);
+-	      if (pglob->gl_pathv[newcount] == NULL)
+-		goto nospace;
++	      if (__glibc_unlikely (malloc_dirname))
++		pglob->gl_pathv[newcount] = dirname;
++	      else
++		{
++		  pglob->gl_pathv[newcount] = strdup (dirname);
++		  if (pglob->gl_pathv[newcount] == NULL)
++		    goto nospace;
++		}
+ 	    }
+ 	  pglob->gl_pathv[++newcount] = NULL;
+ 	  ++pglob->gl_pathc;
+@@ -1034,7 +1067,8 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
+ 	}
+ 
+       /* Not found.  */
+-      return GLOB_NOMATCH;
++      retval = GLOB_NOMATCH;
++      goto out;
+     }
+ 
+   meta = __glob_pattern_type (dirname, !(flags & GLOB_NOESCAPE));
+@@ -1080,7 +1114,10 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
+       if (status != 0)
+ 	{
+ 	  if ((flags & GLOB_NOCHECK) == 0 || status != GLOB_NOMATCH)
+-	    return status;
++	    {
++	      retval = status;
++	      goto out;
++	    }
+ 	  goto no_matches;
+ 	}
+ 
+@@ -1091,19 +1128,6 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
+ 	{
+ 	  size_t old_pathc;
+ 
+-#ifdef	SHELL
+-	  {
+-	    /* Make globbing interruptible in the bash shell. */
+-	    extern int interrupt_state;
+-
+-	    if (interrupt_state)
+-	      {
+-		globfree (&dirs);
+-		return GLOB_ABORTED;
+-	      }
+-	  }
+-#endif /* SHELL.  */
+-
+ 	  old_pathc = pglob->gl_pathc;
+ 	  status = glob_in_dir (filename, dirs.gl_pathv[i],
+ 				((flags | GLOB_APPEND)
+@@ -1118,7 +1142,8 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
+ 	      globfree (&dirs);
+ 	      globfree (pglob);
+ 	      pglob->gl_pathc = 0;
+-	      return status;
++	      retval = status;
++	      goto out;
+ 	    }
+ 
+ 	  /* Stick the directory on the front of each name.  */
+@@ -1129,13 +1154,14 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
+ 	      globfree (&dirs);
+ 	      globfree (pglob);
+ 	      pglob->gl_pathc = 0;
+-	      return GLOB_NOSPACE;
++	      retval = GLOB_NOSPACE;
++	      goto out;
+ 	    }
+ 	}
+ 
+       flags |= GLOB_MAGCHAR;
+ 
+-      /* We have ignored the GLOB_NOCHECK flag in the `glob_in_dir' calls.
++      /* We have ignored the GLOB_NOCHECK flag in the 'glob_in_dir' calls.
+ 	 But if we have not found any matching entry and the GLOB_NOCHECK
+ 	 flag was set we must return the input pattern itself.  */
+       if (pglob->gl_pathc + pglob->gl_offs == oldcount)
+@@ -1147,28 +1173,28 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
+ 	      size_t newcount = pglob->gl_pathc + pglob->gl_offs;
+ 	      char **new_gl_pathv;
+ 
+-	      if (newcount > UINTPTR_MAX - 2
+-		  || newcount + 2 > ~((size_t) 0) / sizeof (char *))
++	      if (newcount > SIZE_MAX / sizeof (char *) - 2)
+ 		{
+ 		nospace2:
+ 		  globfree (&dirs);
+-		  return GLOB_NOSPACE;
++		  retval = GLOB_NOSPACE;
++		  goto out;
+ 		}
+ 
+-	      new_gl_pathv = (char **) realloc (pglob->gl_pathv,
+-						(newcount + 2)
+-						* sizeof (char *));
++	      new_gl_pathv = realloc (pglob->gl_pathv,
++				      (newcount + 2) * sizeof (char *));
+ 	      if (new_gl_pathv == NULL)
+ 		goto nospace2;
+ 	      pglob->gl_pathv = new_gl_pathv;
+ 
+-	      pglob->gl_pathv[newcount] = __strdup (pattern);
++	      pglob->gl_pathv[newcount] = strdup (pattern);
+ 	      if (pglob->gl_pathv[newcount] == NULL)
+ 		{
+ 		  globfree (&dirs);
+ 		  globfree (pglob);
+ 		  pglob->gl_pathc = 0;
+-		  return GLOB_NOSPACE;
++		  retval = GLOB_NOSPACE;
++		  goto out;
+ 		}
+ 
+ 	      ++pglob->gl_pathc;
+@@ -1180,7 +1206,8 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
+ 	  else
+ 	    {
+ 	      globfree (&dirs);
+-	      return GLOB_NOMATCH;
++	      retval = GLOB_NOMATCH;
++	      goto out;
+ 	    }
+ 	}
+ 
+@@ -1226,7 +1253,8 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
+ 	      flags = orig_flags;
+ 	      goto no_matches;
+ 	    }
+-	  return status;
++	  retval = status;
++	  goto out;
+ 	}
+ 
+       if (dirlen > 0)
+@@ -1238,7 +1266,8 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
+ 	    {
+ 	      globfree (pglob);
+ 	      pglob->gl_pathc = 0;
+-	      return GLOB_NOSPACE;
++	      retval = GLOB_NOSPACE;
++	      goto out;
+ 	    }
+ 	}
+     }
+@@ -1263,7 +1292,8 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
+ 	      {
+ 		globfree (pglob);
+ 		pglob->gl_pathc = 0;
+-		return GLOB_NOSPACE;
++		retval = GLOB_NOSPACE;
++		goto out;
+ 	      }
+ 	    strcpy (&new[len - 2], "/");
+ 	    pglob->gl_pathv[i] = new;
+@@ -1289,32 +1319,12 @@ libc_hidden_def (glob)
+ #endif
+ 
+ 
+-#if !defined _LIBC || !defined GLOB_ONLY_P
+-
+-/* Free storage allocated in PGLOB by a previous `glob' call.  */
+-void
+-globfree (glob_t *pglob)
+-{
+-  if (pglob->gl_pathv != NULL)
+-    {
+-      size_t i;
+-      for (i = 0; i < pglob->gl_pathc; ++i)
+-	free (pglob->gl_pathv[pglob->gl_offs + i]);
+-      free (pglob->gl_pathv);
+-      pglob->gl_pathv = NULL;
+-    }
+-}
+-#if defined _LIBC && !defined globfree
+-libc_hidden_def (globfree)
+-#endif
+-
+-
+ /* Do a collated comparison of A and B.  */
+ static int
+ collated_compare (const void *a, const void *b)
+ {
+-  const char *const s1 = *(const char *const * const) a;
+-  const char *const s2 = *(const char *const * const) b;
++  char *const *ps1 = a; char *s1 = *ps1;
++  char *const *ps2 = b; char *s2 = *ps2;
+ 
+   if (s1 == s2)
+     return 0;
+@@ -1335,28 +1345,24 @@ prefix_array (const char *dirname, char **array, size_t n)
+ {
+   size_t i;
+   size_t dirlen = strlen (dirname);
+-#if defined __MSDOS__ || defined WINDOWS32
+-  int sep_char = '/';
+-# define DIRSEP_CHAR sep_char
+-#else
+-# define DIRSEP_CHAR '/'
+-#endif
++  char dirsep_char = '/';
+ 
+   if (dirlen == 1 && dirname[0] == '/')
+     /* DIRNAME is just "/", so normal prepending would get us "//foo".
+        We want "/foo" instead, so don't prepend any chars from DIRNAME.  */
+     dirlen = 0;
++
+ #if defined __MSDOS__ || defined WINDOWS32
+-  else if (dirlen > 1)
++  if (dirlen > 1)
+     {
+       if (dirname[dirlen - 1] == '/' && dirname[dirlen - 2] == ':')
+ 	/* DIRNAME is "d:/".  Don't prepend the slash from DIRNAME.  */
+ 	--dirlen;
+       else if (dirname[dirlen - 1] == ':')
+ 	{
+-	  /* DIRNAME is "d:".  Use `:' instead of `/'.  */
++	  /* DIRNAME is "d:".  Use ':' instead of '/'.  */
+ 	  --dirlen;
+-	  sep_char = ':';
++	  dirsep_char = ':';
+ 	}
+     }
+ #endif
+@@ -1364,7 +1370,7 @@ prefix_array (const char *dirname, char **array, size_t n)
+   for (i = 0; i < n; ++i)
+     {
+       size_t eltlen = strlen (array[i]) + 1;
+-      char *new = (char *) malloc (dirlen + 1 + eltlen);
++      char *new = malloc (dirlen + 1 + eltlen);
+       if (new == NULL)
+ 	{
+ 	  while (i > 0)
+@@ -1374,7 +1380,7 @@ prefix_array (const char *dirname, char **array, size_t n)
+ 
+       {
+ 	char *endp = mempcpy (new, dirname, dirlen);
+-	*endp++ = DIRSEP_CHAR;
++	*endp++ = dirsep_char;
+ 	mempcpy (endp, array[i], eltlen);
+       }
+       free (array[i]);
+@@ -1384,103 +1390,57 @@ prefix_array (const char *dirname, char **array, size_t n)
+   return 0;
+ }
+ 
+-
+-/* We must not compile this function twice.  */
+-#if !defined _LIBC || !defined NO_GLOB_PATTERN_P
+-int
+-__glob_pattern_type (const char *pattern, int quote)
+-{
+-  const char *p;
+-  int ret = 0;
+-
+-  for (p = pattern; *p != '\0'; ++p)
+-    switch (*p)
+-      {
+-      case '?':
+-      case '*':
+-	return 1;
+-
+-      case '\\':
+-	if (quote)
+-	  {
+-	    if (p[1] != '\0')
+-	      ++p;
+-	    ret |= 2;
+-	  }
+-	break;
+-
+-      case '[':
+-	ret |= 4;
+-	break;
+-
+-      case ']':
+-	if (ret & 4)
+-	  return 1;
+-	break;
+-      }
+-
+-  return ret;
+-}
+-
+-/* Return nonzero if PATTERN contains any metacharacters.
+-   Metacharacters can be quoted with backslashes if QUOTE is nonzero.  */
+-int
+-__glob_pattern_p (const char *pattern, int quote)
+-{
+-  return __glob_pattern_type (pattern, quote) == 1;
+-}
+-# ifdef _LIBC
+-weak_alias (__glob_pattern_p, glob_pattern_p)
+-# endif
+-#endif
+-
+-#endif /* !GLOB_ONLY_P */
+-
+-
+ /* We put this in a separate function mainly to allow the memory
+    allocated with alloca to be recycled.  */
+-#if !defined _LIBC || !defined GLOB_ONLY_P
+ static int
+ __attribute_noinline__
+-link_exists2_p (const char *dir, size_t dirlen, const char *fname,
+-	       glob_t *pglob
+-# ifndef _LIBC
+-		, int flags
++link_stat (const char *dir, size_t dirlen, const char *fname,
++	   glob_t *pglob
++# if !defined _LIBC && !HAVE_FSTATAT
++	   , int flags
+ # endif
+-		)
++	   )
+ {
+   size_t fnamelen = strlen (fname);
+-  char *fullname = (char *) __alloca (dirlen + 1 + fnamelen + 1);
++  char *fullname = __alloca (dirlen + 1 + fnamelen + 1);
+   struct stat st;
+-# ifndef _LIBC
+-  struct_stat64 st64;
+-# endif
+ 
+   mempcpy (mempcpy (mempcpy (fullname, dir, dirlen), "/", 1),
+ 	   fname, fnamelen + 1);
+ 
+-# ifdef _LIBC
+-  return (*pglob->gl_stat) (fullname, &st) == 0;
+-# else
+-  return ((__builtin_expect (flags & GLOB_ALTDIRFUNC, 0)
+-	   ? (*pglob->gl_stat) (fullname, &st)
+-	   : __stat64 (fullname, &st64)) == 0);
++# if !defined _LIBC && !HAVE_FSTATAT
++  if (__builtin_expect ((flags & GLOB_ALTDIRFUNC) == 0, 1))
++    {
++      struct_stat64 st64;
++      return __stat64 (fullname, &st64);
++    }
+ # endif
++  return (*pglob->gl_stat) (fullname, &st);
+ }
+-# ifdef _LIBC
+-#  define link_exists_p(dfd, dirname, dirnamelen, fname, pglob, flags) \
+-  (__builtin_expect (flags & GLOB_ALTDIRFUNC, 0)			      \
+-   ? link_exists2_p (dirname, dirnamelen, fname, pglob)			      \
+-   : ({ struct stat64 st64;						      \
+-       __fxstatat64 (_STAT_VER, dfd, fname, &st64, 0) == 0; }))
++
++/* Return true if DIR/FNAME exists.  */
++static int
++link_exists_p (int dfd, const char *dir, size_t dirlen, const char *fname,
++	       glob_t *pglob, int flags)
++{
++  int status;
++# if defined _LIBC || HAVE_FSTATAT
++  if (__builtin_expect (flags & GLOB_ALTDIRFUNC, 0))
++    status = link_stat (dir, dirlen, fname, pglob);
++  else
++    {
++      /* dfd cannot be -1 here, because dirfd never returns -1 on
++	 glibc, or on hosts that have fstatat.  */
++      struct_stat64 st64;
++      status = __fxstatat64 (_STAT_VER, dfd, fname, &st64, 0);
++    }
+ # else
+-#  define link_exists_p(dfd, dirname, dirnamelen, fname, pglob, flags) \
+-  link_exists2_p (dirname, dirnamelen, fname, pglob, flags)
++  status = link_stat (dir, dirlen, fname, pglob, flags);
+ # endif
+-#endif
+-
++  return status == 0 || errno == EOVERFLOW;
++}
+ 
+-/* Like `glob', but PATTERN is a final pathname component,
++/* Like 'glob', but PATTERN is a final pathname component,
+    and matches are searched for in DIRECTORY.
+    The GLOB_NOSORT bit in FLAGS is ignored.  No sorting is ever done.
+    The GLOB_APPEND flag is assumed to be set (always appends).  */
+@@ -1491,25 +1451,25 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
+ {
+   size_t dirlen = strlen (directory);
+   void *stream = NULL;
+-  struct globnames
+-    {
+-      struct globnames *next;
+-      size_t count;
+-      char *name[64];
+-    };
+-#define INITIAL_COUNT sizeof (init_names.name) / sizeof (init_names.name[0])
+-  struct globnames init_names;
+-  struct globnames *names = &init_names;
+-  struct globnames *names_alloca = &init_names;
++# define GLOBNAMES_MEMBERS(nnames) \
++    struct globnames *next; size_t count; char *name[nnames];
++  struct globnames { GLOBNAMES_MEMBERS (FLEXIBLE_ARRAY_MEMBER) };
++  struct { GLOBNAMES_MEMBERS (64) } init_names_buf;
++  struct globnames *init_names = (struct globnames *) &init_names_buf;
++  struct globnames *names = init_names;
++  struct globnames *names_alloca = init_names;
+   size_t nfound = 0;
+   size_t cur = 0;
+   int meta;
+   int save;
++  int result;
+ 
+-  alloca_used += sizeof (init_names);
++  alloca_used += sizeof init_names_buf;
+ 
+-  init_names.next = NULL;
+-  init_names.count = INITIAL_COUNT;
++  init_names->next = NULL;
++  init_names->count = ((sizeof init_names_buf
++                        - offsetof (struct globnames, name))
++                       / sizeof init_names->name[0]);
+ 
+   meta = __glob_pattern_type (pattern, !(flags & GLOB_NOESCAPE));
+   if (meta == 0 && (flags & (GLOB_NOCHECK|GLOB_NOMAGIC)))
+@@ -1529,14 +1489,16 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
+ 	struct_stat64 st64;
+       } ust;
+       size_t patlen = strlen (pattern);
+-      int alloca_fullname = __libc_use_alloca (alloca_used
+-					       + dirlen + 1 + patlen + 1);
++      size_t fullsize;
++      bool alloca_fullname
++        = (! size_add_wrapv (dirlen + 1, patlen + 1, &fullsize)
++           && glob_use_alloca (alloca_used, fullsize));
+       char *fullname;
+       if (alloca_fullname)
+-	fullname = alloca_account (dirlen + 1 + patlen + 1, alloca_used);
++        fullname = alloca_account (fullsize, alloca_used);
+       else
+ 	{
+-	  fullname = malloc (dirlen + 1 + patlen + 1);
++	  fullname = malloc (fullsize);
+ 	  if (fullname == NULL)
+ 	    return GLOB_NOSPACE;
+ 	}
+@@ -1544,9 +1506,11 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
+       mempcpy (mempcpy (mempcpy (fullname, directory, dirlen),
+ 			"/", 1),
+ 	       pattern, patlen + 1);
+-      if ((__builtin_expect (flags & GLOB_ALTDIRFUNC, 0)
++      if (((__builtin_expect (flags & GLOB_ALTDIRFUNC, 0)
+ 	   ? (*pglob->gl_stat) (fullname, &ust.st)
+-	   : __stat64 (fullname, &ust.st64)) == 0)
++	    : __stat64 (fullname, &ust.st64))
++	   == 0)
++	  || errno == EOVERFLOW)
+ 	/* We found this file to be existing.  Now tell the rest
+ 	   of the function to copy this name into the result.  */
+ 	flags |= GLOB_NOCHECK;
+@@ -1568,16 +1532,10 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
+ 	}
+       else
+ 	{
+-#ifdef _LIBC
+ 	  int dfd = (__builtin_expect (flags & GLOB_ALTDIRFUNC, 0)
+ 		     ? -1 : dirfd ((DIR *) stream));
+-#endif
+ 	  int fnm_flags = ((!(flags & GLOB_PERIOD) ? FNM_PERIOD : 0)
+-			   | ((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0)
+-#if defined _AMIGA || defined VMS
+-			   | FNM_CASEFOLD
+-#endif
+-			   );
++			   | ((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0));
+ 	  flags |= GLOB_MAGCHAR;
+ 
+ 	  while (1)
+@@ -1597,19 +1555,24 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
+ 	      }
+ 	      if (d.name == NULL)
+ 		break;
+-	      if (d.skip_entry)
++	      if (readdir_result_skip_entry (d))
+ 		continue;
+ 
+ 	      /* If we shall match only directories use the information
+ 		 provided by the dirent call if possible.  */
+-	      if ((flags & GLOB_ONLYDIR) && !readdir_result_might_be_dir (d))
+-		continue;
++	      if (flags & GLOB_ONLYDIR)
++		switch (readdir_result_type (d))
++		  {
++		  case DT_DIR: case DT_LNK: case DT_UNKNOWN: break;
++		  default: continue;
++		  }
+ 
+ 	      if (fnmatch (pattern, d.name, fnm_flags) == 0)
+ 		{
+ 		  /* If the file we found is a symlink we have to
+ 		     make sure the target file exists.  */
+-		  if (!readdir_result_might_be_symlink (d)
++		  dirent_type type = readdir_result_type (d);
++		  if (! (type == DT_LNK || type == DT_UNKNOWN)
+ 		      || link_exists_p (dfd, directory, dirlen, d.name,
+ 					pglob, flags))
+ 		    {
+@@ -1617,10 +1580,13 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
+ 			{
+ 			  struct globnames *newnames;
+ 			  size_t count = names->count * 2;
+-			  size_t size = (sizeof (struct globnames)
+-					 + ((count - INITIAL_COUNT)
+-					    * sizeof (char *)));
+-			  if (__libc_use_alloca (alloca_used + size))
++			  size_t nameoff = offsetof (struct globnames, name);
++			  size_t size = FLEXSIZEOF (struct globnames, name,
++						    count * sizeof (char *));
++			  if ((SIZE_MAX - nameoff) / 2 / sizeof (char *)
++			      < names->count)
++			    goto memory_error;
++			  if (glob_use_alloca (alloca_used, size))
+ 			    newnames = names_alloca
+ 			      = alloca_account (size, alloca_used);
+ 			  else if ((newnames = malloc (size))
+@@ -1636,6 +1602,8 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
+ 			goto memory_error;
+ 		      ++cur;
+ 		      ++nfound;
++		      if (SIZE_MAX - pglob->gl_offs <= nfound)
++			goto memory_error;
+ 		    }
+ 		}
+ 	    }
+@@ -1646,29 +1614,27 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
+     {
+       size_t len = strlen (pattern);
+       nfound = 1;
+-      names->name[cur] = (char *) malloc (len + 1);
++      names->name[cur] = malloc (len + 1);
+       if (names->name[cur] == NULL)
+ 	goto memory_error;
+       *((char *) mempcpy (names->name[cur++], pattern, len)) = '\0';
+     }
+ 
+-  int result = GLOB_NOMATCH;
++  result = GLOB_NOMATCH;
+   if (nfound != 0)
+     {
++      char **new_gl_pathv;
+       result = 0;
+ 
+-      if (pglob->gl_pathc > UINTPTR_MAX - pglob->gl_offs
+-	  || pglob->gl_pathc + pglob->gl_offs > UINTPTR_MAX - nfound
+-	  || pglob->gl_pathc + pglob->gl_offs + nfound > UINTPTR_MAX - 1
+-	  || (pglob->gl_pathc + pglob->gl_offs + nfound + 1
+-	      > UINTPTR_MAX / sizeof (char *)))
++      if (SIZE_MAX / sizeof (char *) - pglob->gl_pathc
++	  < pglob->gl_offs + nfound + 1)
+ 	goto memory_error;
+ 
+-      char **new_gl_pathv;
+       new_gl_pathv
+-	= (char **) realloc (pglob->gl_pathv,
+-			     (pglob->gl_pathc + pglob->gl_offs + nfound + 1)
+-			     * sizeof (char *));
++	= realloc (pglob->gl_pathv,
++		   (pglob->gl_pathc + pglob->gl_offs + nfound + 1)
++		    * sizeof (char *));
++
+       if (new_gl_pathv == NULL)
+ 	{
+ 	memory_error:
+@@ -1684,7 +1650,7 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
+ 		 and this is the block assigned to OLD here.  */
+ 	      if (names == NULL)
+ 		{
+-		  assert (old == &init_names);
++		  assert (old == init_names);
+ 		  break;
+ 		}
+ 	      cur = names->count;
+@@ -1710,7 +1676,7 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
+ 		 and this is the block assigned to OLD here.  */
+ 	      if (names == NULL)
+ 		{
+-		  assert (old == &init_names);
++		  assert (old == init_names);
+ 		  break;
+ 		}
+ 	      cur = names->count;
+diff --git a/posix/glob64.c b/posix/glob64.c
+index a5f5a7f9e2..39e54afe8b 100644
+--- a/posix/glob64.c
++++ b/posix/glob64.c
+@@ -43,10 +43,4 @@ glob64 (const char *pattern, int flags,
+ }
+ libc_hidden_def (glob64)
+ 
+-void
+-globfree64 (glob64_t *pglob)
+-{
+-}
+-libc_hidden_def (globfree64)
+-
+ stub_warning (glob64)
+diff --git a/posix/glob_internal.h b/posix/glob_internal.h
+new file mode 100644
+index 0000000000..12c93660b7
+--- /dev/null
++++ b/posix/glob_internal.h
+@@ -0,0 +1,57 @@
++/* Shared definition for glob and glob_pattern_p.
++   Copyright (C) 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 GLOB_INTERNAL_H
++# define GLOB_INTERNAL_H
++
++static inline int
++__glob_pattern_type (const char *pattern, int quote)
++{
++  const char *p;
++  int ret = 0;
++
++  for (p = pattern; *p != '\0'; ++p)
++    switch (*p)
++      {
++      case '?':
++      case '*':
++        return 1;
++
++      case '\\':
++        if (quote)
++          {
++            if (p[1] != '\0')
++              ++p;
++            ret |= 2;
++          }
++        break;
++
++      case '[':
++        ret |= 4;
++        break;
++
++      case ']':
++        if (ret & 4)
++          return 1;
++        break;
++      }
++
++  return ret;
++}
++
++#endif /* GLOB_INTERNAL_H  */
+diff --git a/posix/glob_pattern_p.c b/posix/glob_pattern_p.c
+new file mode 100644
+index 0000000000..a17d337182
+--- /dev/null
++++ b/posix/glob_pattern_p.c
+@@ -0,0 +1,33 @@
++/* Return nonzero if PATTERN contains any metacharacters.
++   Copyright (C) 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 <config.h>
++#endif
++
++#include <glob.h>
++#include "glob_internal.h"
++
++/* Return nonzero if PATTERN contains any metacharacters.
++   Metacharacters can be quoted with backslashes if QUOTE is nonzero.  */
++int
++__glob_pattern_p (const char *pattern, int quote)
++{
++  return __glob_pattern_type (pattern, quote) == 1;
++}
++weak_alias (__glob_pattern_p, glob_pattern_p)
+diff --git a/posix/globfree.c b/posix/globfree.c
+new file mode 100644
+index 0000000000..042e29d9b0
+--- /dev/null
++++ b/posix/globfree.c
+@@ -0,0 +1,41 @@
++/* Frees the dynamically allocated storage from an earlier call to glob.
++   Copyright (C) 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 <config.h>
++#endif
++
++#include <glob.h>
++#include <stdlib.h>
++
++/* Free storage allocated in PGLOB by a previous `glob' call.  */
++void
++globfree (glob_t *pglob)
++{
++  if (pglob->gl_pathv != NULL)
++    {
++      size_t i;
++      for (i = 0; i < pglob->gl_pathc; ++i)
++        free (pglob->gl_pathv[pglob->gl_offs + i]);
++      free (pglob->gl_pathv);
++      pglob->gl_pathv = NULL;
++    }
++}
++#ifndef globfree
++libc_hidden_def (globfree)
++#endif
+diff --git a/posix/globfree64.c b/posix/globfree64.c
+new file mode 100644
+index 0000000000..c9f8908a4e
+--- /dev/null
++++ b/posix/globfree64.c
+@@ -0,0 +1,31 @@
++/* Frees the dynamically allocated storage from an earlier call to glob.
++   Copyright (C) 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 <config.h>
++#endif
++
++#include <glob.h>
++#include <stdlib.h>
++
++/* Free storage allocated in PGLOB by a previous `glob' call.  */
++void
++globfree64 (glob64_t *pglob)
++{
++}
++libc_hidden_def (globfree64)
+diff --git a/posix/tst-glob-tilde.c b/posix/tst-glob-tilde.c
+new file mode 100644
+index 0000000000..6886f4371f
+--- /dev/null
++++ b/posix/tst-glob-tilde.c
+@@ -0,0 +1,143 @@
++/* Check for GLOB_TIDLE heap allocation issues (bugs 22320, 22325, 22332).
++   Copyright (C) 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/>.  */
++
++#include <glob.h>
++#include <mcheck.h>
++#include <nss.h>
++#include <pwd.h>
++#include <stdlib.h>
++#include <string.h>
++#include <support/check.h>
++#include <support/support.h>
++
++/* Flag which indicates whether to pass the GLOB_ONLYDIR flag.  */
++static int do_onlydir;
++
++/* Flag which indicates whether to pass the GLOB_NOCHECK flag.  */
++static int do_nocheck;
++
++/* Flag which indicates whether to pass the GLOB_MARK flag.  */
++static int do_mark;
++
++/* Flag which indicates whether to pass the GLOB_NOESCAPE flag.  */
++static int do_noescape;
++
++static void
++one_test (const char *prefix, const char *middle, const char *suffix)
++{
++  char *pattern = xasprintf ("%s%s%s", prefix, middle, suffix);
++  int flags = GLOB_TILDE;
++  if (do_onlydir)
++    flags |= GLOB_ONLYDIR;
++  if (do_nocheck)
++    flags |= GLOB_NOCHECK;
++  if (do_mark)
++    flags |= GLOB_MARK;
++  if (do_noescape)
++    flags |= GLOB_NOESCAPE;
++  glob_t gl;
++  /* This glob call might result in crashes or memory leaks.  */
++  if (glob (pattern, flags, NULL, &gl) == 0)
++    globfree (&gl);
++  free (pattern);
++}
++
++enum
++  {
++    /* The largest base being tested.  */
++    largest_base_size = 500000,
++
++    /* The actual size is the base size plus a variable whose absolute
++       value is not greater than this.  This helps malloc to trigger
++       overflows.  */
++    max_size_skew = 16,
++
++    /* The maximum string length supported by repeating_string
++       below.  */
++    repeat_size = largest_base_size + max_size_skew,
++  };
++
++/* Used to construct strings which repeat a single character 'x'.  */
++static char *repeat;
++
++/* Return a string of SIZE characters.  */
++const char *
++repeating_string (int size)
++{
++  TEST_VERIFY (size >= 0);
++  TEST_VERIFY (size <= repeat_size);
++  const char *repeated_shifted = repeat + repeat_size - size;
++  TEST_VERIFY (strlen (repeated_shifted) == size);
++  return repeated_shifted;
++}
++
++static int
++do_test (void)
++{
++  /* Avoid network-based NSS modules and initialize nss_files with a
++     dummy lookup.  This has to come before mtrace because NSS does
++     not free all memory.  */
++  __nss_configure_lookup ("passwd", "files");
++  (void) getpwnam ("root");
++
++  mtrace ();
++
++  repeat = xmalloc (repeat_size + 1);
++  memset (repeat, 'x', repeat_size);
++  repeat[repeat_size] = '\0';
++
++  /* These numbers control the size of the user name.  The values
++     cover the minimum (0), a typical size (8), a large
++     stack-allocated size (100000), and a somewhat large
++     heap-allocated size (largest_base_size).  */
++  static const int base_sizes[] = { 0, 8, 100, 100000, largest_base_size, -1 };
++
++  for (do_onlydir = 0; do_onlydir < 2; ++do_onlydir)
++    for (do_nocheck = 0; do_nocheck < 2; ++do_nocheck)
++      for (do_mark = 0; do_mark < 2; ++do_mark)
++	for (do_noescape = 0; do_noescape < 2; ++do_noescape)
++	  for (int base_idx = 0; base_sizes[base_idx] >= 0; ++base_idx)
++	    {
++	      for (int size_skew = -max_size_skew; size_skew <= max_size_skew;
++		   ++size_skew)
++		{
++		  int size = base_sizes[base_idx] + size_skew;
++		  if (size < 0)
++		    continue;
++
++		  const char *user_name = repeating_string (size);
++		  one_test ("~", user_name, "/a/b");
++		  one_test ("~", user_name, "x\\x\\x////x\\a");
++		}
++
++	      const char *user_name = repeating_string (base_sizes[base_idx]);
++	      one_test ("~", user_name, "");
++	      one_test ("~", user_name, "/");
++	      one_test ("~", user_name, "/a");
++	      one_test ("~", user_name, "/*/*");
++	      one_test ("~", user_name, "\\/");
++	      one_test ("/~", user_name, "");
++	      one_test ("*/~", user_name, "/a/b");
++	    }
++
++  free (repeat);
++
++  return 0;
++}
++
++#include <support/test-driver.c>
 diff --git a/resolv/Makefile b/resolv/Makefile
 index 8be41d3ae1..a4c86b9762 100644
 --- a/resolv/Makefile
@@ -3712,6 +6788,215 @@ index 0000000000..2ece7ce575
 +}
 +
 +command_$command
+diff --git a/stdlib/Makefile b/stdlib/Makefile
+index fc6f23dcaf..23f2d6e326 100644
+--- a/stdlib/Makefile
++++ b/stdlib/Makefile
+@@ -77,7 +77,7 @@ tests		:= tst-strtol tst-strtod testmb testrand testsort testdiv   \
+ 		   tst-tininess tst-strtod-underflow tst-tls-atexit	    \
+ 		   tst-setcontext3 tst-tls-atexit-nodelete		    \
+ 		   tst-strtol-locale tst-strtod-nan-locale tst-strfmon_l    \
+-		   tst-quick_exit tst-thread-quick_exit
++		   tst-quick_exit tst-thread-quick_exit test-bz22786
+ tests-static	:= tst-secure-getenv
+ ifeq ($(have-cxx-thread_local),yes)
+ CFLAGS-tst-quick_exit.o = -std=c++11
+diff --git a/stdlib/canonicalize.c b/stdlib/canonicalize.c
+index 58bb8de949..59a7b942e0 100644
+--- a/stdlib/canonicalize.c
++++ b/stdlib/canonicalize.c
+@@ -181,7 +181,7 @@ __realpath (const char *name, char *resolved)
+ 		extra_buf = __alloca (path_max);
+ 
+ 	      len = strlen (end);
+-	      if ((long int) (n + len) >= path_max)
++	      if (path_max - n <= len)
+ 		{
+ 		  __set_errno (ENAMETOOLONG);
+ 		  goto error;
+diff --git a/stdlib/test-bz22786.c b/stdlib/test-bz22786.c
+new file mode 100644
+index 0000000000..e445034a8d
+--- /dev/null
++++ b/stdlib/test-bz22786.c
+@@ -0,0 +1,90 @@
++/* Bug 22786: test for buffer overflow in realpath.
++   Copyright (C) 2018 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/>.  */
++
++/* This file must be run from within a directory called "stdlib".  */
++
++#include <errno.h>
++#include <limits.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <unistd.h>
++#include <sys/stat.h>
++#include <sys/types.h>
++#include <support/test-driver.h>
++#include <libc-internal.h>
++
++static int
++do_test (void)
++{
++  const char dir[] = "bz22786";
++  const char lnk[] = "bz22786/symlink";
++
++  rmdir (dir);
++  if (mkdir (dir, 0755) != 0 && errno != EEXIST)
++    {
++      printf ("mkdir %s: %m\n", dir);
++      return EXIT_FAILURE;
++    }
++  if (symlink (".", lnk) != 0 && errno != EEXIST)
++    {
++      printf ("symlink (%s, %s): %m\n", dir, lnk);
++      return EXIT_FAILURE;
++    }
++
++  const size_t path_len = (size_t) INT_MAX + 1;
++
++  DIAG_PUSH_NEEDS_COMMENT;
++#if __GNUC_PREREQ (7, 0)
++  /* GCC 7 warns about too-large allocations; here we need such
++     allocation to succeed for the test to work.  */
++  DIAG_IGNORE_NEEDS_COMMENT (7, "-Walloc-size-larger-than=");
++#endif
++  char *path = malloc (path_len);
++  DIAG_POP_NEEDS_COMMENT;
++
++  if (path == NULL)
++    {
++      printf ("malloc (%zu): %m\n", path_len);
++      return EXIT_UNSUPPORTED;
++    }
++
++  /* Construct very long path = "bz22786/symlink/aaaa....."  */
++  char *p = mempcpy (path, lnk, sizeof (lnk) - 1);
++  *(p++) = '/';
++  memset (p, 'a', path_len - (path - p) - 2);
++  p[path_len - (path - p) - 1] = '\0';
++
++  /* This call crashes before the fix for bz22786 on 32-bit platforms.  */
++  p = realpath (path, NULL);
++
++  if (p != NULL || errno != ENAMETOOLONG)
++    {
++      printf ("realpath: %s (%m)", p);
++      return EXIT_FAILURE;
++    }
++
++  /* Cleanup.  */
++  unlink (lnk);
++  rmdir (dir);
++
++  return 0;
++}
++
++#define TEST_FUNCTION do_test
++#include <support/test-driver.c>
+diff --git a/string/test-memmove.c b/string/test-memmove.c
+index 43433297e5..f44c05d669 100644
+--- a/string/test-memmove.c
++++ b/string/test-memmove.c
+@@ -245,6 +245,60 @@ do_random_tests (void)
+     }
+ }
+ 
++static void
++do_test2 (void)
++{
++  size_t size = 0x20000000;
++  uint32_t * large_buf;
++
++  large_buf = mmap ((void*) 0x70000000, size, PROT_READ | PROT_WRITE,
++		    MAP_PRIVATE | MAP_ANON, -1, 0);
++
++  if (large_buf == MAP_FAILED)
++    error (77, errno, "Large mmap failed");
++
++  if ((uintptr_t) large_buf > 0x80000000 - 128
++      || 0x80000000 - (uintptr_t) large_buf > 0x20000000)
++    {
++      error (0, 0, "Large mmap allocated improperly");
++      ret = 77;
++      munmap ((void *) large_buf, size);
++      return;
++    }
++
++  size_t bytes_move = 0x80000000 - (uintptr_t) large_buf;
++  size_t arr_size = bytes_move / sizeof (uint32_t);
++  size_t i;
++
++  FOR_EACH_IMPL (impl, 0)
++    {
++      for (i = 0; i < arr_size; i++)
++        large_buf[i] = (uint32_t) i;
++
++      uint32_t * dst = &large_buf[33];
++
++#ifdef TEST_BCOPY
++      CALL (impl, (char *) large_buf, (char *) dst, bytes_move);
++#else
++      CALL (impl, (char *) dst, (char *) large_buf, bytes_move);
++#endif
++
++      for (i = 0; i < arr_size; i++)
++	{
++	  if (dst[i] != (uint32_t) i)
++	    {
++	      error (0, 0,
++		     "Wrong result in function %s dst \"%p\" src \"%p\" offset \"%zd\"",
++		     impl->name, dst, large_buf, i);
++	      ret = 1;
++	      break;
++	    }
++	}
++    }
++
++  munmap ((void *) large_buf, size);
++}
++
+ int
+ test_main (void)
+ {
+@@ -284,6 +338,9 @@ test_main (void)
+     }
+ 
+   do_random_tests ();
++
++  do_test2 ();
++
+   return ret;
+ }
+ 
+diff --git a/string/test-mempcpy.c b/string/test-mempcpy.c
+index f4969c24a5..d1802308a1 100644
+--- a/string/test-mempcpy.c
++++ b/string/test-mempcpy.c
+@@ -18,6 +18,7 @@
+    <http://www.gnu.org/licenses/>.  */
+ 
+ #define MEMCPY_RESULT(dst, len) (dst) + (len)
++#define MIN_PAGE_SIZE 131072
+ #define TEST_MAIN
+ #define TEST_NAME "mempcpy"
+ #include "test-string.h"
 diff --git a/sunrpc/Makefile b/sunrpc/Makefile
 index 789ef423e5..1e91905011 100644
 --- a/sunrpc/Makefile
@@ -11966,6 +15251,62 @@ index d5b8119c9c..ac57bd5db0 100644
    "LD_LIBRARY_PATH\0"							      \
    "LD_ORIGIN_PATH\0"							      \
    "LD_PRELOAD\0"							      \
+diff --git a/sysdeps/gnu/glob64.c b/sysdeps/gnu/glob64.c
+index d1e4e6f0d5..52e97e2f6a 100644
+--- a/sysdeps/gnu/glob64.c
++++ b/sysdeps/gnu/glob64.c
+@@ -15,11 +15,8 @@
+ #undef __stat
+ #define __stat(file, buf) __xstat64 (_STAT_VER, file, buf)
+ 
+-#define NO_GLOB_PATTERN_P 1
+-
+ #define COMPILE_GLOB64	1
+ 
+ #include <posix/glob.c>
+ 
+ libc_hidden_def (glob64)
+-libc_hidden_def (globfree64)
+diff --git a/sysdeps/gnu/globfree64.c b/sysdeps/gnu/globfree64.c
+new file mode 100644
+index 0000000000..f092d0bf8b
+--- /dev/null
++++ b/sysdeps/gnu/globfree64.c
+@@ -0,0 +1,10 @@
++#include <dirent.h>
++#include <glob.h>
++#include <sys/stat.h>
++
++#define glob_t glob64_t
++#define globfree(pglob) globfree64 (pglob)
++
++#include <posix/globfree.c>
++
++libc_hidden_def (globfree64)
+diff --git a/sysdeps/gnu/unwind-resume.c b/sysdeps/gnu/unwind-resume.c
+index 5d25e73dd1..e81b65692a 100644
+--- a/sysdeps/gnu/unwind-resume.c
++++ b/sysdeps/gnu/unwind-resume.c
+@@ -35,13 +35,17 @@ __libgcc_s_init (void)
+   void *resume, *personality;
+   void *handle;
+ 
+-  handle = __libc_dlopen (LIBGCC_S_SO);
++  /* Use RTLD_NOW here for consistency with pthread_cancel_init.
++     RTLD_NOW will rarely make a difference here because unwinding is
++     already in progress, so libgcc_s.so has already been loaded if
++     its unwinder is used.  */
++  handle = __libc_dlopen_mode (LIBGCC_S_SO, RTLD_NOW | __RTLD_DLOPEN);
+ 
+   if (handle == NULL
+       || (resume = __libc_dlsym (handle, "_Unwind_Resume")) == NULL
+       || (personality = __libc_dlsym (handle, "__gcc_personality_v0")) == NULL)
+     __libc_fatal (LIBGCC_S_SO
+-                  " must be installed for pthread_cancel to work\n");
++                  " must be installed for unwinding to work\n");
+ 
+ #ifdef PTR_MANGLE
+   PTR_MANGLE (resume);
 diff --git a/sysdeps/hppa/dl-machine.h b/sysdeps/hppa/dl-machine.h
 index 9404211819..01bd5bf197 100644
 --- a/sysdeps/hppa/dl-machine.h
@@ -12012,6 +15353,64 @@ index c2f326ee3d..6e852f35b1 100644
 -PID_THREAD_OFFSET		thread_offsetof (pid)
  TID_THREAD_OFFSET		thread_offsetof (tid)
  MULTIPLE_THREADS_THREAD_OFFSET	thread_offsetof (header.multiple_threads)
+diff --git a/sysdeps/i386/i686/multiarch/memcpy-sse2-unaligned.S b/sysdeps/i386/i686/multiarch/memcpy-sse2-unaligned.S
+index 76f34291a3..bb26708d67 100644
+--- a/sysdeps/i386/i686/multiarch/memcpy-sse2-unaligned.S
++++ b/sysdeps/i386/i686/multiarch/memcpy-sse2-unaligned.S
+@@ -72,7 +72,7 @@ ENTRY (MEMCPY)
+ 	cmp	%edx, %eax
+ 
+ # ifdef USE_AS_MEMMOVE
+-	jg	L(check_forward)
++	ja	L(check_forward)
+ 
+ L(mm_len_0_or_more_backward):
+ /* Now do checks for lengths. We do [0..16], [16..32], [32..64], [64..128]
+@@ -81,7 +81,7 @@ L(mm_len_0_or_more_backward):
+ 	jbe	L(mm_len_0_16_bytes_backward)
+ 
+ 	cmpl	$32, %ecx
+-	jg	L(mm_len_32_or_more_backward)
++	ja	L(mm_len_32_or_more_backward)
+ 
+ /* Copy [0..32] and return.  */
+ 	movdqu	(%eax), %xmm0
+@@ -92,7 +92,7 @@ L(mm_len_0_or_more_backward):
+ 
+ L(mm_len_32_or_more_backward):
+ 	cmpl	$64, %ecx
+-	jg	L(mm_len_64_or_more_backward)
++	ja	L(mm_len_64_or_more_backward)
+ 
+ /* Copy [0..64] and return.  */
+ 	movdqu	(%eax), %xmm0
+@@ -107,7 +107,7 @@ L(mm_len_32_or_more_backward):
+ 
+ L(mm_len_64_or_more_backward):
+ 	cmpl	$128, %ecx
+-	jg	L(mm_len_128_or_more_backward)
++	ja	L(mm_len_128_or_more_backward)
+ 
+ /* Copy [0..128] and return.  */
+ 	movdqu	(%eax), %xmm0
+@@ -132,7 +132,7 @@ L(mm_len_128_or_more_backward):
+ 	add	%ecx, %eax
+ 	cmp	%edx, %eax
+ 	movl	SRC(%esp), %eax
+-	jle	L(forward)
++	jbe	L(forward)
+ 	PUSH (%esi)
+ 	PUSH (%edi)
+ 	PUSH (%ebx)
+@@ -269,7 +269,7 @@ L(check_forward):
+ 	add	%edx, %ecx
+ 	cmp	%eax, %ecx
+ 	movl	LEN(%esp), %ecx
+-	jle	L(forward)
++	jbe	L(forward)
+ 
+ /* Now do checks for lengths. We do [0..16], [0..32], [0..64], [0..128]
+ 	separately.  */
 diff --git a/sysdeps/i386/i686/multiarch/strcspn-c.c b/sysdeps/i386/i686/multiarch/strcspn-c.c
 index 6d61e190a8..ec230fb383 100644
 --- a/sysdeps/i386/i686/multiarch/strcspn-c.c
@@ -12236,6 +15635,30 @@ index 664ad650c3..b6fbcfd2dd 100644
 +  nacl_irt_clock_t result;
    return NACL_CALL (__nacl_irt_basic.clock (&result), result);
  }
+diff --git a/sysdeps/nacl/createthread.c b/sysdeps/nacl/createthread.c
+index 7b571c34e2..5465558cc1 100644
+--- a/sysdeps/nacl/createthread.c
++++ b/sysdeps/nacl/createthread.c
+@@ -32,15 +32,13 @@ static void start_thread (void) __attribute__ ((noreturn));
+ 
+ static int
+ create_thread (struct pthread *pd, const struct pthread_attr *attr,
+-	       bool stopped_start, STACK_VARIABLES_PARMS, bool *thread_ran)
++	       bool *stopped_start, STACK_VARIABLES_PARMS, bool *thread_ran)
+ {
+   pd->tid = __nacl_get_tid (pd);
+ 
+-  pd->stopped_start = stopped_start;
+-  if (__glibc_unlikely (stopped_start))
+-    /* We make sure the thread does not run far by forcing it to get a
+-       lock.  We lock it here too so that the new thread cannot continue
+-       until we tell it to.  */
++  pd->stopped_start = *stopped_start;
++  if (__glibc_unlikely (*stopped_start))
++    /* See CONCURRENCY NOTES in nptl/pthread_create.c.  */
+     lll_lock (pd->lock, LLL_PRIVATE);
+ 
+   TLS_DEFINE_INIT_TP (tp, pd);
 diff --git a/sysdeps/nacl/dup.c b/sysdeps/nacl/dup.c
 index 34a7cd46d4..cbce3f5a5a 100644
 --- a/sysdeps/nacl/dup.c
@@ -12306,6 +15729,19 @@ index 616d897a36..a5d1e86d71 100644
        /* Release acquired locks in the multi-threaded case.  */
        if (multiple_threads)
  	{
+diff --git a/sysdeps/nptl/unwind-forcedunwind.c b/sysdeps/nptl/unwind-forcedunwind.c
+index ca757c48ce..24a1c5b30d 100644
+--- a/sysdeps/nptl/unwind-forcedunwind.c
++++ b/sysdeps/nptl/unwind-forcedunwind.c
+@@ -49,7 +49,7 @@ pthread_cancel_init (void)
+       return;
+     }
+ 
+-  handle = __libc_dlopen (LIBGCC_S_SO);
++  handle = __libc_dlopen_mode (LIBGCC_S_SO, RTLD_NOW | __RTLD_DLOPEN);
+ 
+   if (handle == NULL
+       || (resume = __libc_dlsym (handle, "_Unwind_Resume")) == NULL
 diff --git a/sysdeps/posix/wait3.c b/sysdeps/posix/wait3.c
 index cf43d973a7..73722d2be6 100644
 --- a/sysdeps/posix/wait3.c
@@ -13350,6 +16786,19 @@ index 94a2ce0e37..38c2432002 100644
          LIBC_CANCEL_RESET (sc_cancel_oldtype);				     \
        }									     \
      sc_ret;								     \
+diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile
+index 35e1ed48d2..32beaa67d0 100644
+--- a/sysdeps/unix/sysv/linux/Makefile
++++ b/sysdeps/unix/sysv/linux/Makefile
+@@ -140,7 +140,7 @@ endif
+ ifeq ($(subdir),posix)
+ sysdep_headers += bits/initspin.h
+ 
+-sysdep_routines += sched_getcpu
++sysdep_routines += sched_getcpu oldglob
+ 
+ tests += tst-affinity tst-affinity-pid
+ 
 diff --git a/sysdeps/unix/sysv/linux/aarch64/clone.S b/sysdeps/unix/sysv/linux/aarch64/clone.S
 index 76baa7a698..96482e53c0 100644
 --- a/sysdeps/unix/sysv/linux/aarch64/clone.S
@@ -13447,6 +16896,64 @@ index 6a3154f9a7..2757bf20c3 100644
  	cfi_endproc
  	.end thread_start
  
+diff --git a/sysdeps/unix/sysv/linux/alpha/glob.c b/sysdeps/unix/sysv/linux/alpha/glob.c
+index c5dfb85468..19eb9b1c07 100644
+--- a/sysdeps/unix/sysv/linux/alpha/glob.c
++++ b/sysdeps/unix/sysv/linux/alpha/glob.c
+@@ -42,10 +42,6 @@ extern void __new_globfree (glob_t *__pglob);
+ #undef globfree64
+ 
+ versioned_symbol (libc, __new_glob, glob, GLIBC_2_1);
+-versioned_symbol (libc, __new_globfree, globfree, GLIBC_2_1);
+ libc_hidden_ver (__new_glob, glob)
+-libc_hidden_ver (__new_globfree, globfree)
+ 
+ weak_alias (__new_glob, glob64)
+-weak_alias (__new_globfree, globfree64)
+-libc_hidden_ver (__new_globfree, globfree64)
+diff --git a/sysdeps/unix/sysv/linux/alpha/globfree.c b/sysdeps/unix/sysv/linux/alpha/globfree.c
+new file mode 100644
+index 0000000000..98cf1c200b
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/alpha/globfree.c
+@@ -0,0 +1,37 @@
++/* Compat globfree.  Linux/alpha version.
++   Copyright (C) 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/>.  */
++
++#define globfree64 __no_globfree64_decl
++#include <sys/types.h>
++#include <glob.h>
++#include <shlib-compat.h>
++
++#define globfree(pglob) \
++  __new_globfree (pglob)
++
++extern void __new_globfree (glob_t *__pglob);
++
++#include <posix/globfree.c>
++
++#undef globfree64
++
++versioned_symbol (libc, __new_globfree, globfree, GLIBC_2_1);
++libc_hidden_ver (__new_globfree, globfree)
++
++weak_alias (__new_globfree, globfree64)
++libc_hidden_ver (__new_globfree, globfree64)
 diff --git a/sysdeps/unix/sysv/linux/alpha/vfork.S b/sysdeps/unix/sysv/linux/alpha/vfork.S
 index 9fc199ac41..e5f7ed0661 100644
 --- a/sysdeps/unix/sysv/linux/alpha/vfork.S
@@ -13555,10 +17062,46 @@ index 500f5ca4be..794372ee12 100644
  	it	cc
  	RETINSTR(cc, lr)
 diff --git a/sysdeps/unix/sysv/linux/createthread.c b/sysdeps/unix/sysv/linux/createthread.c
-index 6d32cece48..ec86f50814 100644
+index 6d32cece48..80b2cad54e 100644
 --- a/sysdeps/unix/sysv/linux/createthread.c
 +++ b/sysdeps/unix/sysv/linux/createthread.c
-@@ -128,10 +128,10 @@ create_thread (struct pthread *pd, const struct pthread_attr *attr,
+@@ -46,7 +46,7 @@ static int start_thread (void *arg) __attribute__ ((noreturn));
+ 
+ static int
+ create_thread (struct pthread *pd, const struct pthread_attr *attr,
+-	       bool stopped_start, STACK_VARIABLES_PARMS, bool *thread_ran)
++	       bool *stopped_start, STACK_VARIABLES_PARMS, bool *thread_ran)
+ {
+   /* Determine whether the newly created threads has to be started
+      stopped since we have to set the scheduling parameters or set the
+@@ -54,13 +54,11 @@ create_thread (struct pthread *pd, const struct pthread_attr *attr,
+   if (attr != NULL
+       && (__glibc_unlikely (attr->cpuset != NULL)
+ 	  || __glibc_unlikely ((attr->flags & ATTR_FLAG_NOTINHERITSCHED) != 0)))
+-    stopped_start = true;
++    *stopped_start = true;
+ 
+-  pd->stopped_start = stopped_start;
+-  if (__glibc_unlikely (stopped_start))
+-    /* We make sure the thread does not run far by forcing it to get a
+-       lock.  We lock it here too so that the new thread cannot continue
+-       until we tell it to.  */
++  pd->stopped_start = *stopped_start;
++  if (__glibc_unlikely (*stopped_start))
++    /* See CONCURRENCY NOTES in nptl/pthread_creat.c.  */
+     lll_lock (pd->lock, LLL_PRIVATE);
+ 
+   /* We rely heavily on various flags the CLONE function understands:
+@@ -117,7 +115,7 @@ create_thread (struct pthread *pd, const struct pthread_attr *attr,
+       /* Set the affinity mask if necessary.  */
+       if (attr->cpuset != NULL)
+ 	{
+-	  assert (stopped_start);
++	  assert (*stopped_start);
+ 
+ 	  res = INTERNAL_SYSCALL (sched_setaffinity, err, 3, pd->tid,
+ 				  attr->cpusetsize, attr->cpuset);
+@@ -128,10 +126,10 @@ create_thread (struct pthread *pd, const struct pthread_attr *attr,
  	      /* The operation failed.  We have to kill the thread.
  		 We let the normal cancellation mechanism do the work.  */
  
@@ -13572,6 +17115,15 @@ index 6d32cece48..ec86f50814 100644
  
  	      return INTERNAL_SYSCALL_ERRNO (res, err);
  	    }
+@@ -140,7 +138,7 @@ create_thread (struct pthread *pd, const struct pthread_attr *attr,
+       /* Set the scheduling parameters.  */
+       if ((attr->flags & ATTR_FLAG_NOTINHERITSCHED) != 0)
+ 	{
+-	  assert (stopped_start);
++	  assert (*stopped_start);
+ 
+ 	  res = INTERNAL_SYSCALL (sched_setscheduler, err, 3, pd->tid,
+ 				  pd->schedpolicy, &pd->schedparam);
 diff --git a/sysdeps/unix/sysv/linux/getpid.c b/sysdeps/unix/sysv/linux/getpid.c
 deleted file mode 100644
 index 1124549326..0000000000
@@ -13770,6 +17322,63 @@ index 25f2a9c340..feae504ce6 100644
  PSEUDO_END (__clone)
  
  libc_hidden_def (__clone)
+diff --git a/sysdeps/unix/sysv/linux/i386/glob64.c b/sysdeps/unix/sysv/linux/i386/glob64.c
+index 802c957d6c..c2cc85741f 100644
+--- a/sysdeps/unix/sysv/linux/i386/glob64.c
++++ b/sysdeps/unix/sysv/linux/i386/glob64.c
+@@ -19,6 +19,7 @@
+ #include <dirent.h>
+ #include <glob.h>
+ #include <sys/stat.h>
++#include <shlib-compat.h>
+ 
+ #define dirent dirent64
+ #define __readdir(dirp) __readdir64 (dirp)
+@@ -33,44 +34,9 @@
+ #undef __stat
+ #define __stat(file, buf) __xstat64 (_STAT_VER, file, buf)
+ 
+-#define NO_GLOB_PATTERN_P 1
+-
+ #define COMPILE_GLOB64	1
+ 
+ #include <posix/glob.c>
+ 
+-#include "shlib-compat.h"
+-
+-libc_hidden_def (globfree64)
+-
+ versioned_symbol (libc, __glob64, glob64, GLIBC_2_2);
+ libc_hidden_ver (__glob64, glob64)
+-
+-#if SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_2)
+-
+-#include <sysdeps/unix/sysv/linux/i386/olddirent.h>
+-
+-int __old_glob64 (const char *__pattern, int __flags,
+-		  int (*__errfunc) (const char *, int),
+-		  glob64_t *__pglob);
+-
+-#undef dirent
+-#define dirent __old_dirent64
+-#undef GL_READDIR
+-# define GL_READDIR(pglob, stream) \
+-  ((struct __old_dirent64 *) (pglob)->gl_readdir (stream))
+-#undef __readdir
+-#define __readdir(dirp) __old_readdir64 (dirp)
+-#undef glob
+-#define glob(pattern, flags, errfunc, pglob) \
+-  __old_glob64 (pattern, flags, errfunc, pglob)
+-#define convert_dirent __old_convert_dirent
+-#define glob_in_dir __old_glob_in_dir
+-#define GLOB_ATTRIBUTE attribute_compat_text_section
+-
+-#define GLOB_ONLY_P 1
+-
+-#include <posix/glob.c>
+-
+-compat_symbol (libc, __old_glob64, glob64, GLIBC_2_1);
+-#endif
 diff --git a/sysdeps/unix/sysv/linux/i386/vfork.S b/sysdeps/unix/sysv/linux/i386/vfork.S
 index 7a1d3373bb..a865de2201 100644
 --- a/sysdeps/unix/sysv/linux/i386/vfork.S
@@ -13986,6 +17595,13 @@ index 39634c5cf0..7ae65ef723 100644
  	END(__thread_start)
  
  libc_hidden_def (__clone)
+diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/globfree64.c b/sysdeps/unix/sysv/linux/mips/mips64/n64/globfree64.c
+new file mode 100644
+index 0000000000..abc35fdd2b
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/globfree64.c
+@@ -0,0 +1 @@
++/* glob64 is in globfree64.c */
 diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/syscalls.list b/sysdeps/unix/sysv/linux/mips/mips64/n64/syscalls.list
 index 890a74494a..26ab6d0b75 100644
 --- a/sysdeps/unix/sysv/linux/mips/mips64/n64/syscalls.list
@@ -14080,6 +17696,54 @@ index c1bb9c7134..8997269199 100644
  	bne	r7, zero, SYSCALL_ERROR_LABEL
  	ret
  
+diff --git a/sysdeps/unix/sysv/linux/oldglob.c b/sysdeps/unix/sysv/linux/oldglob.c
+new file mode 100644
+index 0000000000..8233e57ce9
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/oldglob.c
+@@ -0,0 +1,42 @@
++#include <shlib-compat.h>
++
++#if SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_2)
++
++#include <dirent.h>
++#include <glob.h>
++#include <sys/stat.h>
++
++#include <sysdeps/unix/sysv/linux/i386/olddirent.h>
++
++int __old_glob64 (const char *__pattern, int __flags,
++		  int (*__errfunc) (const char *, int),
++		  glob64_t *__pglob);
++libc_hidden_proto (__old_glob64);
++
++#define dirent __old_dirent64
++#define GL_READDIR(pglob, stream) \
++  ((struct __old_dirent64 *) (pglob)->gl_readdir (stream))
++#undef __readdir
++#define __readdir(dirp) __old_readdir64 (dirp)
++
++#define glob_t glob64_t
++#define glob(pattern, flags, errfunc, pglob) \
++  __old_glob64 (pattern, flags, errfunc, pglob)
++#define globfree(pglob) globfree64(pglob)
++
++#define convert_dirent __old_convert_dirent
++#define glob_in_dir __old_glob_in_dir
++
++#undef stat
++#define stat stat64
++#undef __stat
++#define __stat(file, buf) __xstat64 (_STAT_VER, file, buf)
++
++#define GLOB_ATTRIBUTE attribute_compat_text_section
++
++#include <posix/glob.c>
++
++libc_hidden_def (__old_glob64);
++
++compat_symbol (libc, __old_glob64, glob64, GLIBC_2_1);
++#endif
 diff --git a/sysdeps/unix/sysv/linux/powerpc/Makefile b/sysdeps/unix/sysv/linux/powerpc/Makefile
 index c89ed9ec7d..2cfb46eca3 100644
 --- a/sysdeps/unix/sysv/linux/powerpc/Makefile
@@ -15062,7 +18726,7 @@ index 0818eba02e..298dd197a9 100644
  	 nop
  END(__libc_vfork)
 diff --git a/sysdeps/unix/sysv/linux/spawni.c b/sysdeps/unix/sysv/linux/spawni.c
-index bb3eecfde1..b5f20a710b 100644
+index bb3eecfde1..abafd2070f 100644
 --- a/sysdeps/unix/sysv/linux/spawni.c
 +++ b/sysdeps/unix/sysv/linux/spawni.c
 @@ -58,22 +58,19 @@
@@ -15094,6 +18758,15 @@ index bb3eecfde1..b5f20a710b 100644
  #endif
  
  
+@@ -103,7 +100,7 @@ maybe_script_execute (struct posix_spawn_args *args)
+       ptrdiff_t argc = args->argc;
+ 
+       /* Construct an argument list for the shell.  */
+-      char *new_argv[argc + 1];
++      char *new_argv[argc + 2];
+       new_argv[0] = (char *) _PATH_BSHELL;
+       new_argv[1] = (char *) args->file;
+       if (argc > 1)
 @@ -329,6 +326,11 @@ __spawnix (pid_t * pid, const char *file,
  
    /* Add a slack area for child's stack.  */
@@ -15437,6 +19110,14 @@ index 68a7e6d6e2..1472311947 100644
 -#define TEST_FUNCTION do_test ()
 -#include "../test-skeleton.c"
 +#include <support/test-driver.c>
+diff --git a/sysdeps/unix/sysv/linux/wordsize-64/globfree64.c b/sysdeps/unix/sysv/linux/wordsize-64/globfree64.c
+new file mode 100644
+index 0000000000..af035e1514
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/wordsize-64/globfree64.c
+@@ -0,0 +1,2 @@
++/* This file is here so sysdeps/gnu/glob64.c doesn't take precedence.  */
++#include <sysdeps/wordsize-64/globfree64.c>
 diff --git a/sysdeps/unix/sysv/linux/x86_64/clone.S b/sysdeps/unix/sysv/linux/x86_64/clone.S
 index 66f4b11490..5629aed395 100644
 --- a/sysdeps/unix/sysv/linux/x86_64/clone.S
@@ -15492,6 +19173,41 @@ index 8332ade9fb..cdd2dea32a 100644
  	cmpl	$-4095, %eax
  	jae SYSCALL_ERROR_LABEL		/* Branch forward if it failed.  */
  
+diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/globfree.c b/sysdeps/unix/sysv/linux/x86_64/x32/globfree.c
+new file mode 100644
+index 0000000000..b76a761c17
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/x86_64/x32/globfree.c
+@@ -0,0 +1 @@
++#include <sysdeps/wordsize-64/globfree.c>
+diff --git a/sysdeps/wordsize-64/glob.c b/sysdeps/wordsize-64/glob.c
+index 082faf1c70..954e8d37e2 100644
+--- a/sysdeps/wordsize-64/glob.c
++++ b/sysdeps/wordsize-64/glob.c
+@@ -4,5 +4,3 @@
+ #undef glob64
+ #undef globfree64
+ weak_alias (glob, glob64)
+-weak_alias (globfree, globfree64)
+-libc_hidden_ver (globfree, globfree64)
+diff --git a/sysdeps/wordsize-64/globfree.c b/sysdeps/wordsize-64/globfree.c
+new file mode 100644
+index 0000000000..ec8c35b489
+--- /dev/null
++++ b/sysdeps/wordsize-64/globfree.c
+@@ -0,0 +1,5 @@
++#define globfree64 __no_globfree64_decl
++#include <posix/globfree.c>
++#undef globfree64
++weak_alias (globfree, globfree64)
++libc_hidden_ver (globfree, globfree64)
+diff --git a/sysdeps/wordsize-64/globfree64.c b/sysdeps/wordsize-64/globfree64.c
+new file mode 100644
+index 0000000000..a0f57ff4b3
+--- /dev/null
++++ b/sysdeps/wordsize-64/globfree64.c
+@@ -0,0 +1 @@
++/* globfree64 is in globfree.c */
 diff --git a/sysdeps/x86/cpu-features-offsets.sym b/sysdeps/x86/cpu-features-offsets.sym
 index f6739fae81..33dd094e37 100644
 --- a/sysdeps/x86/cpu-features-offsets.sym
@@ -16036,7 +19752,7 @@ index 12f1a5cf84..b4cda0f535 100644
 +#undef USE_XSAVEC
 +#undef STATE_SAVE_ALIGNMENT
 diff --git a/sysdeps/x86_64/dl-trampoline.h b/sysdeps/x86_64/dl-trampoline.h
-index b90836ab13..b9c2f1796f 100644
+index b90836ab13..60c8a595c8 100644
 --- a/sysdeps/x86_64/dl-trampoline.h
 +++ b/sysdeps/x86_64/dl-trampoline.h
 @@ -16,40 +16,47 @@
@@ -16072,13 +19788,13 @@ index b90836ab13..b9c2f1796f 100644
 +
 +# if (STATE_SAVE_ALIGNMENT % 16) != 0
 +#  error STATE_SAVE_ALIGNMENT must be multples of 16
- # endif
--#else
--# define REGISTER_SAVE_AREA	REGISTER_SAVE_AREA_RAW
++# endif
 +
 +# if (STATE_SAVE_OFFSET % STATE_SAVE_ALIGNMENT) != 0
 +#  error STATE_SAVE_OFFSET must be multples of STATE_SAVE_ALIGNMENT
-+# endif
+ # endif
+-#else
+-# define REGISTER_SAVE_AREA	REGISTER_SAVE_AREA_RAW
 +
 +# if DL_RUNTIME_RESOLVE_REALIGN_STACK
 +/* Local stack area before jumping to function address: RBX.  */
@@ -16271,6 +19987,25 @@ index b90836ab13..b9c2f1796f 100644
  # if (LR_VECTOR_OFFSET % VEC_SIZE) != 0
  #  error LR_VECTOR_OFFSET must be multples of VEC_SIZE
  # endif
+@@ -446,8 +440,16 @@ _dl_runtime_profile:
+ # ifdef RESTORE_AVX
+ 	/* sizeof(La_x86_64_retval).  Need extra space for 2 SSE
+ 	   registers to detect if xmm0/xmm1 registers are changed
+-	   by audit module.  */
+-	sub $(LRV_SIZE + XMM_SIZE*2), %RSP_LP
++	   by audit module.  Since rsp is aligned to VEC_SIZE, we
++	   need to make sure that the address of La_x86_64_retval +
++	   LRV_VECTOR0_OFFSET is aligned to VEC_SIZE.  */
++#  define LRV_SPACE (LRV_SIZE + XMM_SIZE*2)
++#  define LRV_MISALIGNED ((LRV_SIZE + LRV_VECTOR0_OFFSET) & (VEC_SIZE - 1))
++#  if LRV_MISALIGNED == 0
++	sub $LRV_SPACE, %RSP_LP
++#  else
++	sub $(LRV_SPACE + VEC_SIZE - LRV_MISALIGNED), %RSP_LP
++#  endif
+ # else
+ 	sub $LRV_SIZE, %RSP_LP	# sizeof(La_x86_64_retval)
+ # endif
 diff --git a/sysdeps/x86_64/memcpy_chk.S b/sysdeps/x86_64/memcpy_chk.S
 index 2296b55119..a95b3ad3cf 100644
 --- a/sysdeps/x86_64/memcpy_chk.S
@@ -16310,6 +20045,29 @@ index 9d92c8a7e3..26b49de6f6 100644
  	HAS_ARCH_FEATURE (AVX512F_Usable)
  	jz	1f
  	lea	__memcpy_chk_avx512_no_vzeroupper(%rip), %RAX_LP
+diff --git a/sysdeps/x86_64/multiarch/memmove-avx512-no-vzeroupper.S b/sysdeps/x86_64/multiarch/memmove-avx512-no-vzeroupper.S
+index 664b74de49..90ac9eaff4 100644
+--- a/sysdeps/x86_64/multiarch/memmove-avx512-no-vzeroupper.S
++++ b/sysdeps/x86_64/multiarch/memmove-avx512-no-vzeroupper.S
+@@ -340,6 +340,7 @@ L(preloop_large):
+ 	vmovups	(%rsi), %zmm4
+ 	vmovups	0x40(%rsi), %zmm5
+ 
++	mov	%rdi, %r11
+ /* Align destination for access with non-temporal stores in the loop.  */
+ 	mov	%rdi, %r8
+ 	and	$-0x80, %rdi
+@@ -370,8 +371,8 @@ L(gobble_256bytes_nt_loop):
+ 	cmp	$256, %rdx
+ 	ja	L(gobble_256bytes_nt_loop)
+ 	sfence
+-	vmovups	%zmm4, (%rax)
+-	vmovups	%zmm5, 0x40(%rax)
++	vmovups	%zmm4, (%r11)
++	vmovups	%zmm5, 0x40(%r11)
+ 	jmp	L(check)
+ 
+ L(preloop_large_bkw):
 diff --git a/sysdeps/x86_64/multiarch/memmove.S b/sysdeps/x86_64/multiarch/memmove.S
 index ff5e041420..ef92afde5a 100644
 --- a/sysdeps/x86_64/multiarch/memmove.S
diff --git a/debian/patches/series b/debian/patches/series
index d6b92393..db6000b0 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -217,3 +217,4 @@ any/local-bootstrap-headers.diff
 any/submitted-dlopen-noload.diff
 any/submitted-unicode-9.0.0.diff
 any/cvs-malloc-hardening.diff
+any/local-condvar-do-not-use-requeue-for-pshared-condvars.patch
diff --git a/debian/script.in/nsscheck.sh b/debian/script.in/nsscheck.sh
index 95d4f7ef..4c2f7c2f 100644
--- a/debian/script.in/nsscheck.sh
+++ b/debian/script.in/nsscheck.sh
@@ -11,6 +11,7 @@
 	    	    	-e's/\blpr-ppd\b/lpd-ppd/g' \
 	    	    	-e's/\bmysql-server\b/mysql/g' \
 	    	    	-e's/\bsasl2-bin\b/saslauthd/g' \
+	    	    	-e's/\bpostgresql-common\b/postgresql/g' \
 	    )
 	    echo
 	    echo "Checking init scripts..."

Reply to: