cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh966775.patch
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh966778.patch
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh970090.patch
+ cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh995972.patch
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1008310.patch
+ cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1019916.patch
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1022022.patch
- cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1091162.patch
- cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1098050.patch
+ cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1027101.patch
+ cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1027261.patch
+ cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1032628.patch
+ cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1044628.patch
+ cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1111460.patch
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1133809-1.patch
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1133809-2.patch
+ cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1139571.patch
+ cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1154563.patch
+ cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1170121.patch
+ cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc/glibc-rh1183533.patch
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc-resolv-stack_chk_fail.patch
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc-remove-ctors-dtors-output-sections.patch
--- /dev/null
+commit 48b67d71ec677d1b3168e52a68b644784cead604
+Author: Andreas Schwab <schwab@redhat.com>
+Date: Wed Sep 14 12:12:25 2011 +0200
+
+ Also relocate in dependency order when doing symbol dependency testing
+
+diff --git a/elf/rtld.c b/elf/rtld.c
+index 764140d..324d979 100644
+--- a/elf/rtld.c
++++ b/elf/rtld.c
+@@ -2027,24 +2027,21 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
+ {
+ /* We have to do symbol dependency testing. */
+ struct relocate_args args;
+- struct link_map *l;
++ unsigned int i;
+
+ args.reloc_mode = GLRO(dl_lazy) ? RTLD_LAZY : 0;
+
+- l = main_map;
+- while (l->l_next != NULL)
+- l = l->l_next;
+- do
++ i = main_map->l_searchlist.r_nlist;
++ while (i-- > 0)
+ {
++ struct link_map *l = main_map->l_initfini[i];
+ if (l != &GL(dl_rtld_map) && ! l->l_faked)
+ {
+ args.l = l;
+ _dl_receive_error (print_unresolved, relocate_doit,
+ &args);
+ }
+- l = l->l_prev;
+ }
+- while (l != NULL);
+
+ if ((GLRO(dl_debug_mask) & DL_DEBUG_PRELINK)
+ && rtld_multiple_ref)
--- /dev/null
+commit 4d653a59ffeae0f46f76a40230e2cfa9587b7e7e
+Author: Siddhesh Poyarekar <siddhesh@redhat.com>
+Date: Fri May 30 22:43:52 2014 +0530
+
+ Add mmap usage in malloc_info output
+
+ The current malloc_info xml output only has information about
+ allocations on the heap. Display information about number of mappings
+ and total mmapped size to this to complete the picture.
+
+diff -pruN a/malloc/malloc.c b/malloc/malloc.c
+--- a/malloc/malloc.c 2014-06-02 07:35:22.573256155 +0530
++++ b/malloc/malloc.c 2014-06-02 07:34:58.856257177 +0530
+@@ -6553,12 +6553,14 @@ malloc_info (int options, FILE *fp)
+ fprintf (fp,
+ "<total type=\"fast\" count=\"%zu\" size=\"%zu\"/>\n"
+ "<total type=\"rest\" count=\"%zu\" size=\"%zu\"/>\n"
++ "<total type=\"mmap\" count=\"%d\" size=\"%zu\"/>\n"
+ "<system type=\"current\" size=\"%zu\"/>\n"
+ "<system type=\"max\" size=\"%zu\"/>\n"
+ "<aspace type=\"total\" size=\"%zu\"/>\n"
+ "<aspace type=\"mprotect\" size=\"%zu\"/>\n"
+ "</malloc>\n",
+ total_nfastblocks, total_fastavail, total_nblocks, total_avail,
++ mp_.n_mmaps, mp_.mmapped_mem,
+ total_system, total_max_system,
+ total_aspace, total_aspace_mprotect);
+
--- /dev/null
+commit 028478fa40d85a73b19638dbe3f83b1acebf370c
+Author: Ulrich Drepper <drepper@gmail.com>
+Date: Thu Mar 10 12:51:33 2011 -0500
+
+ Fix copy relocations handling of unique objects.
+
+ 2011-03-06 Ulrich Drepper <drepper@gmail.com>
+
+and a part of:
+
+commit 33f85a3fb9fe432e0ebf6a3481bc2d5e29cb605f
+Author: Ulrich Drepper <drepper@gmail.com>
+Date: Thu Mar 10 03:18:21 2011 -0500
+
+ Don't run tests checking xecutable stack when SELinux is enforcing.
+
+since the latter incorrectly had a bit of the former changes.
+
+Additionally, the test case needs -lstdc++ to build.
+
+diff --git a/elf/Makefile b/elf/Makefile
+index c427679..56cb1b1 100644
+--- a/elf/Makefile
++++ b/elf/Makefile
+@@ -201,7 +201,7 @@ tests += loadtest restest1 preloadtest loadfail multiload origtest resolvfail \
+ unload3 unload4 unload5 unload6 unload7 unload8 tst-global1 order2 \
+ tst-audit1 tst-audit2 tst-audit9 \
+ tst-stackguard1 tst-addr1 tst-thrlock \
+- tst-unique1 tst-unique2
++ tst-unique1 tst-unique2 tst-unique3
+ # reldep9
+ test-srcs = tst-pathopt
+ tests-execstack-yes = tst-execstack tst-execstack-needed tst-execstack-prog
+@@ -255,6 +255,7 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
+ order2mod1 order2mod2 order2mod3 order2mod4 \
+ tst-unique1mod1 tst-unique1mod2 \
+ tst-unique2mod1 tst-unique2mod2 \
++ tst-unique3lib tst-unique3lib2 \
+ tst-auditmod9a tst-auditmod9b
+ ifeq (yes,$(have-initfini-array))
+ modules-names += tst-array2dep tst-array5dep
+@@ -1178,6 +1179,11 @@ $(objpfx)tst-unique1.out: $(objpfx)tst-unique1mod1.so \
+ $(objpfx)tst-unique2: $(libdl) $(objpfx)tst-unique2mod1.so
+ $(objpfx)tst-unique2.out: $(objpfx)tst-unique2mod2.so
+
++LDLIBS-tst-unique3lib.so = -lstdc++
++LDLIBS-tst-unique3lib2.so = -lstdc++
++$(objpfx)tst-unique3: $(libdl) $(objpfx)tst-unique3lib.so
++$(objpfx)tst-unique3.out: $(objpfx)tst-unique3lib2.so
++
+ ifeq (yes,$(config-cflags-avx))
+ CFLAGS-tst-audit4.c += -mavx
+ CFLAGS-tst-auditmod4a.c += -mavx
+diff --git a/elf/dl-lookup.c b/elf/dl-lookup.c
+index 78c8669..874a4bb 100644
+--- a/elf/dl-lookup.c
++++ b/elf/dl-lookup.c
+@@ -364,8 +363,19 @@ do_lookup_x (const char *undef_name, uint_fast32_t new_hash,
+ if (entries[idx].hashval == new_hash
+ && strcmp (entries[idx].name, undef_name) == 0)
+ {
+- result->s = entries[idx].sym;
+- result->m = (struct link_map *) entries[idx].map;
++ if ((type_class & ELF_RTYPE_CLASS_COPY) != 0)
++ {
++ /* We possibly have to initialize the central
++ copy from the copy addressed through the
++ relocation. */
++ result->s = sym;
++ result->m = (struct link_map *) map;
++ }
++ else
++ {
++ result->s = entries[idx].sym;
++ result->m = (struct link_map *) entries[idx].map;
++ }
+ __rtld_lock_unlock_recursive (tab->lock);
+ return 1;
+ }
+diff --git a/elf/tst-unique3.cc b/elf/tst-unique3.cc
+new file mode 100644
+index 0000000..b2c9593
+--- /dev/null
++++ b/elf/tst-unique3.cc
+@@ -0,0 +1,23 @@
++#include "tst-unique3.h"
++#include <cstdio>
++#include "../dlfcn/dlfcn.h"
++
++int t = S<char>::i;
++
++int
++main (void)
++{
++ std::printf ("%d %d\n", S<char>::i, t);
++ int result = S<char>::i++ != 1 || t != 1;
++ result |= in_lib ();
++ void *d = dlopen ("$ORIGIN/tst-unique3lib2.so", RTLD_LAZY);
++ int (*fp) ();
++ if (d == NULL || (fp = (int(*)()) dlsym (d, "in_lib2")) == NULL)
++ {
++ std::printf ("failed to get symbol in_lib2\n");
++ return 1;
++ }
++ result |= fp ();
++ dlclose (d);
++ return result;
++}
+diff --git a/elf/tst-unique3.h b/elf/tst-unique3.h
+new file mode 100644
+index 0000000..716d236
+--- /dev/null
++++ b/elf/tst-unique3.h
+@@ -0,0 +1,8 @@
++// BZ 12510
++template<typename T>
++struct S
++{
++ static int i;
++};
++
++extern int in_lib (void);
+diff --git a/elf/tst-unique3lib.cc b/elf/tst-unique3lib.cc
+new file mode 100644
+index 0000000..fa8e85a
+--- /dev/null
++++ b/elf/tst-unique3lib.cc
+@@ -0,0 +1,11 @@
++#include <cstdio>
++#include "tst-unique3.h"
++template<typename T> int S<T>::i = 1;
++static int i = S<char>::i;
++
++int
++in_lib (void)
++{
++ std::printf ("in_lib: %d %d\n", S<char>::i, i);
++ return S<char>::i++ != 2 || i != 1;
++}
+diff --git a/elf/tst-unique3lib2.cc b/elf/tst-unique3lib2.cc
+new file mode 100644
+index 0000000..17d817e
+--- /dev/null
++++ b/elf/tst-unique3lib2.cc
+@@ -0,0 +1,12 @@
++#include <cstdio>
++#include "tst-unique3.h"
++
++template<typename T> int S<T>::i;
++
++extern "C"
++int
++in_lib2 ()
++{
++ std::printf ("in_lib2: %d\n", S<char>::i);
++ return S<char>::i != 3;
++}
+diff --git a/include/bits/dlfcn.h b/include/bits/dlfcn.h
+index cb4a5c2..c31a645 100644
+--- a/include/bits/dlfcn.h
++++ b/include/bits/dlfcn.h
+@@ -1,4 +1,3 @@
+ #include_next <bits/dlfcn.h>
+
+-extern void _dl_mcount_wrapper_check (void *__selfpc);
+ libc_hidden_proto (_dl_mcount_wrapper_check)
--- /dev/null
+commit 7cbcdb3699584db8913ca90f705d6337633ee10f
+Author: Siddhesh Poyarekar <siddhesh@redhat.com>
+Date: Fri Oct 25 10:22:12 2013 +0530
+
+ Fix stack overflow due to large AF_INET6 requests
+
+ Resolves #16072 (CVE-2013-4458).
+
+ This patch fixes another stack overflow in getaddrinfo when it is
+ called with AF_INET6. The AF_UNSPEC case was fixed as CVE-2013-1914,
+ but the AF_INET6 case went undetected back then.
+
+commit 91ce40854d0b7f865cf5024ef95a8026b76096f3
+Author: Florian Weimer <fweimer@redhat.com>
+Date: Fri Aug 16 09:38:52 2013 +0200
+
+ CVE-2013-4237, BZ #14699: Buffer overflow in readdir_r
+
+ * sysdeps/posix/dirstream.h (struct __dirstream): Add errcode
+ member.
+ * sysdeps/posix/opendir.c (__alloc_dir): Initialize errcode
+ member.
+ * sysdeps/posix/rewinddir.c (rewinddir): Reset errcode member.
+ * sysdeps/posix/readdir_r.c (__READDIR_R): Enforce NAME_MAX limit.
+ Return delayed error code. Remove GETDENTS_64BIT_ALIGNED
+ conditional.
+ * sysdeps/unix/sysv/linux/wordsize-64/readdir_r.c: Do not define
+ GETDENTS_64BIT_ALIGNED.
+ * sysdeps/unix/sysv/linux/i386/readdir64_r.c: Likewise.
+ * manual/filesys.texi (Reading/Closing Directory): Document
+ ENAMETOOLONG return value of readdir_r. Recommend readdir more
+ strongly.
+ * manual/conf.texi (Limits for Files): Add portability note to
+ NAME_MAX, PATH_MAX.
+ (Pathconf): Add portability note for _PC_NAME_MAX, _PC_PATH_MAX.
+
+diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c
+index e6ce4cf..8ff74b4 100644
+--- a/sysdeps/posix/getaddrinfo.c
++++ b/sysdeps/posix/getaddrinfo.c
+@@ -197,7 +197,22 @@ gaih_inet_serv (const char *servicename, const struct gaih_typeproto *tp,
+ &rc, &herrno, NULL, &localcanon)); \
+ if (rc != ERANGE || herrno != NETDB_INTERNAL) \
+ break; \
+- tmpbuf = extend_alloca (tmpbuf, tmpbuflen, 2 * tmpbuflen); \
++ if (!malloc_tmpbuf && __libc_use_alloca (alloca_used + 2 * tmpbuflen)) \
++ tmpbuf = extend_alloca_account (tmpbuf, tmpbuflen, 2 * tmpbuflen, \
++ alloca_used); \
++ else \
++ { \
++ char *newp = realloc (malloc_tmpbuf ? tmpbuf : NULL, \
++ 2 * tmpbuflen); \
++ if (newp == NULL) \
++ { \
++ result = -EAI_MEMORY; \
++ goto free_and_return; \
++ } \
++ tmpbuf = newp; \
++ malloc_tmpbuf = true; \
++ tmpbuflen = 2 * tmpbuflen; \
++ } \
+ } \
+ if (status == NSS_STATUS_SUCCESS && rc == 0) \
+ h = &th; \
+@@ -209,7 +224,8 @@ gaih_inet_serv (const char *servicename, const struct gaih_typeproto *tp,
+ { \
+ __set_h_errno (herrno); \
+ _res.options = old_res_options; \
+- return -EAI_SYSTEM; \
++ result = -EAI_SYSTEM; \
++ goto free_and_return; \
+ } \
+ if (herrno == TRY_AGAIN) \
+ no_data = EAI_AGAIN; \
+
+diff --git a/manual/conf.texi b/manual/conf.texi
+index 7eb8b36..c720063 100644
+--- a/manual/conf.texi
++++ b/manual/conf.texi
+@@ -1149,6 +1149,9 @@ typed ahead as input. @xref{I/O Queues}.
+ @comment POSIX.1
+ @deftypevr Macro int NAME_MAX
+ The uniform system limit (if any) for the length of a file name component.
++
++@strong{Portability Note:} On some systems, the GNU C Library defines
++@code{NAME_MAX}, but does not actually enforce this limit.
+ @end deftypevr
+
+ @comment limits.h
+@@ -1157,6 +1160,9 @@ including the terminating null character.
+ @deftypevr Macro int PATH_MAX
+ The uniform system limit (if any) for the length of an entire file name (that
+ is, the argument given to system calls such as @code{open}).
++
++@strong{Portability Note:} The GNU C Library does not enforce this limit
++even if @code{PATH_MAX} is defined.
+ @end deftypevr
+
+ @cindex limits, pipe buffer size
+@@ -1476,6 +1482,9 @@ Inquire about the value of @code{POSIX_REC_MIN_XFER_SIZE}.
+ Inquire about the value of @code{POSIX_REC_XFER_ALIGN}.
+ @end table
+
++@strong{Portability Note:} On some systems, the GNU C Library does not
++enforce @code{_PC_NAME_MAX} or @code{_PC_PATH_MAX} limits.
++
+ @node Utility Limits
+ @section Utility Program Capacity Limits
+
+diff --git a/manual/filesys.texi b/manual/filesys.texi
+index 1df9cf2..814c210 100644
+--- a/manual/filesys.texi
++++ b/manual/filesys.texi
+@@ -444,9 +444,9 @@ symbols are declared in the header file @file{dirent.h}.
+ @comment POSIX.1
+ @deftypefun {struct dirent *} readdir (DIR *@var{dirstream})
+ This function reads the next entry from the directory. It normally
+-returns a pointer to a structure containing information about the file.
+-This structure is statically allocated and can be rewritten by a
+-subsequent call.
++returns a pointer to a structure containing information about the
++file. This structure is associated with the @var{dirstream} handle
++and can be rewritten by a subsequent call.
+
+ @strong{Portability Note:} On some systems @code{readdir} may not
+ return entries for @file{.} and @file{..}, even though these are always
+@@ -461,19 +461,61 @@ conditions are defined for this function:
+ The @var{dirstream} argument is not valid.
+ @end table
+
+-@code{readdir} is not thread safe. Multiple threads using
+-@code{readdir} on the same @var{dirstream} may overwrite the return
+-value. Use @code{readdir_r} when this is critical.
++To distinguish between an end-of-directory condition or an error, you
++must set @code{errno} to zero before calling @code{readdir}. To avoid
++entering an infinite loop, you should stop reading from the directory
++after the first error.
++
++In POSIX.1-2008, @code{readdir} is not thread-safe. In the GNU C Library
++implementation, it is safe to call @code{readdir} concurrently on
++different @var{dirstream}s, but multiple threads accessing the same
++@var{dirstream} result in undefined behavior. @code{readdir_r} is a
++fully thread-safe alternative, but suffers from poor portability (see
++below). It is recommended that you use @code{readdir}, with external
++locking if multiple threads access the same @var{dirstream}.
+ @end deftypefun
+
+ @comment dirent.h
+ @comment GNU
+ @deftypefun int readdir_r (DIR *@var{dirstream}, struct dirent *@var{entry}, struct dirent **@var{result})
+-This function is the reentrant version of @code{readdir}. Like
+-@code{readdir} it returns the next entry from the directory. But to
+-prevent conflicts between simultaneously running threads the result is
+-not stored in statically allocated memory. Instead the argument
+-@var{entry} points to a place to store the result.
++This function is a version of @code{readdir} which performs internal
++locking. Like @code{readdir} it returns the next entry from the
++directory. To prevent conflicts between simultaneously running
++threads the result is stored inside the @var{entry} object.
++
++@strong{Portability Note:} It is recommended to use @code{readdir}
++instead of @code{readdir_r} for the following reasons:
++
++@itemize @bullet
++@item
++On systems which do not define @code{NAME_MAX}, it may not be possible
++to use @code{readdir_r} safely because the caller does not specify the
++length of the buffer for the directory entry.
++
++@item
++On some systems, @code{readdir_r} cannot read directory entries with
++very long names. If such a name is encountered, the GNU C Library
++implementation of @code{readdir_r} returns with an error code of
++@code{ENAMETOOLONG} after the final directory entry has been read. On
++other systems, @code{readdir_r} may return successfully, but the
++@code{d_name} member may not be NUL-terminated or may be truncated.
++
++@item
++POSIX-1.2008 does not guarantee that @code{readdir} is thread-safe,
++even when access to the same @var{dirstream} is serialized. But in
++current implementations (including the GNU C Library), it is safe to call
++@code{readdir} concurrently on different @var{dirstream}s, so there is
++no need to use @code{readdir_r} in most multi-threaded programs. In
++the rare case that multiple threads need to read from the same
++@var{dirstream}, it is still better to use @code{readdir} and external
++synchronization.
++
++@item
++It is expected that future versions of POSIX will obsolete
++@code{readdir_r} and mandate the level of thread safety for
++@code{readdir} which is provided by the GNU C Library and other
++implementations today.
++@end itemize
+
+ Normally @code{readdir_r} returns zero and sets @code{*@var{result}}
+ to @var{entry}. If there are no more entries in the directory or an
+@@ -481,15 +523,6 @@ error is detected, @code{readdir_r} sets @code{*@var{result}} to a
+ null pointer and returns a nonzero error code, also stored in
+ @code{errno}, as described for @code{readdir}.
+
+-@strong{Portability Note:} On some systems @code{readdir_r} may not
+-return a NUL terminated string for the file name, even when there is no
+-@code{d_reclen} field in @code{struct dirent} and the file
+-name is the maximum allowed size. Modern systems all have the
+-@code{d_reclen} field, and on old systems multi-threading is not
+-critical. In any case there is no such problem with the @code{readdir}
+-function, so that even on systems without the @code{d_reclen} member one
+-could use multiple threads by using external locking.
+-
+ It is also important to look at the definition of the @code{struct
+ dirent} type. Simply passing a pointer to an object of this type for
+ the second parameter of @code{readdir_r} might not be enough. Some
+diff --git a/sysdeps/unix/dirstream.h b/sysdeps/unix/dirstream.h
+index a7a074d..8e8570d 100644
+--- a/sysdeps/unix/dirstream.h
++++ b/sysdeps/unix/dirstream.h
+@@ -39,6 +39,8 @@ struct __dirstream
+
+ off_t filepos; /* Position of next entry to read. */
+
++ int errcode; /* Delayed error code. */
++
+ /* Directory block. */
+ char data[0] __attribute__ ((aligned (__alignof__ (void*))));
+ };
+diff --git a/sysdeps/unix/opendir.c b/sysdeps/unix/opendir.c
+index ddfc3a7..fc05b0f 100644
+--- a/sysdeps/unix/opendir.c
++++ b/sysdeps/unix/opendir.c
+@@ -231,6 +231,7 @@ __alloc_dir (int fd, bool close_fd, int flags, const struct stat64 *statp)
+ dirp->size = 0;
+ dirp->offset = 0;
+ dirp->filepos = 0;
++ dirp->errcode = 0;
+
+ return dirp;
+ }
+diff --git a/sysdeps/unix/readdir_r.c b/sysdeps/unix/readdir_r.c
+index b5a8e2e..8ed5c3f 100644
+--- a/sysdeps/unix/readdir_r.c
++++ b/sysdeps/unix/readdir_r.c
+@@ -40,6 +40,7 @@ __READDIR_R (DIR *dirp, DIRENT_TYPE *entry, DIRENT_TYPE **result)
+ DIRENT_TYPE *dp;
+ size_t reclen;
+ const int saved_errno = errno;
++ int ret;
+
+ __libc_lock_lock (dirp->lock);
+
+@@ -70,10 +71,10 @@ __READDIR_R (DIR *dirp, DIRENT_TYPE *entry, DIRENT_TYPE **result)
+ bytes = 0;
+ __set_errno (saved_errno);
+ }
++ if (bytes < 0)
++ dirp->errcode = errno;
+
+ dp = NULL;
+- /* Reclen != 0 signals that an error occurred. */
+- reclen = bytes != 0;
+ break;
+ }
+ dirp->size = (size_t) bytes;
+@@ -106,28 +107,46 @@ __READDIR_R (DIR *dirp, DIRENT_TYPE *entry, DIRENT_TYPE **result)
+ dirp->filepos += reclen;
+ #endif
+
+- /* Skip deleted files. */
++#ifdef NAME_MAX
++ if (reclen > offsetof (DIRENT_TYPE, d_name) + NAME_MAX + 1)
++ {
++ /* The record is very long. It could still fit into the
++ caller-supplied buffer if we can skip padding at the
++ end. */
++ size_t namelen = _D_EXACT_NAMLEN (dp);
++ if (namelen <= NAME_MAX)
++ reclen = offsetof (DIRENT_TYPE, d_name) + namelen + 1;
++ else
++ {
++ /* The name is too long. Ignore this file. */
++ dirp->errcode = ENAMETOOLONG;
++ dp->d_ino = 0;
++ continue;
++ }
++ }
++#endif
++
++ /* Skip deleted and ignored files. */
+ }
+ while (dp->d_ino == 0);
+
+ if (dp != NULL)
+ {
+-#ifdef GETDENTS_64BIT_ALIGNED
+- /* The d_reclen value might include padding which is not part of
+- the DIRENT_TYPE data structure. */
+- reclen = MIN (reclen, sizeof (DIRENT_TYPE));
+-#endif
+ *result = memcpy (entry, dp, reclen);
+-#ifdef GETDENTS_64BIT_ALIGNED
++#ifdef _DIRENT_HAVE_D_RECLEN
+ entry->d_reclen = reclen;
+ #endif
++ ret = 0;
+ }
+ else
+- *result = NULL;
++ {
++ *result = NULL;
++ ret = dirp->errcode;
++ }
+
+ __libc_lock_unlock (dirp->lock);
+
+- return dp != NULL ? 0 : reclen ? errno : 0;
++ return ret;
+ }
+
+ #ifdef __READDIR_R_ALIAS
+diff --git a/sysdeps/unix/rewinddir.c b/sysdeps/unix/rewinddir.c
+index 2935a8e..d4991ad 100644
+--- a/sysdeps/unix/rewinddir.c
++++ b/sysdeps/unix/rewinddir.c
+@@ -33,5 +33,6 @@ rewinddir (dirp)
+ dirp->filepos = 0;
+ dirp->offset = 0;
+ dirp->size = 0;
++ dirp->errcode = 0;
+ __libc_lock_unlock (dirp->lock);
+ }
+diff --git a/sysdeps/unix/sysv/linux/i386/readdir64_r.c b/sysdeps/unix/sysv/linux/i386/readdir64_r.c
+index 8ebbcfd..a7d114e 100644
+--- a/sysdeps/unix/sysv/linux/i386/readdir64_r.c
++++ b/sysdeps/unix/sysv/linux/i386/readdir64_r.c
+@@ -18,7 +18,6 @@
+ #define __READDIR_R __readdir64_r
+ #define __GETDENTS __getdents64
+ #define DIRENT_TYPE struct dirent64
+-#define GETDENTS_64BIT_ALIGNED 1
+
+ #include <sysdeps/unix/readdir_r.c>
+
--- /dev/null
+commit 41488498b6d9440ee66ab033808cce8323bba7ac
+Author: Florian Weimer <fweimer@redhat.com>
+Date: Wed Sep 3 19:45:43 2014 +0200
+
+ CVE-2014-6040: Crashes on invalid input in IBM gconv modules [BZ #17325]
+
+ These changes are based on the fix for BZ #14134 in commit
+ 6e230d11837f3ae7b375ea69d7905f0d18eb79e5.
+
+diff --git a/iconvdata/Makefile b/iconvdata/Makefile
+index 0a410a1..b6327d6 100644
+--- a/iconvdata/Makefile
++++ b/iconvdata/Makefile
+@@ -297,6 +297,7 @@ $(objpfx)tst-iconv7.out: $(objpfx)gconv-modules \
+ $(objpfx)iconv-test.out: run-iconv-test.sh $(objpfx)gconv-modules \
+ $(addprefix $(objpfx),$(modules.so)) \
+ $(common-objdir)/iconv/iconv_prog TESTS
++ iconv_modules="$(modules)" \
+ $(SHELL) -e $< $(common-objdir) > $@
+
+ $(objpfx)tst-tables.out: tst-tables.sh $(objpfx)gconv-modules \
+diff --git a/iconvdata/ibm1364.c b/iconvdata/ibm1364.c
+index 0b5484f..cf80993 100644
+--- a/iconvdata/ibm1364.c
++++ b/iconvdata/ibm1364.c
+@@ -221,7 +221,8 @@ enum
+ ++rp2; \
+ \
+ uint32_t res; \
+- if (__builtin_expect (ch < rp2->start, 0) \
++ if (__builtin_expect (rp2->start == 0xffff, 0) \
++ || __builtin_expect (ch < rp2->start, 0) \
+ || (res = DB_TO_UCS4[ch + rp2->idx], \
+ __builtin_expect (res, L'\1') == L'\0' && ch != '\0')) \
+ { \
+diff --git a/iconvdata/ibm932.c b/iconvdata/ibm932.c
+index f5dca59..aa69d65 100644
+--- a/iconvdata/ibm932.c
++++ b/iconvdata/ibm932.c
+@@ -74,11 +74,12 @@
+ } \
+ \
+ ch = (ch * 0x100) + inptr[1]; \
++ /* ch was less than 0xfd. */ \
++ assert (ch < 0xfd00); \
+ while (ch > rp2->end) \
+ ++rp2; \
+ \
+- if (__builtin_expect (rp2 == NULL, 0) \
+- || __builtin_expect (ch < rp2->start, 0) \
++ if (__builtin_expect (ch < rp2->start, 0) \
+ || (res = __ibm932db_to_ucs4[ch + rp2->idx], \
+ __builtin_expect (res, '\1') == 0 && ch !=0)) \
+ { \
+diff --git a/iconvdata/ibm933.c b/iconvdata/ibm933.c
+index f46dfb5..461fb5e 100644
+--- a/iconvdata/ibm933.c
++++ b/iconvdata/ibm933.c
+@@ -162,7 +162,7 @@ enum
+ while (ch > rp2->end) \
+ ++rp2; \
+ \
+- if (__builtin_expect (rp2 == NULL, 0) \
++ if (__builtin_expect (rp2->start == 0xffff, 0) \
+ || __builtin_expect (ch < rp2->start, 0) \
+ || (res = __ibm933db_to_ucs4[ch + rp2->idx], \
+ __builtin_expect (res, L'\1') == L'\0' && ch != '\0')) \
+diff --git a/iconvdata/ibm935.c b/iconvdata/ibm935.c
+index a8e4e6c..132d816 100644
+--- a/iconvdata/ibm935.c
++++ b/iconvdata/ibm935.c
+@@ -162,7 +162,7 @@ enum
+ while (ch > rp2->end) \
+ ++rp2; \
+ \
+- if (__builtin_expect (rp2 == NULL, 0) \
++ if (__builtin_expect (rp2->start == 0xffff, 0) \
+ || __builtin_expect (ch < rp2->start, 0) \
+ || (res = __ibm935db_to_ucs4[ch + rp2->idx], \
+ __builtin_expect (res, L'\1') == L'\0' && ch != '\0')) \
+diff --git a/iconvdata/ibm937.c b/iconvdata/ibm937.c
+index 239be61..69b154d 100644
+--- a/iconvdata/ibm937.c
++++ b/iconvdata/ibm937.c
+@@ -162,7 +162,7 @@ enum
+ while (ch > rp2->end) \
+ ++rp2; \
+ \
+- if (__builtin_expect (rp2 == NULL, 0) \
++ if (__builtin_expect (rp2->start == 0xffff, 0) \
+ || __builtin_expect (ch < rp2->start, 0) \
+ || (res = __ibm937db_to_ucs4[ch + rp2->idx], \
+ __builtin_expect (res, L'\1') == L'\0' && ch != '\0')) \
+diff --git a/iconvdata/ibm939.c b/iconvdata/ibm939.c
+index 5d0db36..9936e2c 100644
+--- a/iconvdata/ibm939.c
++++ b/iconvdata/ibm939.c
+@@ -162,7 +162,7 @@ enum
+ while (ch > rp2->end) \
+ ++rp2; \
+ \
+- if (__builtin_expect (rp2 == NULL, 0) \
++ if (__builtin_expect (rp2->start == 0xffff, 0) \
+ || __builtin_expect (ch < rp2->start, 0) \
+ || (res = __ibm939db_to_ucs4[ch + rp2->idx], \
+ __builtin_expect (res, L'\1') == L'\0' && ch != '\0')) \
+diff --git a/iconvdata/ibm943.c b/iconvdata/ibm943.c
+index be0c14f..c5d5742 100644
+--- a/iconvdata/ibm943.c
++++ b/iconvdata/ibm943.c
+@@ -75,11 +75,12 @@
+ } \
+ \
+ ch = (ch * 0x100) + inptr[1]; \
++ /* ch was less than 0xfd. */ \
++ assert (ch < 0xfd00); \
+ while (ch > rp2->end) \
+ ++rp2; \
+ \
+- if (__builtin_expect (rp2 == NULL, 0) \
+- || __builtin_expect (ch < rp2->start, 0) \
++ if (__builtin_expect (ch < rp2->start, 0) \
+ || (res = __ibm943db_to_ucs4[ch + rp2->idx], \
+ __builtin_expect (res, '\1') == 0 && ch !=0)) \
+ { \
+diff --git a/iconvdata/run-iconv-test.sh b/iconvdata/run-iconv-test.sh
+index c98c929..5dfb69f 100755
+--- a/iconvdata/run-iconv-test.sh
++++ b/iconvdata/run-iconv-test.sh
+@@ -184,6 +184,24 @@ while read utf8 from filename; do
+
+ done < TESTS2
+
++# Check for crashes in decoders.
++printf '\016\377\377\377\377\377\377\377' > $temp1
++for from in $iconv_modules ; do
++ echo $ac_n "test decoder $from $ac_c"
++ PROG=`eval echo $ICONV`
++ if $PROG < $temp1 >/dev/null 2>&1 ; then
++ : # fall through
++ else
++ status=$?
++ if test $status -gt 1 ; then
++ echo "/FAILED"
++ failed=1
++ continue
++ fi
++ fi
++ echo "OK"
++done
++
+ exit $failed
+ # Local Variables:
+ # mode:shell-script
--- /dev/null
+#
+# This is a special patch for rhel-6 to fix recursive dlopen.
+# It is likely the upstream patch will always be too risky for
+# rhel-6 and will involve reorganizing the way in which recursive
+# dlopen is allowed to operate and how the _r_debug and stap
+# points are used by gdb for the recursive case.
+#
+# This fix changes the internal API to duplicate the ldconfig
+# cache data. This means that at any point the cache can be
+# unmapped without any consequences. The caller is responsible
+# fore freeing the returned string.
+#
+# A regression test is added to verify the assertion for _r_debug
+# is no longer triggered due to the recursive dlopen. The test to
+# verify the fix in _dl_load_cache_lookup is not automated and
+# has to be run by hand.
+#
+diff -urN glibc-2.12-2-gc4ccff1/elf/dl-cache.c glibc-2.12-2-gc4ccff1.mod/elf/dl-cache.c
+--- glibc-2.12-2-gc4ccff1/elf/dl-cache.c 2010-05-04 07:27:23.000000000 -0400
++++ glibc-2.12-2-gc4ccff1.mod/elf/dl-cache.c 2014-12-10 21:54:08.801985045 -0500
+@@ -175,9 +175,12 @@
+
+
+ /* Look up NAME in ld.so.cache and return the file name stored there,
+- or null if none is found. */
+-
+-const char *
++ or null if none is found.
++ The caller is responsible for freeing the returned string. The ld.so.cache
++ may be unmapped at any time by a completing recursive dlopen and
++ this function must take care that it does not return references to
++ any data in the mapping. */
++char *
+ internal_function
+ _dl_load_cache_lookup (const char *name)
+ {
+@@ -290,7 +293,17 @@
+ && best != NULL)
+ _dl_debug_printf (" trying file=%s\n", best);
+
+- return best;
++ if (best == NULL)
++ return NULL;
++
++ /* The double copy is *required* since malloc may be interposed
++ and call dlopen itself whose completion would unmap the data
++ we are accessing. Therefore we must make the copy of the
++ mapping data without using malloc. */
++ char *temp;
++ temp = alloca (strlen (best) + 1);
++ strcpy (temp, best);
++ return strdup (temp);
+ }
+
+ #ifndef MAP_COPY
+diff -urN glibc-2.12-2-gc4ccff1/elf/dl-load.c glibc-2.12-2-gc4ccff1.mod/elf/dl-load.c
+--- glibc-2.12-2-gc4ccff1/elf/dl-load.c 2014-12-10 11:03:17.966048404 -0500
++++ glibc-2.12-2-gc4ccff1.mod/elf/dl-load.c 2014-12-10 21:47:29.319387538 -0500
+@@ -2126,7 +2126,7 @@
+ {
+ /* Check the list of libraries in the file /etc/ld.so.cache,
+ for compatibility with Linux's ldconfig program. */
+- const char *cached = _dl_load_cache_lookup (name);
++ char *cached = _dl_load_cache_lookup (name);
+
+ if (cached != NULL)
+ {
+@@ -2156,6 +2156,7 @@
+ if (memcmp (cached, dirp, system_dirs_len[cnt]) == 0)
+ {
+ /* The prefix matches. Don't use the entry. */
++ free (cached);
+ cached = NULL;
+ break;
+ }
+@@ -2172,14 +2173,9 @@
+ &fb, loader ?: GL(dl_ns)[nsid]._ns_loaded,
+ LA_SER_CONFIG, &found_other_class, false);
+ if (__builtin_expect (fd != -1, 1))
+- {
+- realname = local_strdup (cached);
+- if (realname == NULL)
+- {
+- __close (fd);
+- fd = -1;
+- }
+- }
++ realname = cached;
++ else
++ free (cached);
+ }
+ }
+ }
+diff -urN glibc-2.12-2-gc4ccff1/elf/dl-open.c glibc-2.12-2-gc4ccff1.mod/elf/dl-open.c
+--- glibc-2.12-2-gc4ccff1/elf/dl-open.c 2014-12-10 11:03:18.083048497 -0500
++++ glibc-2.12-2-gc4ccff1.mod/elf/dl-open.c 2014-12-10 20:34:16.017503638 -0500
+@@ -220,7 +220,11 @@
+ }
+ }
+
+- assert (_dl_debug_initialize (0, args->nsid)->r_state == RT_CONSISTENT);
++ /* One might be tempted to assert that we are RT_CONSISTENT at this point, but that
++ may not be true if this is a recursive call to dlopen.
++ TODO: Fix all of the debug state so we end up at RT_CONSISTENT only when the last
++ recursive dlopen completes. */
++ _dl_debug_initialize (0, args->nsid);
+
+ /* Load the named object. */
+ struct link_map *new;
+diff -urN glibc-2.12-2-gc4ccff1/sysdeps/generic/ldsodefs.h glibc-2.12-2-gc4ccff1.mod/sysdeps/generic/ldsodefs.h
+--- glibc-2.12-2-gc4ccff1/sysdeps/generic/ldsodefs.h 2014-12-10 11:03:17.944048387 -0500
++++ glibc-2.12-2-gc4ccff1.mod/sysdeps/generic/ldsodefs.h 2014-12-10 21:46:14.071344018 -0500
+@@ -996,8 +996,8 @@
+ internal_function;
+
+ /* Look up NAME in ld.so.cache and return the file name stored there,
+- or null if none is found. */
+-extern const char *_dl_load_cache_lookup (const char *name)
++ or null if none is found. Caller must free returned string. */
++extern char *_dl_load_cache_lookup (const char *name)
+ internal_function;
+
+ /* If the system does not support MAP_COPY we cannot leave the file open
+diff -urN glibc-2.12-2-gc4ccff1/dlfcn/Makefile glibc-2.12-2-gc4ccff1.mod/dlfcn/Makefile
+--- glibc-2.12-2-gc4ccff1/dlfcn/Makefile 2010-05-04 07:27:23.000000000 -0400
++++ glibc-2.12-2-gc4ccff1.mod/dlfcn/Makefile 2014-12-11 16:58:55.719803063 -0500
+@@ -42,12 +42,12 @@
+ ifeq (yes,$(build-shared))
+ tests = glrefmain failtest tst-dladdr default errmsg1 tstcxaatexit \
+ bug-dlopen1 bug-dlsym1 tst-dlinfo bug-atexit1 bug-atexit2 \
+- bug-atexit3 tstatexit
++ bug-atexit3 tstatexit tst-rec-dlopen
+ endif
+ modules-names = glreflib1 glreflib2 glreflib3 failtestmod defaultmod1 \
+ defaultmod2 errmsg1mod modatexit modcxaatexit \
+ bug-dlsym1-lib1 bug-dlsym1-lib2 bug-atexit1-lib \
+- bug-atexit2-lib bug-atexit3-lib
++ bug-atexit2-lib bug-atexit3-lib moddummy1 moddummy2
+
+ failtestmod.so-no-z-defs = yes
+ glreflib2.so-no-z-defs = yes
+@@ -142,6 +142,8 @@
+ $(objpfx)bug-atexit3-lib.so: $(common-objpfx)libc.so \
+ $(common-objpfx)libc_nonshared.a
+
++LDLIBS-tst-rec-dlopen = -ldl
++$(objpfx)tst-rec-dlopen: $(libdl)
+
+ # Depend on libc.so so a DT_NEEDED is generated in the shared objects.
+ # This ensures they will load libc.so for needed symbols if loaded by
+diff -urN glibc-2.12-2-gc4ccff1/dlfcn/moddummy1.c glibc-2.12-2-gc4ccff1.mod/dlfcn/moddummy1.c
+--- glibc-2.12-2-gc4ccff1/dlfcn/moddummy1.c 1969-12-31 19:00:00.000000000 -0500
++++ glibc-2.12-2-gc4ccff1.mod/dlfcn/moddummy1.c 2014-12-11 16:57:54.108797285 -0500
+@@ -0,0 +1,13 @@
++/* Provide a dummy DSO for tst-recursive-dlopen to use. */
++#include <stdio.h>
++#include <stdlib.h>
++
++int called_dummy1;
++
++void
++dummy1 (void)
++{
++ printf ("Called dummy1()\n");
++ called_dummy1++;
++}
++
+diff -urN glibc-2.12-2-gc4ccff1/dlfcn/moddummy2.c glibc-2.12-2-gc4ccff1.mod/dlfcn/moddummy2.c
+--- glibc-2.12-2-gc4ccff1/dlfcn/moddummy2.c 1969-12-31 19:00:00.000000000 -0500
++++ glibc-2.12-2-gc4ccff1.mod/dlfcn/moddummy2.c 2014-12-11 16:57:54.108797285 -0500
+@@ -0,0 +1,13 @@
++/* Provide a dummy DSO for tst-recursive-dlopen to use. */
++#include <stdio.h>
++#include <stdlib.h>
++
++int called_dummy2;
++
++void
++dummy2 (void)
++{
++ printf ("Called dummy2()\n");
++ called_dummy2++;
++}
++
+diff -urN glibc-2.12-2-gc4ccff1/dlfcn/tst-rec-dlopen.c glibc-2.12-2-gc4ccff1.mod/dlfcn/tst-rec-dlopen.c
+--- glibc-2.12-2-gc4ccff1/dlfcn/tst-rec-dlopen.c 1969-12-31 19:00:00.000000000 -0500
++++ glibc-2.12-2-gc4ccff1.mod/dlfcn/tst-rec-dlopen.c 2014-12-11 20:53:28.617848774 -0500
+@@ -0,0 +1,145 @@
++/* Test recursive dlopen using malloc hooks.
++ Copyright (C) 1998-2014 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++ Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
++
++ 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 <stdio.h>
++#include <stdlib.h>
++#include <malloc.h>
++#include <dlfcn.h>
++
++#define DSO "moddummy1.so"
++#define FUNC "dummy1"
++
++#define DSO1 "moddummy2.so"
++#define FUNC1 "dummy2"
++
++/* Prevent the compiler from moving the assignment to called_func
++ before (*func)() since the compiler doesn't know we might abort
++ or catch a SIGSEGV signal and it may move the store. */
++volatile int called_func;
++
++/* Prototype for my hook. */
++void *custom_malloc_hook (size_t, const void *);
++
++/* Pointer to old malloc hooks. */
++void *(*old_malloc_hook) (size_t, const void *);
++
++/* Call function func_name in DSO dso_name via dlopen. */
++void
++call_func (const char *dso_name, const char *func_name)
++{
++ int ret;
++ void *dso;
++ void (*func) (void);
++ char *err;
++
++ /* Open the DSO. */
++ dso = dlopen (dso_name, RTLD_NOW|RTLD_GLOBAL);
++ if (dso == NULL)
++ {
++ err = dlerror ();
++ fprintf (stderr, "%s\n", err);
++ exit (1);
++ }
++ /* Clear any errors. */
++ dlerror ();
++
++ /* Lookup func. */
++ *(void **) (&func) = dlsym (dso, func_name);
++ if (func == NULL)
++ {
++ err = dlerror ();
++ if (err != NULL)
++ {
++ fprintf (stderr, "%s\n", err);
++ exit (1);
++ }
++ }
++ /* Call func. */
++ (*func) ();
++ called_func = 1;
++
++ /* Close the library and look for errors too. */
++ ret = dlclose (dso);
++ if (ret != 0)
++ {
++ err = dlerror ();
++ fprintf (stderr, "%s\n", err);
++ exit (1);
++ }
++
++}
++
++/* Empty hook that does nothing. */
++void *
++custom_malloc_hook (size_t size, const void *caller)
++{
++ void *result;
++ /* Restore old hooks. */
++ __malloc_hook = old_malloc_hook;
++ /* First call a function in another library via dlopen. */
++ call_func (DSO1, FUNC1);
++ /* Called recursively. */
++ result = malloc (size);
++ /* Restore new hooks. */
++ __malloc_hook = custom_malloc_hook;
++ return result;
++}
++
++static int
++do_test (void)
++{
++ /* Save old hook. */
++ old_malloc_hook = __malloc_hook;
++ /* Install new hook. */
++ __malloc_hook = custom_malloc_hook;
++
++ /* Bug 17702 fixes two things:
++ * A recursive dlopen unmapping the ld.so.cache.
++ * An assertion that _r_debug is RT_CONSISTENT at entry to dlopen.
++ We can only test the latter. Testing the former requires modifying
++ ld.so.conf to cache the dummy libraries, then running ldconfig,
++ then run the test. If you do all of that (and glibc's test
++ infrastructure doesn't support that yet) then the test will
++ SEGFAULT without the fix. If you don't do that, then the test
++ will abort because of the assert described in detail below. */
++ call_func (DSO, FUNC);
++
++ /* Restore old hook. */
++ __malloc_hook = old_malloc_hook;
++
++ /* The function dummy2() is called by the malloc hook. Check to
++ see that it was called. This ensures the second recursive
++ dlopen happened and we called the function in that library.
++
++ Before the fix you either get a SIGSEGV when accessing mmap'd
++ ld.so.cache data or an assertion failure about _r_debug not
++ beint RT_CONSISTENT. We don't test for the SIGSEGV since it
++ would require finding moddummy1 or moddummy2 in the cache and
++ we don't have any infrastructure to test that, but the _r_debug
++ assertion triggers. */
++ if (called_func > 0)
++ printf ("PASS: Function call_func() called more than once.\n");
++ else
++ printf ("FAIL: Function call_func() not called.\n");
++
++ return 0;
++}
++
++#define TEST_FUNCTION do_test ()
++#include "../test-skeleton.c"
--- /dev/null
+#
+# commit a39208bd7fb76c1b01c127b4c61f9bfd915bfe7c
+# Author: Carlos O'Donell <carlos@redhat.com>
+# Date: Wed Nov 19 11:44:12 2014 -0500
+#
+# CVE-2014-7817: wordexp fails to honour WRDE_NOCMD.
+#
+# The function wordexp() fails to properly handle the WRDE_NOCMD
+# flag when processing arithmetic inputs in the form of "$((... ``))"
+# where "..." can be anything valid. The backticks in the arithmetic
+# epxression are evaluated by in a shell even if WRDE_NOCMD forbade
+# command substitution. This allows an attacker to attempt to pass
+# dangerous commands via constructs of the above form, and bypass
+# the WRDE_NOCMD flag. This patch fixes this by checking for WRDE_NOCMD
+# in exec_comm(), the only place that can execute a shell. All other
+# checks for WRDE_NOCMD are superfluous and removed.
+#
+# We expand the testsuite and add 3 new regression tests of roughly
+# the same form but with a couple of nested levels.
+#
+# On top of the 3 new tests we add fork validation to the WRDE_NOCMD
+# testing. If any forks are detected during the execution of a wordexp()
+# call with WRDE_NOCMD, the test is marked as failed. This is slightly
+# heuristic since vfork might be used in the future, but it provides a
+# higher level of assurance that no shells were executed as part of
+# command substitution with WRDE_NOCMD in effect. In addition it doesn't
+# require libpthread or libdl, instead we use the public implementation
+# namespace function __register_atfork (already part of the public ABI
+# for libpthread).
+#
+# Tested on x86_64 with no regressions.
+#
+diff --git a/posix/wordexp-test.c b/posix/wordexp-test.c
+index 4957006..bdd65e4 100644
+--- a/posix/wordexp-test.c
++++ b/posix/wordexp-test.c
+@@ -27,6 +27,25 @@
+
+ #define IFS " \n\t"
+
++extern void *__dso_handle __attribute__ ((__weak__, __visibility__ ("hidden")));
++extern int __register_atfork (void (*) (void), void (*) (void), void (*) (void), void *);
++
++static int __app_register_atfork (void (*prepare) (void), void (*parent) (void), void (*child) (void))
++{
++ return __register_atfork (prepare, parent, child,
++ &__dso_handle == NULL ? NULL : __dso_handle);
++}
++
++/* Number of forks seen. */
++static int registered_forks;
++
++/* For each fork increment the fork count. */
++static void
++register_fork (void)
++{
++ registered_forks++;
++}
++
+ struct test_case_struct
+ {
+ int retval;
+@@ -206,6 +225,12 @@ struct test_case_struct
+ { WRDE_SYNTAX, NULL, "$((2+))", 0, 0, { NULL, }, IFS },
+ { WRDE_SYNTAX, NULL, "`", 0, 0, { NULL, }, IFS },
+ { WRDE_SYNTAX, NULL, "$((010+4+))", 0, 0, { NULL }, IFS },
++ /* Test for CVE-2014-7817. We test 3 combinations of command
++ substitution inside an arithmetic expression to make sure that
++ no commands are executed and error is returned. */
++ { WRDE_CMDSUB, NULL, "$((`echo 1`))", WRDE_NOCMD, 0, { NULL, }, IFS },
++ { WRDE_CMDSUB, NULL, "$((1+`echo 1`))", WRDE_NOCMD, 0, { NULL, }, IFS },
++ { WRDE_CMDSUB, NULL, "$((1+$((`echo 1`))))", WRDE_NOCMD, 0, { NULL, }, IFS },
+
+ { -1, NULL, NULL, 0, 0, { NULL, }, IFS },
+ };
+@@ -258,6 +283,15 @@ main (int argc, char *argv[])
+ return -1;
+ }
+
++ /* If we are not allowed to do command substitution, we install
++ fork handlers to verify that no forks happened. No forks should
++ happen at all if command substitution is disabled. */
++ if (__app_register_atfork (register_fork, NULL, NULL) != 0)
++ {
++ printf ("Failed to register fork handler.\n");
++ return -1;
++ }
++
+ for (test = 0; test_case[test].retval != -1; test++)
+ if (testit (&test_case[test]))
+ ++fail;
+@@ -367,6 +401,9 @@ testit (struct test_case_struct *tc)
+
+ printf ("Test %d (%s): ", ++tests, tc->words);
+
++ if (tc->flags & WRDE_NOCMD)
++ registered_forks = 0;
++
+ if (tc->flags & WRDE_APPEND)
+ {
+ /* initial wordexp() call, to be appended to */
+@@ -378,6 +415,13 @@ testit (struct test_case_struct *tc)
+ }
+ retval = wordexp (tc->words, &we, tc->flags);
+
++ if ((tc->flags & WRDE_NOCMD)
++ && (registered_forks > 0))
++ {
++ printf ("FAILED fork called for WRDE_NOCMD\n");
++ return 1;
++ }
++
+ if (tc->flags & WRDE_DOOFFS)
+ start_offs = sav_we.we_offs;
+
+diff --git a/posix/wordexp.c b/posix/wordexp.c
+index b6b65dd..26f3a26 100644
+--- a/posix/wordexp.c
++++ b/posix/wordexp.c
+@@ -893,6 +893,10 @@ exec_comm (char *comm, char **word, size_t *word_length, size_t *max_length,
+ pid_t pid;
+ int noexec = 0;
+
++ /* Do nothing if command substitution should not succeed. */
++ if (flags & WRDE_NOCMD)
++ return WRDE_CMDSUB;
++
+ /* Don't fork() unless necessary */
+ if (!comm || !*comm)
+ return 0;
+@@ -2082,9 +2086,6 @@ parse_dollars (char **word, size_t *word_length, size_t *max_length,
+ }
+ }
+
+- if (flags & WRDE_NOCMD)
+- return WRDE_CMDSUB;
+-
+ (*offset) += 2;
+ return parse_comm (word, word_length, max_length, words, offset, flags,
+ quoted? NULL : pwordexp, ifs, ifs_white);
+@@ -2196,9 +2197,6 @@ parse_dquote (char **word, size_t *word_length, size_t *max_length,
+ break;
+
+ case '`':
+- if (flags & WRDE_NOCMD)
+- return WRDE_CMDSUB;
+-
+ ++(*offset);
+ error = parse_backtick (word, word_length, max_length, words,
+ offset, flags, NULL, NULL, NULL);
+@@ -2357,12 +2355,6 @@ wordexp (const char *words, wordexp_t *pwordexp, int flags)
+ break;
+
+ case '`':
+- if (flags & WRDE_NOCMD)
+- {
+- error = WRDE_CMDSUB;
+- goto do_error;
+- }
+-
+ ++words_offset;
+ error = parse_backtick (&word, &word_length, &max_length, words,
+ &words_offset, flags, pwordexp, ifs,
--- /dev/null
+commit d5dd6189d506068ed11c8bfa1e1e9bffde04decd
+Author: Andreas Schwab <schwab@suse.de>
+Date: Mon Jan 21 17:41:28 2013 +0100
+
+ Fix parsing of numeric hosts in gethostbyname_r
+
+diff --git a/nss/digits_dots.c b/nss/digits_dots.c
+index 2b86295..e007ef4 100644
+--- a/nss/digits_dots.c
++++ b/nss/digits_dots.c
+@@ -46,7 +46,10 @@ __nss_hostname_digits_dots (const char *name, struct hostent *resbuf,
+ {
+ if (h_errnop)
+ *h_errnop = NETDB_INTERNAL;
+- *result = NULL;
++ if (buffer_size == NULL)
++ *status = NSS_STATUS_TRYAGAIN;
++ else
++ *result = NULL;
+ return -1;
+ }
+
+@@ -83,14 +86,16 @@ __nss_hostname_digits_dots (const char *name, struct hostent *resbuf,
+ }
+
+ size_needed = (sizeof (*host_addr)
+- + sizeof (*h_addr_ptrs) + strlen (name) + 1);
++ + sizeof (*h_addr_ptrs)
++ + sizeof (*h_alias_ptr) + strlen (name) + 1);
+
+ if (buffer_size == NULL)
+ {
+ if (buflen < size_needed)
+ {
++ *status = NSS_STATUS_TRYAGAIN;
+ if (h_errnop != NULL)
+- *h_errnop = TRY_AGAIN;
++ *h_errnop = NETDB_INTERNAL;
+ __set_errno (ERANGE);
+ goto done;
+ }
+@@ -109,7 +114,7 @@ __nss_hostname_digits_dots (const char *name, struct hostent *resbuf,
+ *buffer_size = 0;
+ __set_errno (save);
+ if (h_errnop != NULL)
+- *h_errnop = TRY_AGAIN;
++ *h_errnop = NETDB_INTERNAL;
+ *result = NULL;
+ goto done;
+ }
+@@ -149,7 +154,9 @@ __nss_hostname_digits_dots (const char *name, struct hostent *resbuf,
+ if (! ok)
+ {
+ *h_errnop = HOST_NOT_FOUND;
+- if (buffer_size)
++ if (buffer_size == NULL)
++ *status = NSS_STATUS_NOTFOUND;
++ else
+ *result = NULL;
+ goto done;
+ }
+@@ -190,7 +197,7 @@ __nss_hostname_digits_dots (const char *name, struct hostent *resbuf,
+ if (buffer_size == NULL)
+ *status = NSS_STATUS_SUCCESS;
+ else
+- *result = resbuf;
++ *result = resbuf;
+ goto done;
+ }
+
+@@ -201,15 +208,6 @@ __nss_hostname_digits_dots (const char *name, struct hostent *resbuf,
+
+ if ((isxdigit (name[0]) && strchr (name, ':') != NULL) || name[0] == ':')
+ {
+- const char *cp;
+- char *hostname;
+- typedef unsigned char host_addr_t[16];
+- host_addr_t *host_addr;
+- typedef char *host_addr_list_t[2];
+- host_addr_list_t *h_addr_ptrs;
+- size_t size_needed;
+- int addr_size;
+-
+ switch (af)
+ {
+ default:
+@@ -225,7 +223,10 @@ __nss_hostname_digits_dots (const char *name, struct hostent *resbuf,
+ /* This is not possible. We cannot represent an IPv6 address
+ in an `struct in_addr' variable. */
+ *h_errnop = HOST_NOT_FOUND;
+- *result = NULL;
++ if (buffer_size == NULL)
++ *status = NSS_STATUS_NOTFOUND;
++ else
++ *result = NULL;
+ goto done;
+
+ case AF_INET6:
+@@ -233,42 +234,6 @@ __nss_hostname_digits_dots (const char *name, struct hostent *resbuf,
+ break;
+ }
+
+- size_needed = (sizeof (*host_addr)
+- + sizeof (*h_addr_ptrs) + strlen (name) + 1);
+-
+- if (buffer_size == NULL && buflen < size_needed)
+- {
+- if (h_errnop != NULL)
+- *h_errnop = TRY_AGAIN;
+- __set_errno (ERANGE);
+- goto done;
+- }
+- else if (buffer_size != NULL && *buffer_size < size_needed)
+- {
+- char *new_buf;
+- *buffer_size = size_needed;
+- new_buf = realloc (*buffer, *buffer_size);
+-
+- if (new_buf == NULL)
+- {
+- save = errno;
+- free (*buffer);
+- __set_errno (save);
+- *buffer = NULL;
+- *buffer_size = 0;
+- *result = NULL;
+- goto done;
+- }
+- *buffer = new_buf;
+- }
+-
+- memset (*buffer, '\0', size_needed);
+-
+- host_addr = (host_addr_t *) *buffer;
+- h_addr_ptrs = (host_addr_list_t *)
+- ((char *) host_addr + sizeof (*host_addr));
+- hostname = (char *) h_addr_ptrs + sizeof (*h_addr_ptrs);
+-
+ for (cp = name;; ++cp)
+ {
+ if (!*cp)
+@@ -281,7 +246,9 @@ __nss_hostname_digits_dots (const char *name, struct hostent *resbuf,
+ if (inet_pton (AF_INET6, name, host_addr) <= 0)
+ {
+ *h_errnop = HOST_NOT_FOUND;
+- if (buffer_size)
++ if (buffer_size == NULL)
++ *status = NSS_STATUS_NOTFOUND;
++ else
+ *result = NULL;
+ goto done;
+ }
+diff --git a/nss/getXXbyYY_r.c b/nss/getXXbyYY_r.c
+index 1067744..44d00f4 100644
+--- a/nss/getXXbyYY_r.c
++++ b/nss/getXXbyYY_r.c
+@@ -179,6 +179,9 @@ INTERNAL (REENTRANT_NAME) (ADD_PARAMS, LOOKUP_TYPE *resbuf, char *buffer,
+ case -1:
+ return errno;
+ case 1:
++#ifdef NEED_H_ERRNO
++ any_service = true;
++#endif
+ goto done;
+ }
+ #endif
+diff --git a/nss/test-digits-dots.c b/nss/test-digits-dots.c
+new file mode 100644
+index 0000000..1efa344
+--- /dev/null
++++ b/nss/test-digits-dots.c
+@@ -0,0 +1,38 @@
++/* Copyright (C) 2013 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/>. */
++
++/* Testcase for BZ #15014 */
++
++#include <stdlib.h>
++#include <netdb.h>
++#include <errno.h>
++
++static int
++do_test (void)
++{
++ char buf[32];
++ struct hostent *result = NULL;
++ struct hostent ret;
++ int h_err = 0;
++ int err;
++
++ err = gethostbyname_r ("1.2.3.4", &ret, buf, sizeof (buf), &result, &h_err);
++ return err == ERANGE && h_err == NETDB_INTERNAL ? EXIT_SUCCESS : EXIT_FAILURE;
++}
++
++#define TEST_FUNCTION do_test ()
++#include "../test-skeleton.c"
--- /dev/null
+commit d26dfc60edc8c6dd160eefff16a734152a835ca0
+Author: Martin von Gagern <Martin.vGagern@gmx.net>
+Date: Sat May 14 21:25:43 2011 -0400
+
+ Fix handling of static TLS in dlopen'ed objects
+
+ When dynamically loading a library along with several dependencies, calls to
+ _dl_add_to_slotinfo and _dl_update_slotinfo can become intermixed. As a
+ consequence, _dl_update_slotinfo will update the generation counter of the dtv
+ although not all of the slots belonging to that generation have been added.
+ Subsequent calls to _dl_add_to_slotinfo will add more slots to the same
+ generation, for which no storage will be allocated, as the dtv generation
+ checks will claim no work is necessary. This will lead to uninitialized dtv
+ entries and will likely cause a SIGSEGV when thread local variables are
+ accessed.
+
+diff --git a/elf/Makefile b/elf/Makefile
+index 8d9657d..6efb86c 100644
+--- a/elf/Makefile
++++ b/elf/Makefile
+@@ -76,6 +76,7 @@ distribute := rtld-Rules \
+ tst-tlsmod12.c tst-tls10.h tst-alignmod.c tst-alignmod2.c \
+ circlemod1.c circlemod1a.c circlemod2.c circlemod2a.c \
+ circlemod3.c circlemod3a.c nodlopenmod2.c \
++ tst-tls19mod1.c tst-tls19mod2.c tst-tls19mod3.c \
+ tls-macros.h \
+ reldep8mod1.c reldep8mod2.c reldep8mod3.c \
+ nodel2mod1.c nodel2mod2.c nodel2mod3.c \
+@@ -194,7 +195,7 @@ tests += loadtest restest1 preloadtest loadfail multiload origtest resolvfail \
+ restest2 next dblload dblunload reldep5 reldep6 reldep7 reldep8 \
+ circleload1 tst-tls3 tst-tls4 tst-tls5 tst-tls6 tst-tls7 tst-tls8 \
+ tst-tls10 tst-tls11 tst-tls12 tst-tls13 tst-tls14 tst-tls15 \
+- tst-tls16 tst-tls17 tst-tls18 tst-tls-dlinfo \
++ tst-tls16 tst-tls17 tst-tls18 tst-tls19 tst-tls-dlinfo \
+ tst-align tst-align2 $(tests-execstack-$(have-z-execstack)) \
+ tst-dlmodcount tst-dlopenrpath tst-deep1 \
+ tst-dlmopen1 tst-dlmopen2 tst-dlmopen3 \
+@@ -240,6 +241,7 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
+ $(patsubst %,tst-tlsmod17a%,$(tlsmod17a-suffixes)) \
+ tst-tlsmod17b \
+ $(patsubst %,tst-tlsmod18a%,$(tlsmod18a-suffixes)) \
++ tst-tls19mod1 tst-tls19mod2 tst-tls19mod3 \
+ circlemod1 circlemod1a circlemod2 circlemod2a \
+ circlemod3 circlemod3a \
+ reldep8mod1 reldep8mod2 reldep8mod3 \
+@@ -525,6 +527,8 @@ $(objpfx)tst-tlsmod13a.so: $(objpfx)tst-tlsmod13.so
+ # For tst-tls9-static, make sure the modules it dlopens have libc.so in DT_NEEDED
+ $(objpfx)tst-tlsmod5.so: $(common-objpfx)libc.so
+ $(objpfx)tst-tlsmod6.so: $(common-objpfx)libc.so
++$(objpfx)tst-tls19mod1.so: $(objpfx)tst-tls19mod2.so $(objpfx)tst-tls19mod3.so
++$(objpfx)tst-tls19mod3.so: $(objpfx)ld.so
+ $(objpfx)reldep8mod3.so: $(objpfx)reldep8mod1.so $(objpfx)reldep8mod2.so
+ $(objpfx)nodel2mod3.so: $(objpfx)nodel2mod1.so $(objpfx)nodel2mod2.so
+ $(objpfx)reldep9mod2.so: $(objpfx)reldep9mod1.so
+@@ -822,6 +826,9 @@ $(patsubst %,$(objpfx)%.os,$(tlsmod18a-modules)): $(objpfx)tst-tlsmod18a%.os : t
+ $(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ -DN=$* -DNOT_IN_libc=1 $<
+ $(patsubst %,$(objpfx)tst-tlsmod18a%.so,$(tlsmod18a-suffixes)): $(objpfx)tst-tlsmod18a%.so: $(objpfx)ld.so
+
++$(objpfx)tst-tls19: $(libdl)
++$(objpfx)tst-tls19.out: $(objpfx)tst-tls19mod1.so
++
+ CFLAGS-tst-align.c = $(stack-align-test-flags)
+ CFLAGS-tst-align2.c = $(stack-align-test-flags)
+ CFLAGS-tst-alignmod.c = $(stack-align-test-flags)
+diff --git a/elf/dl-open.c b/elf/dl-open.c
+index cf8e8cc..8d90b56 100644
+--- a/elf/dl-open.c
++++ b/elf/dl-open.c
+@@ -347,6 +347,7 @@ dl_open_worker (void *a)
+ /* If the file is not loaded now as a dependency, add the search
+ list of the newly loaded object to the scope. */
+ bool any_tls = false;
++ unsigned int first_static_tls = new->l_searchlist.r_nlist;
+ for (unsigned int i = 0; i < new->l_searchlist.r_nlist; ++i)
+ {
+ struct link_map *imap = new->l_searchlist.r_list[i];
+@@ -425,30 +426,9 @@ dl_open_worker (void *a)
+ might have to increase its size. */
+ _dl_add_to_slotinfo (imap);
+
+- if (imap->l_need_tls_init)
+- {
+- /* For static TLS we have to allocate the memory here
+- and now. This includes allocating memory in the DTV.
+- But we cannot change any DTV other than our own. So,
+- if we cannot guarantee that there is room in the DTV
+- we don't even try it and fail the load.
+-
+- XXX We could track the minimum DTV slots allocated in
+- all threads. */
+- if (! RTLD_SINGLE_THREAD_P && imap->l_tls_modid > DTV_SURPLUS)
+- _dl_signal_error (0, "dlopen", NULL, N_("\
+-cannot load any more object with static TLS"));
+-
+- imap->l_need_tls_init = 0;
+-#ifdef SHARED
+- /* Update the slot information data for at least the
+- generation of the DSO we are allocating data for. */
+- _dl_update_slotinfo (imap->l_tls_modid);
+-#endif
+-
+- GL(dl_init_static_tls) (imap);
+- assert (imap->l_need_tls_init == 0);
+- }
++ if (imap->l_need_tls_init
++ && first_static_tls == new->l_searchlist.r_nlist)
++ first_static_tls = i;
+
+ /* We have to bump the generation counter. */
+ any_tls = true;
+@@ -460,6 +440,40 @@ cannot load any more object with static TLS"));
+ _dl_fatal_printf (N_("\
+ TLS generation counter wrapped! Please report this."));
+
++ /* We need a second pass for static tls data, because _dl_update_slotinfo
++ must not be run while calls to _dl_add_to_slotinfo are still pending. */
++ for (unsigned int i = first_static_tls; i < new->l_searchlist.r_nlist; ++i)
++ {
++ struct link_map *imap = new->l_searchlist.r_list[i];
++
++ if (imap->l_need_tls_init
++ && ! imap->l_init_called
++ && imap->l_tls_blocksize > 0)
++ {
++ /* For static TLS we have to allocate the memory here and
++ now. This includes allocating memory in the DTV. But we
++ cannot change any DTV other than our own. So, if we
++ cannot guarantee that there is room in the DTV we don't
++ even try it and fail the load.
++
++ XXX We could track the minimum DTV slots allocated in
++ all threads. */
++ if (! RTLD_SINGLE_THREAD_P && imap->l_tls_modid > DTV_SURPLUS)
++ _dl_signal_error (0, "dlopen", NULL, N_("\
++cannot load any more object with static TLS"));
++
++ imap->l_need_tls_init = 0;
++#ifdef SHARED
++ /* Update the slot information data for at least the
++ generation of the DSO we are allocating data for. */
++ _dl_update_slotinfo (imap->l_tls_modid);
++#endif
++
++ GL(dl_init_static_tls) (imap);
++ assert (imap->l_need_tls_init == 0);
++ }
++ }
++
+ /* Notify the debugger all new objects have been relocated. */
+ if (relocation_in_progress)
+ LIBC_PROBE (rtld_reloc_complete, 3, args->nsid, r, new);
+diff --git a/elf/tst-tls19.c b/elf/tst-tls19.c
+new file mode 100644
+index 0000000..acbc1d6
+--- /dev/null
++++ b/elf/tst-tls19.c
+@@ -0,0 +1,27 @@
++// BZ 12453
++#include <stdio.h>
++#include <dlfcn.h>
++
++
++static int
++do_test (void)
++{
++ void* dl = dlopen ("tst-tls19mod1.so", RTLD_LAZY | RTLD_GLOBAL);
++ if (dl == NULL)
++ {
++ printf ("Error loading tst-tls19mod1.so: %s\n", dlerror ());
++ return 1;
++ }
++
++ int (*fn) (void) = dlsym (dl, "foo");
++ if (fn == NULL)
++ {
++ printf("Error obtaining symbol foo\n");
++ return 1;
++ }
++
++ return fn ();
++}
++
++#define TEST_FUNCTION do_test ()
++#include "../test-skeleton.c"
+diff --git a/elf/tst-tls19mod1.c b/elf/tst-tls19mod1.c
+new file mode 100644
+index 0000000..2790097
+--- /dev/null
++++ b/elf/tst-tls19mod1.c
+@@ -0,0 +1,15 @@
++#include <stdio.h>
++
++extern int bar (void);
++extern int baz (void);
++
++int
++foo (void)
++{
++ int v1 = bar ();
++ int v2 = baz ();
++
++ printf ("bar=%d, baz=%d\n", v1, v2);
++
++ return v1 != 666 || v2 != 42;
++}
+diff --git a/elf/tst-tls19mod2.c b/elf/tst-tls19mod2.c
+new file mode 100644
+index 0000000..cae702f
+--- /dev/null
++++ b/elf/tst-tls19mod2.c
+@@ -0,0 +1,13 @@
++static int __thread tbar __attribute__ ((tls_model ("initial-exec"))) = 666;
++
++void
++setter (int a)
++{
++ tbar = a;
++}
++
++int
++bar (void)
++{
++ return tbar;
++}
+diff --git a/elf/tst-tls19mod3.c b/elf/tst-tls19mod3.c
+new file mode 100644
+index 0000000..e7b2801
+--- /dev/null
++++ b/elf/tst-tls19mod3.c
+@@ -0,0 +1,16 @@
++#include <stdio.h>
++
++static int __thread tbaz __attribute__ ((tls_model ("local-dynamic"))) = 42;
++
++void
++setter2 (int a)
++{
++ tbaz = a;
++}
++
++int
++baz (void)
++{
++ printf ("&tbaz=%p\n", &tbaz);
++ return tbaz;
++}