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

Bug#917620: marked as done (stretch-pu: package glibc/2.24-11+deb9u4)



Your message dated Sat, 16 Feb 2019 11:36:33 +0000
with message-id <1550316993.21192.50.camel@adam-barratt.org.uk>
and subject line Closing bugs for updates included in 9.8
has caused the Debian Bug report #917620,
regarding stretch-pu: package glibc/2.24-11+deb9u4
to be marked as done.

This means that you claim that the problem has been dealt with.
If this is not the case it is now your responsibility to reopen the
Bug report if necessary, and/or fix the problem forthwith.

(NB: If you are a system administrator and have no idea what this
message is talking about, this may indicate a serious mail system
misconfiguration somewhere. Please contact owner@bugs.debian.org
immediately.)


-- 
917620: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=917620
Debian Bug Tracking System
Contact owner@bugs.debian.org with problems
--- Begin Message ---
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..."

--- End Message ---
--- Begin Message ---
Version: 9.8

Hi,

The update referenced by each of these bugs was included in this
morning's stretch point release.

Regards,

Adam

--- End Message ---

Reply to: