diff --git a/build-locale-archive.c b/build-locale-archive.c index fde71d6..6d695a8 100644 --- a/build-locale-archive.c +++ b/build-locale-archive.c @@ -8,19 +8,21 @@ #include #include #include +#include #include #include #include #include -#include "locale/hashval.h" +#include "./locale/hashval.h" #define __LC_LAST 13 -#include "locale/locarchive.h" -#include "crypt/md5.h" +#include "./locale/locarchive.h" +#include "./crypt/md5.h" const char *alias_file = DATADIR "/locale/locale.alias"; const char *locar_file = PREFIX "/lib/locale/locale-archive"; const char *tmpl_file = PREFIX "/lib/locale/locale-archive.tmpl"; const char *loc_path = PREFIX "/lib/locale/"; +/* Flags set by `--verbose` option. */ int be_quiet = 1; int verbose = 0; int max_locarchive_open_retry = 10; @@ -36,7 +38,7 @@ static const char *locnames[] = { #define DEFINE_CATEGORY(category, category_name, items, a) \ [category] = category_name, -#include "locale/categories.def" +#include "./locale/categories.def" #undef DEFINE_CATEGORY }; @@ -122,7 +124,7 @@ open_tmpl_archive (struct locarhandle *ah) ah->mmaped = (head.sumhash_offset + head.sumhash_size * sizeof (struct sumhashent)); if (ah->mmaped > (unsigned long) st.st_size) - error (EXIT_FAILURE, 0, "locale archite template file truncated"); + error (EXIT_FAILURE, 0, "locale archive template file truncated"); ah->mmaped = st.st_size; ah->reserved = st.st_size; @@ -147,7 +149,7 @@ extern void add_alias (struct locarhandle *ah, const char *alias, bool replace, const char *oldname, uint32_t *locrec_offset_p); -static struct namehashent * +extern struct namehashent * insert_name (struct locarhandle *ah, const char *name, size_t name_len, bool replace); @@ -257,7 +259,9 @@ compute_data (struct locarhandle *ah, struct nameent *name, size_t sumused, static int fill_archive (struct locarhandle *tmpl_ah, - const char *fname, size_t nlist, char *list[], + const char *fname, + size_t install_langs_count, char *install_langs_list[], + size_t nlist, char *list[], const char *primary) { struct locarhandle ah; @@ -288,11 +292,40 @@ fill_archive (struct locarhandle *tmpl_ah, for (cnt = used = 0; cnt < head->namehash_size; ++cnt) if (namehashtab[cnt].locrec_offset != 0) { + char * name; + int i; assert (used < head->namehash_used); - names[used].name = tmpl_ah->addr + namehashtab[cnt].name_offset; - names[used++].locrec - = (struct locrecent *) ((char *) tmpl_ah->addr + - namehashtab[cnt].locrec_offset); + name = tmpl_ah->addr + namehashtab[cnt].name_offset; + if (install_langs_count == 0) + { + /* Always intstall the entry. */ + names[used].name = name; + names[used++].locrec + = (struct locrecent *) ((char *) tmpl_ah->addr + + namehashtab[cnt].locrec_offset); + } + else + { + /* Only install the entry if the user asked for it via + --install-langs. */ + for (i = 0; i < install_langs_count; i++) + { + /* Add one for "_" and one for the null terminator. */ + size_t len = strlen (install_langs_list[i]) + 2; + char *install_lang = (char *)xmalloc (len); + strcpy (install_lang, install_langs_list[i]); + if (strchr (install_lang, '_') == NULL) + strcat (install_lang, "_"); + if (strncmp (name, install_lang, strlen (install_lang)) == 0) + { + names[used].name = name; + names[used++].locrec + = (struct locrecent *) ((char *)tmpl_ah->addr + + namehashtab[cnt].locrec_offset); + } + free (install_lang); + } + } } /* Sort the names. */ @@ -542,6 +575,62 @@ fill_archive (struct locarhandle *tmpl_ah, return result; } +void usage() +{ + printf ("\ +Usage: build-locale-archive [OPTION]... [TEMPLATE-FILE] [ARCHIVE-FILE]\n\ + Builds a locale archive from a template file.\n\ + Options:\n\ + -h, --help Print this usage message.\n\ + -v, --verbose Verbose execution.\n\ + -l, --install-langs=LIST Only include locales given in LIST into the \n\ + locale archive. LIST is a colon separated list\n\ + of locale prefixes, for example \"de:en:ja\".\n\ + The special argument \"all\" means to install\n\ + all languages and it must be present by itself.\n\ + If \"all\" is present with any other language it\n\ + will be treated as the name of a locale.\n\ + If the --install-langs option is missing, all\n\ + locales are installed. The colon separated list\n\ + can contain any strings matching the beginning of\n\ + locale names.\n\ + If a string does not contain a \"_\", it is added.\n\ + Examples:\n\ + --install-langs=\"en\"\n\ + installs en_US, en_US.iso88591,\n\ + en_US.iso885915, en_US.utf8,\n\ + en_GB ...\n\ + --install-langs=\"en_US.utf8\"\n\ + installs only en_US.utf8.\n\ + --install-langs=\"ko\"\n\ + installs ko_KR, ko_KR.euckr,\n\ + ko_KR.utf8 but *not* kok_IN\n\ + because \"ko\" does not contain\n\ + \"_\" and it is silently added\n\ + --install-langs\"ko:kok\"\n\ + installs ko_KR, ko_KR.euckr,\n\ + ko_KR.utf8, kok_IN, and\n\ + kok_IN.utf8.\n\ + --install-langs=\"POSIX\" will\n\ + installs *no* locales at all\n\ + because POSIX matches none of\n\ + the locales. Actually, any string\n\ + matching nothing will do that.\n\ + POSIX and C will always be\n\ + available because they are\n\ + builtin.\n\ + Aliases are installed as well,\n\ + i.e. --install-langs=\"de\"\n\ + will install not only every locale starting with\n\ + \"de\" but also the aliases \"deutsch\"\n\ + and and \"german\" although the latter does not\n\ + start with \"de\".\n\ +\n\ + If the arguments TEMPLATE-FILE and ARCHIVE-FILE are not given the locations\n\ + where the glibc used expects these files are used by default.\n\ +"); +} + int main (int argc, char *argv[]) { char path[4096]; @@ -549,22 +638,138 @@ int main (int argc, char *argv[]) struct dirent64 *d; struct stat64 st; char *list[16384], *primary; + char *lang; + int install_langs_count = 0; + int i; + char *install_langs_arg, *ila_start; + char **install_langs_list = NULL; unsigned int cnt = 0; struct locarhandle tmpl_ah; + char *new_locar_fname = NULL; size_t loc_path_len = strlen (loc_path); + while (1) + { + int c; + + static struct option long_options[] = + { + {"help", no_argument, 0, 'h'}, + {"verbose", no_argument, 0, 'v'}, + {"install-langs", required_argument, 0, 'l'}, + {0, 0, 0, 0} + }; + /* getopt_long stores the option index here. */ + int option_index = 0; + + c = getopt_long (argc, argv, "vhl:", + long_options, &option_index); + + /* Detect the end of the options. */ + if (c == -1) + break; + + switch (c) + { + case 0: + printf ("unknown option %s", long_options[option_index].name); + if (optarg) + printf (" with arg %s", optarg); + printf ("\n"); + usage (); + exit (1); + + case 'v': + verbose = 1; + be_quiet = 0; + break; + + case 'h': + usage (); + exit (0); + + case 'l': + install_langs_arg = ila_start = strdup (optarg); + /* If the argument to --install-lang is "all", do + not limit the list of languages to install and install + them all. We do not support installing a single locale + called "all". */ +#define MAGIC_INSTALL_ALL "all" + if (install_langs_arg != NULL + && install_langs_arg[0] != '\0' + && !(strncmp(install_langs_arg, MAGIC_INSTALL_ALL, + strlen(MAGIC_INSTALL_ALL)) == 0 + && strlen (install_langs_arg) == 3)) + { + /* Count the number of languages we will install. */ + while (true) + { + lang = strtok(install_langs_arg, ":;,"); + if (lang == NULL) + break; + install_langs_count++; + install_langs_arg = NULL; + } + free (ila_start); + + /* Reject an entire string made up of delimiters. */ + if (install_langs_count == 0) + break; + + /* Copy the list. */ + install_langs_list = (char **)xmalloc (sizeof(char *) * install_langs_count); + install_langs_arg = ila_start = strdup (optarg); + install_langs_count = 0; + while (true) + { + lang = strtok(install_langs_arg, ":;,"); + if (lang == NULL) + break; + install_langs_list[install_langs_count] = lang; + install_langs_count++; + install_langs_arg = NULL; + } + } + break; + + case '?': + /* getopt_long already printed an error message. */ + usage (); + exit (0); + + default: + abort (); + } + } + tmpl_ah.fname = NULL; + if (optind < argc) + tmpl_ah.fname = argv[optind]; + if (optind + 1 < argc) + new_locar_fname = argv[optind + 1]; + if (verbose) + { + if (tmpl_ah.fname) + printf("input archive file specified on command line: %s\n", + tmpl_ah.fname); + else + printf("using default input archive file.\n"); + if (new_locar_fname) + printf("output archive file specified on command line: %s\n", + new_locar_fname); + else + printf("using default output archive file.\n"); + } + dirp = opendir (loc_path); if (dirp == NULL) error (EXIT_FAILURE, errno, "cannot open directory \"%s\"", loc_path); - /* Use the template file as specified on the command line. */ - tmpl_ah.fname = NULL; - if (argc > 1) - tmpl_ah.fname = argv[1]; - open_tmpl_archive (&tmpl_ah); - unlink (locar_file); + if (new_locar_fname) + unlink (new_locar_fname); + else + unlink (locar_file); primary = getenv ("LC_ALL"); if (primary == NULL) primary = getenv ("LANG"); @@ -575,7 +780,8 @@ int main (int argc, char *argv[]) && strncmp (primary, "zh", 2) != 0) { char *ptr = malloc (strlen (primary) + strlen (".utf8") + 1), *p, *q; - + /* This leads to invalid locales sometimes: + de_DE.iso885915@euro -> de_DE.utf8@euro */ if (ptr != NULL) { p = ptr; @@ -640,9 +846,16 @@ int main (int argc, char *argv[]) closedir (dirp); /* Store the archive to the file specified as the second argument on the command line or the default locale archive. */ - fill_archive (&tmpl_ah, argc > 2 ? argv[2] : NULL, cnt, list, primary); + fill_archive (&tmpl_ah, new_locar_fname, + install_langs_count, install_langs_list, + cnt, list, primary); close_archive (&tmpl_ah); truncate (tmpl_file, 0); + if (install_langs_count > 0) + { + free (ila_start); + free (install_langs_list); + } char *tz_argv[] = { "/usr/sbin/tzdata-update", NULL }; execve (tz_argv[0], (char *const *)tz_argv, (char *const *)&tz_argv[1]); exit (0); diff --git a/git-updates.diff b/git-updates.diff new file mode 100644 index 0000000..3930e2e --- /dev/null +++ b/git-updates.diff @@ -0,0 +1,10243 @@ +GIT update of https://sourceware.org/git/glibc.git/release/2.28/master from glibc-2.28 + +diff --git a/ChangeLog b/ChangeLog +index 08b42bd2f5..5667d9262b 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,800 @@ ++2019-01-31 Paul Eggert ++ ++ CVE-2019-9169 ++ regex: fix read overrun [BZ #24114] ++ Problem found by AddressSanitizer, reported by Hongxu Chen in: ++ https://debbugs.gnu.org/34140 ++ * posix/regexec.c (proceed_next_node): ++ Do not read past end of input buffer. ++ ++2018-11-07 Andreas Schwab ++ ++ [BZ #23864] ++ * sysdeps/unix/sysv/linux/riscv/kernel-features.h ++ (__ASSUME_SET_ROBUST_LIST) [__LINUX_KERNEL_VERSION < 0x041400]: ++ Undef. ++ ++2018-09-21 Adhemerval Zanella ++ ++ * NEWS: Add note about new TLE support on powerpc64le. ++ * sysdeps/powerpc/nptl/tcb-offsets.sym (TM_CAPABLE): Remove. ++ * sysdeps/powerpc/nptl/tls.h (tcbhead_t): Rename tm_capable to ++ __ununsed1. ++ (TLS_INIT_TP, TLS_DEFINE_INIT_TP): Remove tm_capable setup. ++ (THREAD_GET_TM_CAPABLE, THREAD_SET_TM_CAPABLE): Remove macros. ++ * sysdeps/powerpc/powerpc32/sysdep.h, ++ sysdeps/powerpc/powerpc64/sysdep.h (ABORT_TRANSACTION_IMPL, ++ ABORT_TRANSACTION): Remove macros. ++ * sysdeps/powerpc/sysdep.h (ABORT_TRANSACTION): Likewise. ++ * sysdeps/unix/sysv/linux/powerpc/elision-conf.c (elision_init): Set ++ __pthread_force_elision iff PPC_FEATURE2_HTM_NOSC is set. ++ * sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h, ++ sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h ++ sysdeps/unix/sysv/linux/powerpc/syscall.S (ABORT_TRANSACTION): Remove ++ usage. ++ * sysdeps/unix/sysv/linux/powerpc/not-errno.h: Remove file. ++ ++2019-01-13 Jim Wilson ++ ++ [BZ #24040] ++ * elf/Makefile (CFLAGS-tst-unwind-main.c): Add -DUSE_PTHREADS=0. ++ * elf/tst-unwind-main.c: If USE_PTHEADS, include pthread.h and error.h ++ (func): New. ++ (main): If USE_PTHREADS, call pthread_create to run func. Otherwise ++ call func directly. ++ * nptl/Makefile (tests): Add tst-unwind-thread. ++ (CFLAGS-tst-unwind-thread.c): Define. ++ * nptl/tst-unwind-thread.c: New file. ++ * sysdeps/unix/sysv/linux/riscv/clone.S (__thread_start): Mark ra ++ as undefined. ++ ++2019-01-31 Carlos O'Donell ++ Torvald Riegel ++ Rik Prohaska ++ ++ [BZ# 23844] ++ * nptl/Makefile (tests): Add tst-rwlock-tryrdlock-stall, and ++ tst-rwlock-trywrlock-stall. ++ * nptl/pthread_rwlock_tryrdlock.c (__pthread_rwlock_tryrdlock): ++ Wake waiters if PTHREAD_RWLOCK_FUTEX_USED is set. ++ * nptl/pthread_rwlock_trywrlock.c (__pthread_rwlock_trywrlock): ++ Set __wrphase_fute to 1 only if we started the write phase. ++ * nptl/tst-rwlock-tryrdlock-stall.c: New file. ++ * nptl/tst-rwlock-trywrlock-stall.c: New file. ++ * support/Makefile (libsupport-routines): Add xpthread_rwlock_destroy. ++ * support/xpthread_rwlock_destroy.c: New file. ++ * support/xthread.h: Declare xpthread_rwlock_destroy. ++ ++2019-02-08 Florian Weimer ++ ++ [BZ #24161] ++ * sysdeps/nptl/fork.h (__run_fork_handlers): Add multiple_threads ++ argument. ++ * nptl/register-atfork.c (__run_fork_handlers): Only perform ++ locking if the new do_locking argument is true. ++ * sysdeps/nptl/fork.c (__libc_fork): Pass multiple_threads to ++ __run_fork_handlers. ++ ++2019-02-07 Stefan Liebler ++ ++ [BZ #24180] ++ * nptl/pthread_mutex_trylock.c (__pthread_mutex_trylock): ++ Add compiler barriers and comments. ++ ++2019-02-04 Florian Weimer ++ ++ [BZ #20018] ++ nscd: Do not rely on new GLIBC_PRIVATE ABI after CVE-2016-10739 fix. ++ * nscd/nscd-inet_addr.c: New file. Build resolv/inet_addr.c for ++ nscd, without public symbols. ++ * nscd/Makefile (nscd-modules): Add it. ++ * nscd/gai.c: Include and change visibility of ++ __inet_aton_exact. ++ ++2019-01-21 Florian Weimer ++ ++ [BZ #20018] ++ CVE-2016-10739 ++ resolv: Reject trailing characters in host names ++ * include/arpa/inet.h (__inet_aton_exact): Declare. ++ (inet_aton): Remove hidden prototype. No longer used internally. ++ * nscd/gai.c (__inet_aton): Do not define. ++ * nscd/gethstbynm3_r.c (__inet_aton): Likewise. ++ * nss/digits_dots.c (__inet_aton): Likewise. ++ (__nss_hostname_digits_dots_context): Call __inet_aton_exact. ++ * resolv/Makefile (tests-internal): Add tst-inet_aton_exact. ++ (tests): Add tst-resolv-nondecimal, tst-resolv-trailing. ++ (tst-resolv-nondecimal): Link with libresolv.so and libpthread. ++ (tst-resolv-trailing): Likewise. ++ * resolv/Versions (GLIBC_PRIVATE): Export __inet_aton_exact from ++ libc. ++ * resolv/inet_addr.c (inet_aton_end): Remame from __inet_aton. ++ Make static. Add endp parameter. ++ (__inet_aton_exact): New function. ++ (__inet_aton_ignore_trailing): New function, aliased to inet_aton. ++ (__inet_addr): Call inet_aton_end. ++ * resolv/res_init.c (res_vinit_1): Truncate nameserver for IPv4, ++ not just IPv6. Call __inet_aton_exact. ++ * resolv/tst-aton.c: Switch to . ++ (tests): Make const. Add additional test cases with trailing ++ characters. ++ (do_test): Use array_length. ++ * resolv/tst-inet_aton_exact.c: New file. ++ * resolv/tst-resolv-trailing.c: Likewise. ++ * resolv/tst-resolv-nondecimal.c: Likewise. ++ * sysdeps/posix/getaddrinfo.c (gaih_inet): Call __inet_aton_exact. ++ ++2019-01-18 Florian Weimer ++ ++ [BZ #24112] ++ resolv: Do not send queries for non-host-names in nss_dns. ++ * resolv/nss_dns/dns-host.c (check_name): New function. ++ (_nss_dns_gethostbyname2_r): Use it. ++ (_nss_dns_gethostbyname_r): Likewise. ++ (_nss_dns_gethostbyname4_r): Likewise. ++ ++2019-01-21 Florian Weimer ++ ++ * resolv/inet_addr.c: Reformat to GNU style. ++ (__inet_addr, __inet_aton): Update comment. ++ ++2019-02-04 H.J. Lu ++ ++ [BZ #24155] ++ CVE-2019-7309 ++ * NEWS: Updated for CVE-2019-7309. ++ * sysdeps/x86_64/memcmp.S: Use RDX_LP for size. Clear the ++ upper 32 bits of RDX register for x32. Use unsigned Jcc ++ instructions, instead of signed. ++ * sysdeps/x86_64/x32/Makefile (tests): Add tst-size_t-memcmp-2. ++ * sysdeps/x86_64/x32/tst-size_t-memcmp-2.c: New test. ++ ++2019-02-01 H.J. Lu ++ ++ [BZ #24097] ++ CVE-2019-6488 ++ * sysdeps/x86_64/multiarch/strlen-avx2.S: Use RSI_LP for length. ++ Clear the upper 32 bits of RSI register. ++ * sysdeps/x86_64/strlen.S: Use RSI_LP for length. ++ * sysdeps/x86_64/x32/Makefile (tests): Add tst-size_t-strnlen ++ and tst-size_t-wcsnlen. ++ * sysdeps/x86_64/x32/tst-size_t-strnlen.c: New file. ++ * sysdeps/x86_64/x32/tst-size_t-wcsnlen.c: Likewise. ++ ++2019-02-01 H.J. Lu ++ ++ [BZ #24097] ++ CVE-2019-6488 ++ * sysdeps/x86_64/multiarch/strcpy-sse2-unaligned.S: Use RDX_LP ++ for length. ++ * sysdeps/x86_64/multiarch/strcpy-ssse3.S: Likewise. ++ * sysdeps/x86_64/x32/Makefile (tests): Add tst-size_t-strncpy. ++ * sysdeps/x86_64/x32/tst-size_t-strncpy.c: New file. ++ ++2019-02-01 H.J. Lu ++ ++ [BZ #24097] ++ CVE-2019-6488 ++ * sysdeps/x86_64/multiarch/strcmp-avx2.S: Use RDX_LP for length. ++ * sysdeps/x86_64/multiarch/strcmp-sse42.S: Likewise. ++ * sysdeps/x86_64/strcmp.S: Likewise. ++ * sysdeps/x86_64/x32/Makefile (tests): Add tst-size_t-strncasecmp, ++ tst-size_t-strncmp and tst-size_t-wcsncmp. ++ * sysdeps/x86_64/x32/tst-size_t-strncasecmp.c: New file. ++ * sysdeps/x86_64/x32/tst-size_t-strncmp.c: Likewise. ++ * sysdeps/x86_64/x32/tst-size_t-wcsncmp.c: Likewise. ++ ++2019-02-01 H.J. Lu ++ ++ [BZ #24097] ++ CVE-2019-6488 ++ * sysdeps/x86_64/multiarch/memset-avx512-no-vzeroupper.S: Use ++ RDX_LP for length. Clear the upper 32 bits of RDX register. ++ * sysdeps/x86_64/multiarch/memset-vec-unaligned-erms.S: Likewise. ++ * sysdeps/x86_64/x32/Makefile (tests): Add tst-size_t-wmemset. ++ * sysdeps/x86_64/x32/tst-size_t-memset.c: New file. ++ * sysdeps/x86_64/x32/tst-size_t-wmemset.c: Likewise. ++ ++2019-02-01 H.J. Lu ++ ++ [BZ #24097] ++ CVE-2019-6488 ++ * sysdeps/x86_64/memrchr.S: Use RDX_LP for length. ++ * sysdeps/x86_64/multiarch/memrchr-avx2.S: Likewise. ++ * sysdeps/x86_64/x32/Makefile (tests): Add tst-size_t-memrchr. ++ * sysdeps/x86_64/x32/tst-size_t-memrchr.c: New file. ++ ++2019-02-01 H.J. Lu ++ ++ [BZ #24097] ++ CVE-2019-6488 ++ * sysdeps/x86_64/multiarch/memcpy-ssse3-back.S: Use RDX_LP for ++ length. Clear the upper 32 bits of RDX register. ++ * sysdeps/x86_64/multiarch/memcpy-ssse3.S: Likewise. ++ * sysdeps/x86_64/multiarch/memmove-avx512-no-vzeroupper.S: ++ Likewise. ++ * sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S: ++ Likewise. ++ * sysdeps/x86_64/x32/Makefile (tests): Add tst-size_t-memcpy. ++ tst-size_t-wmemchr. ++ * sysdeps/x86_64/x32/tst-size_t-memcpy.c: New file. ++ ++2019-02-01 H.J. Lu ++ ++ [BZ #24097] ++ CVE-2019-6488 ++ * sysdeps/x86_64/multiarch/memcmp-avx2-movbe.S: Use RDX_LP for ++ length. Clear the upper 32 bits of RDX register. ++ * sysdeps/x86_64/multiarch/memcmp-sse4.S: Likewise. ++ * sysdeps/x86_64/multiarch/memcmp-ssse3.S: Likewise. ++ * sysdeps/x86_64/x32/Makefile (tests): Add tst-size_t-memcmp and ++ tst-size_t-wmemcmp. ++ * sysdeps/x86_64/x32/tst-size_t-memcmp.c: New file. ++ * sysdeps/x86_64/x32/tst-size_t-wmemcmp.c: Likewise. ++ ++2019-02-01 H.J. Lu ++ ++ [BZ #24097] ++ CVE-2019-6488 ++ * sysdeps/x86_64/memchr.S: Use RDX_LP for length. Clear the ++ upper 32 bits of RDX register. ++ * sysdeps/x86_64/multiarch/memchr-avx2.S: Likewise. ++ * sysdeps/x86_64/x32/Makefile (tests): Add tst-size_t-memchr and ++ tst-size_t-wmemchr. ++ * sysdeps/x86_64/x32/test-size_t.h: New file. ++ * sysdeps/x86_64/x32/tst-size_t-memchr.c: Likewise. ++ * sysdeps/x86_64/x32/tst-size_t-wmemchr.c: Likewise. ++ ++2019-01-16 Tulio Magno Quites Machado Filho ++ ++ * math/libm-test-fma.inc (fma_test_data): Set ++ XFAIL_ROUNDING_IBM128_LIBGCC to more tests. ++ ++2019-01-07 Aurelien Jarno ++ ++ [BZ #24024] ++ * Makeconfig: Build libm with -fno-math-errno but build the remaining ++ code with -fmath-errno. ++ * string/Makefile [$(build-shared)] (tests): Add test-strerror-errno. ++ [$(build-shared)] (LDLIBS-test-strerror-errno): New variable. ++ * string/test-strerror-errno.c: New file. ++ ++2019-01-03 Martin Jansa ++ ++ [BZ #19444] ++ * sysdeps/ieee754/soft-fp/s_fdiv.c: Include and use ++ DIAG_PUSH_NEEDS_COMMENT, DIAG_IGNORE_NEEDS_COMMENT and ++ DIAG_POP_NEEDS_COMMENT to disable -Wmaybe-uninitialized. ++ ++2019-01-02 Aurelien Jarno ++ ++ [BZ #24034] ++ * sysdeps/unix/sysv/linux/arm/atomic-machine.h ++ (__arm_assisted_compare_and_exchange_val_32_acq): Use uint32_t rather ++ than __typeof (...) for the a_ptr variable. ++ ++2018-12-31 H.J. Lu ++ ++ [BZ #24022] ++ * sysdeps/unix/sysv/linux/riscv/flush-icache.c: Check if ++ exists with __has_include__ before including it. ++ ++2019-01-02 Florian Weimer ++ ++ [BZ #24018] ++ * intl/dcigettext.c (DCIGETTEXT): Do not return NULL on asprintf ++ failure. ++ ++2018-12-31 Florian Weimer ++ ++ [BZ #24027] ++ * malloc/malloc.c (_int_realloc): Always call memcpy for the ++ copying operation. (ncopies had the wrong type, resulting in an ++ integer wraparound and too few elements being copied.) ++ ++2018-12-28 Aurelien Jarno ++ ++ * sysdeps/alpha/fpu/libm-test-ulps: Regenerated. ++ ++2018-12-18 Adhemerval Zanella ++ James Clarke ++ ++ [BZ #23967] ++ * sysdeps/unix/sysv/linux/kernel_sigaction.h (HAS_SA_RESTORER): ++ Define if SA_RESTORER is defined. ++ (kernel_sigaction): Define sa_restorer if HAS_SA_RESTORER is defined. ++ (SET_SA_RESTORER, RESET_SA_RESTORER): Define iff the macro are not ++ already defined. ++ * sysdeps/unix/sysv/linux/m68k/kernel_sigaction.h (SA_RESTORER, ++ kernel_sigaction, SET_SA_RESTORER, RESET_SA_RESTORER): Remove ++ definitions. ++ (HAS_SA_RESTORER): Define. ++ * sysdeps/unix/sysv/linux/sparc/kernel_sigaction.h (SA_RESTORER, ++ SET_SA_RESTORER, RESET_SA_RESTORER): Remove definition. ++ (HAS_SA_RESTORER): Define. ++ * sysdeps/unix/sysv/linux/nios2/kernel_sigaction.h: Include generic ++ kernel_sigaction after define SET_SA_RESTORER and RESET_SA_RESTORER. ++ * sysdeps/unix/sysv/linux/powerpc/kernel_sigaction.h: Likewise. ++ * sysdeps/unix/sysv/linux/s390/kernel_sigaction.h: Likewise. ++ * sysdeps/unix/sysv/linux/x86_64/sigaction.c: Likewise. ++ ++2018-10-30 Andreas Schwab ++ ++ [BZ #23125] ++ * sysdeps/riscv/start.S (ENTRY_POINT): Mark ra as undefined. ++ Don't use tail call. ++ * elf/tst-unwind-main.c: New file. ++ * elf/Makefile (tests): Add tst-unwind-main. ++ (CFLAGS-tst-unwind-main.c): Define. ++ ++2018-12-15 Florian Weimer ++ ++ * support/blob_repeat.c (check_mul_overflow_size_t): New function. ++ (minimum_stride_size): Use it. ++ (support_blob_repeat_allocate): Likewise. ++ ++2018-12-13 Andreas Schwab ++ ++ [BZ #23861] ++ * nptl/pthread_rwlock_common.c: Reindent. Fix typos. ++ (__pthread_rwlock_rdlock_full): Update expected value for ++ __readers while waiting on PTHREAD_RWLOCK_RWAITING. ++ * nptl/tst-rwlock-pwn.c: New file. ++ * nptl/Makefile (tests): Add tst-rwlock-pwn. ++ ++2018-12-12 Tulio Magno Quites Machado Filho ++ ++ [BZ #23614] ++ * sysdeps/powerpc/powerpc64/addmul_1.S (FUNC): Add CFI offset for ++ registers saved in the stack frame. ++ * sysdeps/powerpc/powerpc64/lshift.S (__mpn_lshift): Likewise. ++ * sysdeps/powerpc/powerpc64/mul_1.S (__mpn_mul_1): Likewise. ++ ++2018-12-07 DJ Delorie ++ ++ [BZ #23907] ++ * malloc/tst-tcfree3.c: New. ++ * malloc/Makefile: Add it. ++ ++2018-12-07 Florian Weimer ++ ++ [BZ #23927] ++ CVE-2018-19591 ++ * inet/tst-if_index-long.c: New file. ++ * inet/Makefile (tests): Add tst-if_index-long. ++ ++2018-12-07 Florian Weimer ++ ++ * support/check.h (support_record_failure_is_failed): Declare. ++ * support/descriptors.h: New file. ++ * support/support_descriptors.c: Likewise. ++ * support/tst-support_descriptors.c: Likewise. ++ * support/support_record_failure.c ++ (support_record_failure_is_failed): New function. ++ * support/Makefile (libsupport-routines): Add support_descriptors. ++ (tests): Add tst-support_descriptors. ++ ++2018-12-01 Florian Weimer ++ ++ * support/support_capture_subprocess.c ++ (support_capture_subprocess): Check that pipe descriptors have ++ expected values. Close original pipe descriptors in subprocess. ++ ++2018-11-28 Florian Weimer ++ ++ * support/support.h (support_quote_string): Do not use str ++ parameter name. ++ ++2018-11-27 Florian Weimer ++ ++ * support/support.h (support_quote_string): Declare. ++ * support/support_quote_string.c: New file. ++ * support/tst-support_quote_string.c: Likewise. ++ * support/Makefile (libsupport-routines): Add ++ support_quote_string. ++ (tests): Add tst-support_quote_string. ++ ++2018-12-10 Florian Weimer ++ ++ [BZ #23972] ++ * sysdeps/unix/sysv/linux/getdents64.c (handle_overflow): Check ++ offset instead of count for clarity. Fix typo in comment. ++ (__old_getdents64): Keep track of previous offset. Use it to call ++ handle_overflow. ++ * sysdeps/unix/sysv/linux/tst-readdir64-compat.c (do_test): Check ++ that d_off is never zero. ++ ++2018-11-30 Tulio Magno Quites Machado Filho ++ ++ [BZ #23690] ++ * elf/dl-runtime.c (_dl_profile_fixup): Guarantee memory ++ modification order when accessing reloc_result->addr. ++ * include/link.h (reloc_result): Add field init. ++ * nptl/Makefile (tests): Add tst-audit-threads. ++ (modules-names): Add tst-audit-threads-mod1 and ++ tst-audit-threads-mod2. ++ Add rules to build tst-audit-threads. ++ * nptl/tst-audit-threads-mod1.c: New file. ++ * nptl/tst-audit-threads-mod2.c: Likewise. ++ * nptl/tst-audit-threads.c: Likewise. ++ * nptl/tst-audit-threads.h: Likewise. ++ ++2018-11-26 Florian Weimer ++ ++ [BZ #23907] ++ * malloc/malloc.c (_int_free): Validate tc_idx before checking for ++ double-frees. ++ ++ ++2018-11-20 DJ Delorie ++ ++ * malloc/malloc.c (tcache_entry): Add key field. ++ (tcache_put): Set it. ++ (tcache_get): Likewise. ++ (_int_free): Check for double free in tcache. ++ * malloc/tst-tcfree1.c: New. ++ * malloc/tst-tcfree2.c: New. ++ * malloc/Makefile: Run the new tests. ++ * manual/probes.texi: Document memory_tcache_double_free probe. ++ ++ * dlfcn/dlerror.c (check_free): Prevent double frees. ++ ++2018-11-27 Florian Weimer ++ ++ [BZ #23927] ++ CVE-2018-19591 ++ * sysdeps/unix/sysv/linux/if_index.c (__if_nametoindex): Avoid ++ descriptor leak in case of ENODEV error. ++ ++2018-11-19 Florian Weimer ++ ++ support: Print timestamps in timeout handler. ++ * support/support_test_main.c (print_timestamp): New function. ++ (signal_handler): Use it to print the termination time and the ++ time of the last write to standard output. ++ ++2018-10-09 Szabolcs Nagy ++ ++ * libio/tst-readline.c (TIMEOUT): Define. ++ ++2018-10-22 Joseph Myers ++ ++ * sysdeps/unix/sysv/linux/syscall-names.list: Update kernel ++ version to 4.19. ++ ++2018-09-18 Paul Eggert ++ ++ Fix tzfile low-memory assertion failure ++ [BZ #21716] ++ * time/tzfile.c (__tzfile_read): Check for memory exhaustion ++ when registering time zone abbreviations. ++ ++2018-08-31 Paul Pluzhnikov ++ ++ [BZ #20271] ++ * include/stdio.h (__libc_fatal): Mention newline in comment. ++ * grp/initgroups.c (internal_getgrouplist): Add missing newline. ++ * nptl/pthread_cond_wait.c (__pthread_cond_wait_common): Likewise. ++ * nscd/initgrcache.c (addinitgroupsX): Likewise. ++ * nss/nsswitch.c (__nss_next2): Likewise. ++ * sysdeps/aarch64/dl-irel.h (elf_irela): Likewise. ++ * sysdeps/arm/dl-irel.h (elf_irel): Likewise. ++ * sysdeps/generic/unwind-dw2.c (execute_cfa_program): Likewise. ++ * sysdeps/i386/dl-irel.h (elf_irel): Likewise. ++ * sysdeps/powerpc/powerpc32/dl-irel.h (elf_irel): Likewise. ++ * sysdeps/powerpc/powerpc64/dl-irel.h (elf_irel): Likewise. ++ * sysdeps/s390/dl-irel.h (elf_irel): Likewise. ++ * sysdeps/sparc/sparc32/dl-irel.h (elf_irel): Likewise. ++ * sysdeps/sparc/sparc64/dl-irel.h (elf_irel): Likewise. ++ * sysdeps/x86_64/dl-irel.h (elf_irel): Likewise. ++ * sysdeps/nptl/futex-internal.h (futex_wake): Likewise. ++ * sysdeps/unix/sysv/linux/netlink_assert_response.c ++ (__netlink_assert_response): Likewise. ++ ++2018-08-28 Florian Weimer ++ ++ [BZ #23520] ++ nscd: Fix use-after-free in addgetnetgrentX and its callers. ++ * nscd/netgroupcache.c ++ (addgetnetgrentX): Add tofreep parameter. Do not free ++ heap-allocated buffer. ++ (addinnetgrX): Free buffer allocated bt addgetnetgrentX. ++ (addgetnetgrentX_ignore): New function. ++ (addgetnetgrent): Call it. ++ (readdgetnetgrent): Likewise. ++ ++2018-08-16 DJ Delorie ++ ++ * malloc/malloc.c (_int_free): Check for corrupt prev_size vs size. ++ (malloc_consolidate): Likewise. ++ ++2018-08-16 Pochang Chen ++ ++ * malloc/malloc.c (_int_malloc.c): Verify size of top chunk. ++ ++2018-08-13 Joseph Myers ++ ++ * sysdeps/unix/sysv/linux/syscall-names.list: Update kernel ++ version to 4.18. ++ (io_pgetevents): New syscall. ++ (rseq): Likewise. ++ ++2018-11-08 Alexandra Hájková ++ ++ [BZ #17630] ++ * resolv/tst-resolv-network.c: Add test for getnetbyname. ++ ++2018-11-08 H.J. Lu ++ ++ [BZ #23509] ++ * sysdeps/x86/dl-prop.h (_dl_process_cet_property_note): Skip ++ note parsing if a NT_GNU_PROPERTY_TYPE_0 note has been processed. ++ Update the l_cet field when processing NT_GNU_PROPERTY_TYPE_0 note. ++ Check multiple NT_GNU_PROPERTY_TYPE_0 notes. ++ * sysdeps/x86/link_map.h (l_cet): Expand to 3 bits, Add ++ lc_unknown. ++ ++2018-11-05 Andreas Schwab ++ ++ [BZ #22927] ++ * resolv/gai_misc.c (__gai_enqueue_request): Don't crash if ++ creating the first helper thread failed. ++ ++2018-10-23 Adhemerval Zanella ++ ++ [BZ #23709] ++ * sysdeps/x86/cpu-features.c (init_cpu_features): Set TSX bits ++ independently of other flags. ++ ++2018-10-30 Florian Weimer ++ ++ * stdlib/tst-strtod-overflow.c (do_test): Switch to ++ support_blob_repeat. ++ ++2018-10-30 Florian Weimer ++ ++ * support/blob_repeat.c (allocate_big): Call mkstemp directly. ++ ++2018-10-30 Florian Weimer ++ ++ * stdlib/test-bz22786.c (do_test): Additional free calls to avoid ++ memory leaks. ++ ++2018-10-30 Florian Weimer ++ ++ Avoid spurious test failures in stdlib/test-bz22786. ++ * support/Makefile (libsupport-routines): Add blob_repeat. ++ (tests): Add tst-support_blob_repeat. ++ * support/blob_repeat.h: New file. ++ * support/blob_repeat.c: Likewise. ++ * support/tst-support_blob_repeat.c: Likewise. ++ * stdlib/test-bz22786.c (do_test): Replace malloc and memset with ++ support_blob_repeat_allocate. ++ ++2018-08-30 Stefan Liebler ++ ++ * stdlib/test-bz22786.c (do_test): Return EXIT_UNSUPPORTED ++ if malloc fails. ++ ++2018-08-24 Paul Pluzhnikov ++ ++ [BZ #23400] ++ * stdlib/test-bz22786.c (do_test): Fix undefined behavior, don't ++ create temporary files in source tree. ++ ++2018-10-26 Szabolcs Nagy ++ ++ [BZ #23822] ++ * sysdeps/ia64/fpu/e_exp2f.S (exp2f): Use WEAK_LIBM_ENTRY. ++ * sysdeps/ia64/fpu/e_log2f.S (log2f): Likewise. ++ * sysdeps/ia64/fpu/e_exp2f.S (powf): Likewise. ++ ++2018-10-25 Florian Weimer ++ ++ [BZ #23562] ++ [BZ #23821] ++ XFAIL siginfo_t si_band conform test on sparc64. ++ * sysdeps/unix/sysv/linux/sparc/bits/siginfo-arch.h ++ (__SI_BAND_TYPE): Only override long int default type on sparc64. ++ * sysdeps/unix/sysv/linux/sparc/sparc64/Makefile ++ (conformtest-xfail-conds): Add sparc64-linux. ++ * conform/data/signal.h-data (siginfo_t): XFAIL si_band test on ++ sparc64. ++ * conform/data/sys/wait.h-data (siginfo_t): Likewise. ++ ++2018-10-19 Ilya Yu. Malakhov ++ ++ [BZ #23562] ++ * sysdeps/unix/sysv/linux/bits/types/siginfo_t.h ++ (struct siginfo_t): Use correct type for si_band. ++ ++2018-10-17 Stefan Liebler ++ ++ [BZ #23275] ++ * nptl/tst-mutex10.c: New File. ++ * nptl/Makefile (tests): Add tst-mutex10. ++ (tst-mutex10-ENV): New variable. ++ * sysdeps/unix/sysv/linux/s390/force-elision.h: (FORCE_ELISION): ++ Ensure that elision path is used if elision is available. ++ * sysdeps/unix/sysv/linux/powerpc/force-elision.h (FORCE_ELISION): ++ Likewise. ++ * sysdeps/unix/sysv/linux/x86/force-elision.h: (FORCE_ELISION): ++ Likewise. ++ * nptl/pthreadP.h (PTHREAD_MUTEX_TYPE, PTHREAD_MUTEX_TYPE_ELISION) ++ (PTHREAD_MUTEX_PSHARED): Use atomic_load_relaxed. ++ * nptl/pthread_mutex_consistent.c (pthread_mutex_consistent): Likewise. ++ * nptl/pthread_mutex_getprioceiling.c (pthread_mutex_getprioceiling): ++ Likewise. ++ * nptl/pthread_mutex_lock.c (__pthread_mutex_lock_full) ++ (__pthread_mutex_cond_lock_adjust): Likewise. ++ * nptl/pthread_mutex_setprioceiling.c (pthread_mutex_setprioceiling): ++ Likewise. ++ * nptl/pthread_mutex_timedlock.c (__pthread_mutex_timedlock): Likewise. ++ * nptl/pthread_mutex_trylock.c (__pthread_mutex_trylock): Likewise. ++ * nptl/pthread_mutex_unlock.c (__pthread_mutex_unlock_full): Likewise. ++ * sysdeps/nptl/bits/thread-shared-types.h (struct __pthread_mutex_s): ++ Add comments. ++ * nptl/pthread_mutex_destroy.c (__pthread_mutex_destroy): ++ Use atomic_load_relaxed and atomic_store_relaxed. ++ * nptl/pthread_mutex_init.c (__pthread_mutex_init): ++ Use atomic_store_relaxed. ++ ++2018-10-09 H.J. Lu ++ ++ [BZ #23716] ++ * sysdeps/i386/dl-cet.c: Removed. ++ * sysdeps/i386/dl-machine.h (_dl_runtime_resolve_shstk): New ++ prototype. ++ (_dl_runtime_profile_shstk): Likewise. ++ (elf_machine_runtime_setup): Use _dl_runtime_profile_shstk or ++ _dl_runtime_resolve_shstk if SHSTK is enabled by kernel. ++ ++2018-10-09 Rafal Luzynski ++ ++ [BZ #20209] ++ * localedata/locales/kl_GL: (abday): Fix spelling of Sun (Sunday), ++ should be "sap" rather than "sab". ++ (day): Fix spelling of Sunday, should be "sapaat" rather than ++ "sabaat". ++ ++2018-09-28 Adhemerval Zanella ++ ++ [BZ #23579] ++ * misc/tst-preadvwritev2-common.c (do_test_with_invalid_fd, ++ do_test_with_invalid_iov): New tests. ++ * misc/tst-preadvwritev2.c, misc/tst-preadvwritev64v2.c (do_test): ++ Call do_test_with_invalid_fd and do_test_with_invalid_iov. ++ * sysdeps/unix/sysv/linux/preadv2.c (preadv2): Use fallback code iff ++ errno is ENOSYS. ++ * sysdeps/unix/sysv/linux/preadv64v2.c (preadv64v2): Likewise. ++ * sysdeps/unix/sysv/linux/pwritev2.c (pwritev2): Likewise. ++ * sysdeps/unix/sysv/linux/pwritev64v2.c (pwritev64v2): Likewise. ++ * NEWS: Add bug fixed. ++ ++2018-09-27 Andreas Schwab ++ ++ [BZ #23717] ++ * stdlib/tst-setcontext9.c (f1a): Make st2 static. ++ (do_test): Make st1 static. ++ ++2018-09-21 H.J. Lu ++ Xuepeng Guo ++ ++ [BZ #23606] ++ * sysdeps/i386/start.S: Include ++ (_start): Use ENTRY/END to insert ENDBR32 at entry when CET is ++ enabled. Add cfi_undefined (eip). ++ ++2018-09-19 Wilco Dijkstra ++ ++ [BZ #23637] ++ * string/test-strstr.c (pr23637): New function. ++ (test_main): Add tests with longer needles. ++ * string/strcasestr.c (AVAILABLE): Fix readahead distance. ++ * string/strstr.c (AVAILABLE): Likewise. ++ ++2018-09-19 Carlos O'Donell ++ ++ * stdlib/tst-setcontext9.c (f1): Rename to... ++ (f1a): ... this. ++ (f1b): New function implementing lower half of f1 in alternate stack. ++ ++2018-09-20 Florian Weimer ++ ++ * misc/tst-gethostid.c: New file. ++ * misc/Makefile [$(build-shared)] (tests): Add tst-gethostid. ++ (tst-gethostid): Link with -ldl. ++ ++2018-09-20 Mingli Yu ++ ++ * sysdeps/unix/sysv/linux/gethostid.c (gethostid): Check for NULL ++ value from gethostbyname_r. ++ ++2018-09-06 Stefan Liebler ++ ++ * sysdeps/unix/sysv/linux/spawni.c (maybe_script_execute): ++ Increment size of new_argv by one. ++ ++2018-08-28 Florian Weimer ++ ++ [BZ #23578] ++ * posix/tst-regcomp-truncated.c: New file. ++ * posix/Makefile (tests): Add it. ++ (tst-regcomp-truncated.out): Depend on generated locales. ++ ++2018-08-25 Paul Eggert ++ ++ [BZ #23578] ++ regex: fix uninitialized memory access ++ I introduced this bug into gnulib in commit ++ 8335a4d6c7b4448cd0bcb6d0bebf1d456bcfdb17 dated 2006-04-10; ++ eventually it was merged into glibc. The bug was found by ++ project-repo and reported here: ++ https://lists.gnu.org/r/sed-devel/2018-08/msg00017.html ++ Diagnosis and draft fix reported by Assaf Gordon here: ++ https://lists.gnu.org/r/bug-gnulib/2018-08/msg00071.html ++ https://lists.gnu.org/r/bug-gnulib/2018-08/msg00142.html ++ * posix/regex_internal.c (build_wcs_upper_buffer): ++ Fix bug when mbrtowc returns 0. ++ ++2018-08-27 Martin Kuchta ++ Torvald Riegel ++ ++ [BZ #23538] ++ * nptl/pthread_cond_common.c (__condvar_quiesce_and_switch_g1): ++ Update r to include the set wake-request flag if waiters are ++ remaining after spinning. ++ ++2018-08-03 DJ Delorie ++ ++ * sysdeps/riscv/rvf/math_private.h (libc_feholdexcept_setround_riscv): ++ Move libc_fesetround_riscv after libc_feholdexcept_riscv. ++ ++ * sysdeps/riscv/rv64/rvd/libm-test-ulps: Update. ++ ++2018-08-14 Florian Weimer ++ ++ [BZ #23521] ++ [BZ #23522] ++ * nss/nss_files/files-alias.c (get_next_alias): During :include: ++ processing, bail out if no room, and close the stream before ++ returning ERANGE. ++ * nss/Makefile (tests): Add tst-nss-files-alias-leak. ++ (tst-nss-files-alias-leak): Link with libdl. ++ (tst-nss-files-alias-leak.out): Depend on nss_files. ++ ++ * nss/tst-nss-files-alias-leak.c: New file. ++ ++2018-08-14 Florian Weimer ++ ++ * nscd/nscd_conf.c (nscd_parse_file): Deallocate old storage for ++ server_user, stat_user. ++ ++2018-08-13 Florian Weimer ++ ++ * misc/error.c (error): Add missing va_end call. ++ (error_at_line): Likewise. ++ ++2018-08-10 Florian Weimer ++ ++ [BZ #23497] ++ * sysdeps/unix/sysv/linux/getdents64.c (handle_overflow): New ++ function. ++ (__old_getdents64): Use getdents64. Convert entries without ++ moving them. ++ * sysdeps/unix/sysv/linux/tst-readdir64-compat.c: New file. ++ * sysdeps/unix/sysv/linux/Makefile (tests-internal): Add ++ tst-readdir64-compat. ++ ++2018-08-08 Samuel Thibault ++ ++ * htl/Versions (__pthread_getspecific, __pthread_setspecific): Add ++ symbols. ++ * sysdeps/htl/pthreadP.h [IS_IN (libpthread)] (__pthread_getspecific, ++ __pthread_setspecific): Add hidden proto. ++ * sysdeps/htl/pt-getspecific.c (__pthread_getspecific): Add hidden def. ++ * sysdeps/htl/pt-setspecific.c (__pthread_setspecific): Add hidden def. ++ + 2018-08-01 Carlos O'Donel + + * version.h (RELEASE): Set to "stable". +diff --git a/Makeconfig b/Makeconfig +index 608ffe648c..f5e81bdf5d 100644 +--- a/Makeconfig ++++ b/Makeconfig +@@ -831,8 +831,10 @@ endif + # disable any optimization that assume default rounding mode. + +math-flags = -frounding-math + +-# Build libc/libm using -fno-math-errno, but run testsuite with -fmath-errno. +-+extra-math-flags = $(if $(filter libnldbl nonlib testsuite,$(in-module)),-fmath-errno,-fno-math-errno) ++# Logically only "libnldbl", "nonlib" and "testsuite" should be using ++# -fno-math-errno. However due to GCC bug #88576, only "libm" can use ++# -fno-math-errno. +++extra-math-flags = $(if $(filter libm,$(in-module)),-fno-math-errno,-fmath-errno) + + # We might want to compile with some stack-protection flag. + ifneq ($(stack-protector),) +diff --git a/NEWS b/NEWS +index 154ab22d7c..f4981a16f0 100644 +--- a/NEWS ++++ b/NEWS +@@ -5,6 +5,82 @@ See the end for copying conditions. + Please send GNU C library bug reports via + using `glibc' in the "product" field. + ++Version 2.28.1 ++ ++Deprecated and removed features, and other changes affecting compatibility: ++ ++* For powercp64le ABI, Transactional Lock Elision is now enabled iff kernel ++ indicates that it will abort the transaction prior to entering the kernel ++ (PPC_FEATURE2_HTM_NOSC on hwcap2). On older kernels the transaction is ++ suspended, and this caused some undefined side-effects issues by aborting ++ transactions manually. Glibc avoided it by abort transactions manually on ++ each syscall, but it lead to performance issues on newer kernels where the ++ HTM state is saved and restore lazily (the state being saved even when the ++ process actually does not use HTM). ++ ++The following bugs are resolved with this release: ++ ++ [19444] build failures with -O1 due to -Wmaybe-uninitialized ++ [20018] getaddrinfo should reject IP addresses with trailing characters ++ [20209] localedata: Spelling mistake for Sunday in Greenlandic kl_GL ++ [22927] libanl: properly cleanup if first helper thread creation failed ++ [23400] stdlib/test-bz22786.c creates temporary files in glibc source tree ++ [23497] readdir64@GLIBC_2.1 cannot parse the kernel directory stream ++ [23509] CET enabled glibc is incompatible with the older linker ++ [23521] nss_files aliases database file stream leak ++ [23538] pthread_cond_broadcast: Fix waiters-after-spinning case ++ [23562] signal: Use correct type for si_band in siginfo_t ++ [23578] regex: Fix memory overread in re_compile_pattern ++ [23579] libc: Errors misreported in preadv2 ++ [23606] Missing ENDBR32 in sysdeps/i386/start.S ++ [23614] powerpc: missing CFI register information in __mpn_* functions ++ [23679] gethostid: Missing NULL check for gethostbyname_r result ++ [23709] Fix CPU string flags for Haswell-type CPUs ++ [23717] Fix stack overflow in stdlib/tst-setcontext9 ++ [23821] si_band in siginfo_t has wrong type long int on sparc64 ++ [23822] ia64 static libm.a is missing exp2f, log2f and powf symbols ++ [23864] libc: [riscv] missing kernel-features.h undefines ++ [23844] pthread_rwlock_trywrlock results in hang ++ [23927] Linux if_nametoindex() does not close descriptor (CVE-2018-19591) ++ [23972] __old_getdents64 uses wrong d_off value on overflow ++ [24018] gettext may return NULL ++ [24022] riscv may lack ++ [24024] strerror() might set errno to ENOMEM due to -fno-math-error ++ [24027] malloc: Integer overflow in realloc ++ [24034] tst-cancel21-static fails with SIGBUS on pre-ARMv7 when using GCC 8 ++ [24040] riscv64: unterminated call chain in __thread_start ++ [24097] Can't use 64-bit register for size_t in assembly codes for x32 (CVE-2019-6488) ++ [24155] x32 memcmp can treat positive length as 0 (if sign bit in RDX is set) (CVE-2019-7309) ++ [24161] __run_fork_handlers self-deadlocks in malloc/tst-mallocfork2 ++ ++Security related changes: ++ ++ CVE-2018-19591: A file descriptor leak in if_nametoindex can lead to a ++ denial of service due to resource exhaustion when processing getaddrinfo ++ calls with crafted host names. Reported by Guido Vranken. ++ ++ CVE-2019-6488: On x32, the size_t parameter may be passed in the lower ++ 32 bits of a 64-bit register with with non-zero upper 32 bit. When it ++ happened, accessing the 32-bit size_t value as the full 64-bit register ++ in the assembly string/memory functions would cause a buffer overflow. ++ Reported by H.J. Lu. ++ ++ CVE-2019-7309: x86-64 memcmp used signed Jcc instructions to check ++ size. For x86-64, memcmp on an object size larger than SSIZE_MAX ++ has undefined behavior. On x32, the size_t argument may be passed ++ in the lower 32 bits of the 64-bit RDX register with non-zero upper ++ 32 bits. When it happened with the sign bit of RDX register set, ++ memcmp gave the wrong result since it treated the size argument as ++ zero. Reported by H.J. Lu. ++ ++ CVE-2016-10739: The getaddrinfo function could successfully parse IPv4 ++ addresses with arbitrary trailing characters, potentially leading to data ++ or command injection issues in applications. ++ ++ CVE-2019-9169: Attempted case-insensitive regular-expression match ++ via proceed_next_node in posix/regexec.c leads to heap-based buffer ++ over-read. Reported by Hongxu Chen. ++ + Version 2.28 + + Major new features: +@@ -422,6 +498,8 @@ The following bugs are resolved with this release: + [23459] libc: COMMON_CPUID_INDEX_80000001 isn't populated for Intel + processors + [23467] dynamic-link: x86/CET: A property note parser bug ++ [24112] network: Do not send DNS queries for non-host names (where all ++ answers will be rejected) + + + Version 2.27 +diff --git a/conform/data/signal.h-data b/conform/data/signal.h-data +index 11e54adb04..674e5793db 100644 +--- a/conform/data/signal.h-data ++++ b/conform/data/signal.h-data +@@ -172,7 +172,8 @@ element siginfo_t pid_t si_pid + element siginfo_t uid_t si_uid + element siginfo_t {void*} si_addr + element siginfo_t int si_status +-element siginfo_t long si_band ++// Bug 23821: si_band has type int on sparc64. ++xfail[sparc64-linux]-element siginfo_t long si_band + # endif + # ifndef XPG42 + element siginfo_t {union sigval} si_value +diff --git a/conform/data/sys/wait.h-data b/conform/data/sys/wait.h-data +index ed3869b34f..c0761424da 100644 +--- a/conform/data/sys/wait.h-data ++++ b/conform/data/sys/wait.h-data +@@ -46,7 +46,8 @@ element siginfo_t pid_t si_pid + element siginfo_t uid_t si_uid + element siginfo_t {void*} si_addr + element siginfo_t int si_status +-element siginfo_t long si_band ++// Bug 23821: si_band has type int on sparc64. ++xfail[sparc64-linux]-element siginfo_t long si_band + # ifndef XPG42 + element siginfo_t {union sigval} si_value + # endif +diff --git a/dlfcn/dlerror.c b/dlfcn/dlerror.c +index 33574faab6..96bf925333 100644 +--- a/dlfcn/dlerror.c ++++ b/dlfcn/dlerror.c +@@ -198,7 +198,10 @@ check_free (struct dl_action_result *rec) + Dl_info info; + if (_dl_addr (check_free, &info, &map, NULL) != 0 && map->l_ns == 0) + #endif +- free ((char *) rec->errstring); ++ { ++ free ((char *) rec->errstring); ++ rec->errstring = NULL; ++ } + } + } + +diff --git a/elf/Makefile b/elf/Makefile +index cd0771307f..6027926bd1 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -186,7 +186,8 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \ + tst-tlsalign tst-tlsalign-extern tst-nodelete-opened \ + tst-nodelete2 tst-audit11 tst-audit12 tst-dlsym-error tst-noload \ + tst-latepthread tst-tls-manydynamic tst-nodelete-dlclose \ +- tst-debug1 tst-main1 tst-absolute-sym tst-absolute-zero tst-big-note ++ tst-debug1 tst-main1 tst-absolute-sym tst-absolute-zero tst-big-note \ ++ tst-unwind-main + # reldep9 + tests-internal += loadtest unload unload2 circleload1 \ + neededtest neededtest2 neededtest3 neededtest4 \ +@@ -1484,3 +1485,5 @@ tst-libc_dlvsym-static-ENV = \ + $(objpfx)tst-libc_dlvsym-static.out: $(objpfx)tst-libc_dlvsym-dso.so + + $(objpfx)tst-big-note: $(objpfx)tst-big-note-lib.so ++ ++CFLAGS-tst-unwind-main.c += -funwind-tables -DUSE_PTHREADS=0 +diff --git a/elf/dl-runtime.c b/elf/dl-runtime.c +index 63bbc89776..3d2f4a7a76 100644 +--- a/elf/dl-runtime.c ++++ b/elf/dl-runtime.c +@@ -183,10 +183,36 @@ _dl_profile_fixup ( + /* This is the address in the array where we store the result of previous + relocations. */ + struct reloc_result *reloc_result = &l->l_reloc_result[reloc_index]; +- DL_FIXUP_VALUE_TYPE *resultp = &reloc_result->addr; + +- DL_FIXUP_VALUE_TYPE value = *resultp; +- if (DL_FIXUP_VALUE_CODE_ADDR (value) == 0) ++ /* CONCURRENCY NOTES: ++ ++ Multiple threads may be calling the same PLT sequence and with ++ LD_AUDIT enabled they will be calling into _dl_profile_fixup to ++ update the reloc_result with the result of the lazy resolution. ++ The reloc_result guard variable is reloc_init, and we use ++ acquire/release loads and store to it to ensure that the results of ++ the structure are consistent with the loaded value of the guard. ++ This does not fix all of the data races that occur when two or more ++ threads read reloc_result->reloc_init with a value of zero and read ++ and write to that reloc_result concurrently. The expectation is ++ generally that while this is a data race it works because the ++ threads write the same values. Until the data races are fixed ++ there is a potential for problems to arise from these data races. ++ The reloc result updates should happen in parallel but there should ++ be an atomic RMW which does the final update to the real result ++ entry (see bug 23790). ++ ++ The following code uses reloc_result->init set to 0 to indicate if it is ++ the first time this object is being relocated, otherwise 1 which ++ indicates the object has already been relocated. ++ ++ Reading/Writing from/to reloc_result->reloc_init must not happen ++ before previous writes to reloc_result complete as they could ++ end-up with an incomplete struct. */ ++ DL_FIXUP_VALUE_TYPE value; ++ unsigned int init = atomic_load_acquire (&reloc_result->init); ++ ++ if (init == 0) + { + /* This is the first time we have to relocate this object. */ + const ElfW(Sym) *const symtab +@@ -346,19 +372,31 @@ _dl_profile_fixup ( + + /* Store the result for later runs. */ + if (__glibc_likely (! GLRO(dl_bind_not))) +- *resultp = value; ++ { ++ reloc_result->addr = value; ++ /* Guarantee all previous writes complete before ++ init is updated. See CONCURRENCY NOTES earlier */ ++ atomic_store_release (&reloc_result->init, 1); ++ } ++ init = 1; + } ++ else ++ value = reloc_result->addr; + + /* By default we do not call the pltexit function. */ + long int framesize = -1; + ++ + #ifdef SHARED + /* Auditing checkpoint: report the PLT entering and allow the + auditors to change the value. */ +- if (DL_FIXUP_VALUE_CODE_ADDR (value) != 0 && GLRO(dl_naudit) > 0 ++ if (GLRO(dl_naudit) > 0 + /* Don't do anything if no auditor wants to intercept this call. */ + && (reloc_result->enterexit & LA_SYMB_NOPLTENTER) == 0) + { ++ /* Sanity check: DL_FIXUP_VALUE_CODE_ADDR (value) should have been ++ initialized earlier in this function or in another thread. */ ++ assert (DL_FIXUP_VALUE_CODE_ADDR (value) != 0); + ElfW(Sym) *defsym = ((ElfW(Sym) *) D_PTR (reloc_result->bound, + l_info[DT_SYMTAB]) + + reloc_result->boundndx); +diff --git a/elf/tst-unwind-main.c b/elf/tst-unwind-main.c +new file mode 100644 +index 0000000000..7c20f04743 +--- /dev/null ++++ b/elf/tst-unwind-main.c +@@ -0,0 +1,60 @@ ++/* Test unwinding through main. ++ 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 ++ . */ ++ ++#include ++#include ++#include ++ ++#if USE_PTHREADS ++# include ++# include ++#endif ++ ++static _Unwind_Reason_Code ++callback (struct _Unwind_Context *ctx, void *arg) ++{ ++ return _URC_NO_REASON; ++} ++ ++static void * ++func (void *a) ++{ ++ /* Arrange for this test to be killed if _Unwind_Backtrace runs into an ++ endless loop. We cannot use the test driver because the complete ++ call chain needs to be compiled with -funwind-tables so that ++ _Unwind_Backtrace is able to reach the start routine. */ ++ alarm (DEFAULT_TIMEOUT); ++ _Unwind_Backtrace (callback, 0); ++ return a; ++} ++ ++int ++main (void) ++{ ++#if USE_PTHREADS ++ pthread_t thr; ++ int rc = pthread_create (&thr, NULL, &func, NULL); ++ if (rc) ++ error (1, rc, "pthread_create"); ++ rc = pthread_join (thr, NULL); ++ if (rc) ++ error (1, rc, "pthread_join"); ++#else ++ func (NULL); ++#endif ++} +diff --git a/grp/initgroups.c b/grp/initgroups.c +index f056fbf5aa..93e7f5814d 100644 +--- a/grp/initgroups.c ++++ b/grp/initgroups.c +@@ -128,7 +128,7 @@ internal_getgrouplist (const char *user, gid_t group, long int *size, + + /* This is really only for debugging. */ + if (NSS_STATUS_TRYAGAIN > status || status > NSS_STATUS_RETURN) +- __libc_fatal ("illegal status in internal_getgrouplist"); ++ __libc_fatal ("Illegal status in internal_getgrouplist.\n"); + + /* For compatibility reason we will continue to look for more + entries using the next service even though data has already +diff --git a/htl/Versions b/htl/Versions +index 6a63a1b8a1..c5a616da10 100644 +--- a/htl/Versions ++++ b/htl/Versions +@@ -150,6 +150,8 @@ libpthread { + __cthread_keycreate; + __cthread_getspecific; + __cthread_setspecific; ++ __pthread_getspecific; ++ __pthread_setspecific; + __pthread_getattr_np; + __pthread_attr_getstack; + } +diff --git a/include/arpa/inet.h b/include/arpa/inet.h +index c3f28f2baa..19aec74275 100644 +--- a/include/arpa/inet.h ++++ b/include/arpa/inet.h +@@ -1,10 +1,10 @@ + #include + + #ifndef _ISOMAC +-extern int __inet_aton (const char *__cp, struct in_addr *__inp); +-libc_hidden_proto (__inet_aton) ++/* Variant of inet_aton which rejects trailing garbage. */ ++extern int __inet_aton_exact (const char *__cp, struct in_addr *__inp); ++libc_hidden_proto (__inet_aton_exact) + +-libc_hidden_proto (inet_aton) + libc_hidden_proto (inet_ntop) + libc_hidden_proto (inet_pton) + extern __typeof (inet_pton) __inet_pton; +diff --git a/include/link.h b/include/link.h +index 5924594548..83b1c34b7b 100644 +--- a/include/link.h ++++ b/include/link.h +@@ -216,6 +216,10 @@ struct link_map + unsigned int boundndx; + uint32_t enterexit; + unsigned int flags; ++ /* CONCURRENCY NOTE: This is used to guard the concurrent initialization ++ of the relocation result across multiple threads. See the more ++ detailed notes in elf/dl-runtime.c. */ ++ unsigned int init; + } *l_reloc_result; + + /* Pointer to the version information if available. */ +diff --git a/include/stdio.h b/include/stdio.h +index 9162d4e247..7a5c09089f 100644 +--- a/include/stdio.h ++++ b/include/stdio.h +@@ -98,7 +98,8 @@ enum __libc_message_action + do_backtrace = 1 << 1 /* Backtrace. */ + }; + +-/* Print out MESSAGE on the error output and abort. */ ++/* Print out MESSAGE (which should end with a newline) on the error output ++ and abort. */ + extern void __libc_fatal (const char *__message) + __attribute__ ((__noreturn__)); + extern void __libc_message (enum __libc_message_action action, +diff --git a/inet/Makefile b/inet/Makefile +index 09f5ba78fc..7782913b4c 100644 +--- a/inet/Makefile ++++ b/inet/Makefile +@@ -52,7 +52,7 @@ aux := check_pf check_native ifreq + tests := htontest test_ifindex tst-ntoa tst-ether_aton tst-network \ + tst-gethnm test-ifaddrs bug-if1 test-inet6_opt tst-ether_line \ + tst-getni1 tst-getni2 tst-inet6_rth tst-checks tst-checks-posix \ +- tst-sockaddr test-hnto-types ++ tst-sockaddr test-hnto-types tst-if_index-long + + # tst-deadline must be linked statically so that we can access + # internal functions. +diff --git a/inet/tst-if_index-long.c b/inet/tst-if_index-long.c +new file mode 100644 +index 0000000000..3dc74874e5 +--- /dev/null ++++ b/inet/tst-if_index-long.c +@@ -0,0 +1,61 @@ ++/* Check for descriptor leak in if_nametoindex with a long interface name. ++ 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 ++ . */ ++ ++/* This test checks for a descriptor leak in case of a long interface ++ name (CVE-2018-19591, bug 23927). */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static int ++do_test (void) ++{ ++ struct support_descriptors *descrs = support_descriptors_list (); ++ ++ /* Prepare a name which is just as long as required for trigging the ++ bug. */ ++ char name[IFNAMSIZ + 1]; ++ memset (name, 'A', IFNAMSIZ); ++ name[IFNAMSIZ] = '\0'; ++ TEST_COMPARE (strlen (name), IFNAMSIZ); ++ struct ifreq ifr; ++ TEST_COMPARE (strlen (name), sizeof (ifr.ifr_name)); ++ ++ /* Test directly via if_nametoindex. */ ++ TEST_COMPARE (if_nametoindex (name), 0); ++ TEST_COMPARE (errno, ENODEV); ++ support_descriptors_check (descrs); ++ ++ /* Same test via getaddrinfo. */ ++ char *host = xasprintf ("fea0::%%%s", name); ++ struct addrinfo hints = { .ai_flags = AI_NUMERICHOST, }; ++ struct addrinfo *ai; ++ TEST_COMPARE (getaddrinfo (host, NULL, &hints, &ai), EAI_NONAME); ++ support_descriptors_check (descrs); ++ ++ support_descriptors_free (descrs); ++ ++ return 0; ++} ++ ++#include +diff --git a/intl/dcigettext.c b/intl/dcigettext.c +index 2a50369948..25f47c5bd3 100644 +--- a/intl/dcigettext.c ++++ b/intl/dcigettext.c +@@ -631,7 +631,7 @@ DCIGETTEXT (const char *domainname, const char *msgid1, const char *msgid2, + int ret = __asprintf (&xdirname, "%s/%s", cwd, dirname); + free (cwd); + if (ret < 0) +- return NULL; ++ goto return_untranslated; + dirname = xdirname; + } + #ifndef IN_LIBGLOCALE +diff --git a/libio/tst-readline.c b/libio/tst-readline.c +index 9322ef68da..63f5227760 100644 +--- a/libio/tst-readline.c ++++ b/libio/tst-readline.c +@@ -232,5 +232,6 @@ do_test (void) + return 0; + } + ++#define TIMEOUT 100 + #define PREPARE prepare + #include +diff --git a/localedata/locales/kl_GL b/localedata/locales/kl_GL +index 5ab14a31aa..5723ce7dcf 100644 +--- a/localedata/locales/kl_GL ++++ b/localedata/locales/kl_GL +@@ -70,11 +70,11 @@ copy "da_DK" + END LC_NUMERIC + + LC_TIME +-abday "sab";"ata";/ ++abday "sap";"ata";/ + "mar";"pin";/ + "sis";"tal";/ + "arf" +-day "sabaat";/ ++day "sapaat";/ + "ataasinngorneq";/ + "marlunngorneq";/ + "pingasunngorneq";/ +diff --git a/malloc/Makefile b/malloc/Makefile +index 7d54bad866..388cf7e9ee 100644 +--- a/malloc/Makefile ++++ b/malloc/Makefile +@@ -38,6 +38,7 @@ tests := mallocbug tst-malloc tst-valloc tst-calloc tst-obstack \ + tst-malloc_info \ + tst-malloc-too-large \ + tst-malloc-stats-cancellation \ ++ tst-tcfree1 tst-tcfree2 tst-tcfree3 \ + + tests-static := \ + tst-interpose-static-nothread \ +diff --git a/malloc/malloc.c b/malloc/malloc.c +index e247c77b7d..27cf6137c2 100644 +--- a/malloc/malloc.c ++++ b/malloc/malloc.c +@@ -2888,6 +2888,8 @@ mremap_chunk (mchunkptr p, size_t new_size) + typedef struct tcache_entry + { + struct tcache_entry *next; ++ /* This field exists to detect double frees. */ ++ struct tcache_perthread_struct *key; + } tcache_entry; + + /* There is one of these for each thread, which contains the +@@ -2911,6 +2913,11 @@ tcache_put (mchunkptr chunk, size_t tc_idx) + { + tcache_entry *e = (tcache_entry *) chunk2mem (chunk); + assert (tc_idx < TCACHE_MAX_BINS); ++ ++ /* Mark this chunk as "in the tcache" so the test in _int_free will ++ detect a double free. */ ++ e->key = tcache; ++ + e->next = tcache->entries[tc_idx]; + tcache->entries[tc_idx] = e; + ++(tcache->counts[tc_idx]); +@@ -2926,6 +2933,7 @@ tcache_get (size_t tc_idx) + assert (tcache->entries[tc_idx] > 0); + tcache->entries[tc_idx] = e->next; + --(tcache->counts[tc_idx]); ++ e->key = NULL; + return (void *) e; + } + +@@ -3716,11 +3724,22 @@ _int_malloc (mstate av, size_t bytes) + while ((victim = unsorted_chunks (av)->bk) != unsorted_chunks (av)) + { + bck = victim->bk; +- if (__builtin_expect (chunksize_nomask (victim) <= 2 * SIZE_SZ, 0) +- || __builtin_expect (chunksize_nomask (victim) +- > av->system_mem, 0)) +- malloc_printerr ("malloc(): memory corruption"); + size = chunksize (victim); ++ mchunkptr next = chunk_at_offset (victim, size); ++ ++ if (__glibc_unlikely (size <= 2 * SIZE_SZ) ++ || __glibc_unlikely (size > av->system_mem)) ++ malloc_printerr ("malloc(): invalid size (unsorted)"); ++ if (__glibc_unlikely (chunksize_nomask (next) < 2 * SIZE_SZ) ++ || __glibc_unlikely (chunksize_nomask (next) > av->system_mem)) ++ malloc_printerr ("malloc(): invalid next size (unsorted)"); ++ if (__glibc_unlikely ((prev_size (next) & ~(SIZE_BITS)) != size)) ++ malloc_printerr ("malloc(): mismatching next->prev_size (unsorted)"); ++ if (__glibc_unlikely (bck->fd != victim) ++ || __glibc_unlikely (victim->fd != unsorted_chunks (av))) ++ malloc_printerr ("malloc(): unsorted double linked list corrupted"); ++ if (__glibc_unlikely (prev_inuse(next))) ++ malloc_printerr ("malloc(): invalid next->prev_inuse (unsorted)"); + + /* + If a small request, try to use last remainder if it is the +@@ -4076,6 +4095,9 @@ _int_malloc (mstate av, size_t bytes) + victim = av->top; + size = chunksize (victim); + ++ if (__glibc_unlikely (size > av->system_mem)) ++ malloc_printerr ("malloc(): corrupted top size"); ++ + if ((unsigned long) (size) >= (unsigned long) (nb + MINSIZE)) + { + remainder_size = size - nb; +@@ -4151,13 +4173,33 @@ _int_free (mstate av, mchunkptr p, int have_lock) + #if USE_TCACHE + { + size_t tc_idx = csize2tidx (size); +- +- if (tcache +- && tc_idx < mp_.tcache_bins +- && tcache->counts[tc_idx] < mp_.tcache_count) ++ if (tcache != NULL && tc_idx < mp_.tcache_bins) + { +- tcache_put (p, tc_idx); +- return; ++ /* Check to see if it's already in the tcache. */ ++ tcache_entry *e = (tcache_entry *) chunk2mem (p); ++ ++ /* This test succeeds on double free. However, we don't 100% ++ trust it (it also matches random payload data at a 1 in ++ 2^ chance), so verify it's not an unlikely ++ coincidence before aborting. */ ++ if (__glibc_unlikely (e->key == tcache)) ++ { ++ tcache_entry *tmp; ++ LIBC_PROBE (memory_tcache_double_free, 2, e, tc_idx); ++ for (tmp = tcache->entries[tc_idx]; ++ tmp; ++ tmp = tmp->next) ++ if (tmp == e) ++ malloc_printerr ("free(): double free detected in tcache 2"); ++ /* If we get here, it was a coincidence. We've wasted a ++ few cycles, but don't abort. */ ++ } ++ ++ if (tcache->counts[tc_idx] < mp_.tcache_count) ++ { ++ tcache_put (p, tc_idx); ++ return; ++ } + } + } + #endif +@@ -4278,6 +4320,8 @@ _int_free (mstate av, mchunkptr p, int have_lock) + prevsize = prev_size (p); + size += prevsize; + p = chunk_at_offset(p, -((long) prevsize)); ++ if (__glibc_unlikely (chunksize(p) != prevsize)) ++ malloc_printerr ("corrupted size vs. prev_size while consolidating"); + unlink(av, p, bck, fwd); + } + +@@ -4439,6 +4483,8 @@ static void malloc_consolidate(mstate av) + prevsize = prev_size (p); + size += prevsize; + p = chunk_at_offset(p, -((long) prevsize)); ++ if (__glibc_unlikely (chunksize(p) != prevsize)) ++ malloc_printerr ("corrupted size vs. prev_size in fastbins"); + unlink(av, p, bck, fwd); + } + +@@ -4498,11 +4544,6 @@ _int_realloc(mstate av, mchunkptr oldp, INTERNAL_SIZE_T oldsize, + mchunkptr bck; /* misc temp for linking */ + mchunkptr fwd; /* misc temp for linking */ + +- unsigned long copysize; /* bytes to copy */ +- unsigned int ncopies; /* INTERNAL_SIZE_T words to copy */ +- INTERNAL_SIZE_T* s; /* copy source */ +- INTERNAL_SIZE_T* d; /* copy destination */ +- + /* oldmem size */ + if (__builtin_expect (chunksize_nomask (oldp) <= 2 * SIZE_SZ, 0) + || __builtin_expect (oldsize >= av->system_mem, 0)) +@@ -4570,43 +4611,7 @@ _int_realloc(mstate av, mchunkptr oldp, INTERNAL_SIZE_T oldsize, + } + else + { +- /* +- Unroll copy of <= 36 bytes (72 if 8byte sizes) +- We know that contents have an odd number of +- INTERNAL_SIZE_T-sized words; minimally 3. +- */ +- +- copysize = oldsize - SIZE_SZ; +- s = (INTERNAL_SIZE_T *) (chunk2mem (oldp)); +- d = (INTERNAL_SIZE_T *) (newmem); +- ncopies = copysize / sizeof (INTERNAL_SIZE_T); +- assert (ncopies >= 3); +- +- if (ncopies > 9) +- memcpy (d, s, copysize); +- +- else +- { +- *(d + 0) = *(s + 0); +- *(d + 1) = *(s + 1); +- *(d + 2) = *(s + 2); +- if (ncopies > 4) +- { +- *(d + 3) = *(s + 3); +- *(d + 4) = *(s + 4); +- if (ncopies > 6) +- { +- *(d + 5) = *(s + 5); +- *(d + 6) = *(s + 6); +- if (ncopies > 8) +- { +- *(d + 7) = *(s + 7); +- *(d + 8) = *(s + 8); +- } +- } +- } +- } +- ++ memcpy (newmem, chunk2mem (oldp), oldsize - SIZE_SZ); + _int_free (av, oldp, 1); + check_inuse_chunk (av, newp); + return chunk2mem (newp); +diff --git a/malloc/tst-tcfree1.c b/malloc/tst-tcfree1.c +new file mode 100644 +index 0000000000..bc29375ce7 +--- /dev/null ++++ b/malloc/tst-tcfree1.c +@@ -0,0 +1,42 @@ ++/* Test that malloc tcache catches double free. ++ 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 ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static int ++do_test (void) ++{ ++ /* Do one allocation of any size that fits in tcache. */ ++ char * volatile x = malloc (32); ++ ++ free (x); // puts in tcache ++ free (x); // should abort ++ ++ printf("FAIL: tcache double free not detected\n"); ++ return 1; ++} ++ ++#define TEST_FUNCTION do_test ++#define EXPECTED_SIGNAL SIGABRT ++#include +diff --git a/malloc/tst-tcfree2.c b/malloc/tst-tcfree2.c +new file mode 100644 +index 0000000000..17f06bacd4 +--- /dev/null ++++ b/malloc/tst-tcfree2.c +@@ -0,0 +1,48 @@ ++/* Test that malloc tcache catches double free. ++ 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 ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static int ++do_test (void) ++{ ++ char * volatile ptrs[20]; ++ int i; ++ ++ /* Allocate enough small chunks so that when we free them all, the tcache ++ is full, and the first one we freed is at the end of its linked list. */ ++#define COUNT 20 ++ for (i=0; i +diff --git a/malloc/tst-tcfree3.c b/malloc/tst-tcfree3.c +new file mode 100644 +index 0000000000..016d30ddd8 +--- /dev/null ++++ b/malloc/tst-tcfree3.c +@@ -0,0 +1,56 @@ ++/* Test that malloc tcache catches double free. ++ 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 ++ . */ ++ ++#include ++#include ++ ++/* Prevent GCC from optimizing away any malloc/free pairs. */ ++#pragma GCC optimize ("O0") ++ ++static int ++do_test (void) ++{ ++ /* Do two allocation of any size that fit in tcache, and one that ++ doesn't. */ ++ int ** volatile a = malloc (32); ++ int ** volatile b = malloc (32); ++ /* This is just under the mmap threshold. */ ++ int ** volatile c = malloc (127 * 1024); ++ ++ /* The invalid "tcache bucket" we might dereference will likely end ++ up somewhere within this memory block, so make all the accidental ++ "next" pointers cause segfaults. BZ #23907. */ ++ memset (c, 0xff, 127 * 1024); ++ ++ free (a); // puts in tcache ++ ++ /* A is now free and contains the key we use to detect in-tcache. ++ Copy the key to the other chunks. */ ++ memcpy (b, a, 32); ++ memcpy (c, a, 32); ++ ++ /* This free tests the "are we in the tcache already" loop with a ++ VALID bin but "coincidental" matching key. */ ++ free (b); // should NOT abort ++ /* This free tests the "is it a valid tcache bin" test. */ ++ free (c); // should NOT abort ++ ++ return 0; ++} ++ ++#include +diff --git a/math/libm-test-fma.inc b/math/libm-test-fma.inc +index 5b29fb8201..a7ee409924 100644 +--- a/math/libm-test-fma.inc ++++ b/math/libm-test-fma.inc +@@ -119,32 +119,32 @@ static const struct test_fff_f_data fma_test_data[] = + TEST_fff_f (fma, plus_infty, plus_infty, -min_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), + TEST_fff_f (fma, plus_infty, plus_infty, min_subnorm_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), + TEST_fff_f (fma, plus_infty, plus_infty, -min_subnorm_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), +- TEST_fff_f (fma, plus_infty, plus_infty, max_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), +- TEST_fff_f (fma, plus_infty, plus_infty, -max_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), ++ TEST_fff_f (fma, plus_infty, plus_infty, max_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED|XFAIL_ROUNDING_IBM128_LIBGCC), ++ TEST_fff_f (fma, plus_infty, plus_infty, -max_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED|XFAIL_ROUNDING_IBM128_LIBGCC), + TEST_fff_f (fma, plus_infty, minus_infty, plus_zero, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), + TEST_fff_f (fma, plus_infty, minus_infty, minus_zero, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), + TEST_fff_f (fma, plus_infty, minus_infty, min_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), + TEST_fff_f (fma, plus_infty, minus_infty, -min_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), + TEST_fff_f (fma, plus_infty, minus_infty, min_subnorm_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), + TEST_fff_f (fma, plus_infty, minus_infty, -min_subnorm_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), +- TEST_fff_f (fma, plus_infty, minus_infty, max_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), +- TEST_fff_f (fma, plus_infty, minus_infty, -max_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), ++ TEST_fff_f (fma, plus_infty, minus_infty, max_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED|XFAIL_ROUNDING_IBM128_LIBGCC), ++ TEST_fff_f (fma, plus_infty, minus_infty, -max_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED|XFAIL_ROUNDING_IBM128_LIBGCC), + TEST_fff_f (fma, minus_infty, plus_infty, plus_zero, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), + TEST_fff_f (fma, minus_infty, plus_infty, minus_zero, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), + TEST_fff_f (fma, minus_infty, plus_infty, min_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), + TEST_fff_f (fma, minus_infty, plus_infty, -min_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), + TEST_fff_f (fma, minus_infty, plus_infty, min_subnorm_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), + TEST_fff_f (fma, minus_infty, plus_infty, -min_subnorm_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), +- TEST_fff_f (fma, minus_infty, plus_infty, max_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), +- TEST_fff_f (fma, minus_infty, plus_infty, -max_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), ++ TEST_fff_f (fma, minus_infty, plus_infty, max_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED|XFAIL_ROUNDING_IBM128_LIBGCC), ++ TEST_fff_f (fma, minus_infty, plus_infty, -max_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED|XFAIL_ROUNDING_IBM128_LIBGCC), + TEST_fff_f (fma, minus_infty, minus_infty, plus_zero, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), + TEST_fff_f (fma, minus_infty, minus_infty, minus_zero, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), + TEST_fff_f (fma, minus_infty, minus_infty, min_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), + TEST_fff_f (fma, minus_infty, minus_infty, -min_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), + TEST_fff_f (fma, minus_infty, minus_infty, min_subnorm_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), + TEST_fff_f (fma, minus_infty, minus_infty, -min_subnorm_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), +- TEST_fff_f (fma, minus_infty, minus_infty, max_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), +- TEST_fff_f (fma, minus_infty, minus_infty, -max_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), ++ TEST_fff_f (fma, minus_infty, minus_infty, max_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED|XFAIL_ROUNDING_IBM128_LIBGCC), ++ TEST_fff_f (fma, minus_infty, minus_infty, -max_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED|XFAIL_ROUNDING_IBM128_LIBGCC), + + AUTO_TESTS_fff_f (fma), + }; +diff --git a/misc/Makefile b/misc/Makefile +index b7be2bc19a..c9f81515ac 100644 +--- a/misc/Makefile ++++ b/misc/Makefile +@@ -86,6 +86,11 @@ tests := tst-dirname tst-tsearch tst-fdset tst-efgcvt tst-mntent tst-hsearch \ + tst-preadvwritev tst-preadvwritev64 tst-makedev tst-empty \ + tst-preadvwritev2 tst-preadvwritev64v2 + ++# Tests which need libdl. ++ifeq (yes,$(build-shared)) ++tests += tst-gethostid ++endif ++ + tests-internal := tst-atomic tst-atomic-long tst-allocate_once + tests-static := tst-empty + +@@ -145,3 +150,5 @@ tst-allocate_once-ENV = MALLOC_TRACE=$(objpfx)tst-allocate_once.mtrace + $(objpfx)tst-allocate_once-mem.out: $(objpfx)tst-allocate_once.out + $(common-objpfx)malloc/mtrace $(objpfx)tst-allocate_once.mtrace > $@; \ + $(evaluate-test) ++ ++$(objpfx)tst-gethostid: $(libdl) +diff --git a/misc/error.c b/misc/error.c +index b4e8b6c938..03378e2f2a 100644 +--- a/misc/error.c ++++ b/misc/error.c +@@ -319,6 +319,7 @@ error (int status, int errnum, const char *message, ...) + + va_start (args, message); + error_tail (status, errnum, message, args); ++ va_end (args); + + #ifdef _LIBC + _IO_funlockfile (stderr); +@@ -390,6 +391,7 @@ error_at_line (int status, int errnum, const char *file_name, + + va_start (args, message); + error_tail (status, errnum, message, args); ++ va_end (args); + + #ifdef _LIBC + _IO_funlockfile (stderr); +diff --git a/misc/tst-gethostid.c b/misc/tst-gethostid.c +new file mode 100644 +index 0000000000..1490aaf3f5 +--- /dev/null ++++ b/misc/tst-gethostid.c +@@ -0,0 +1,108 @@ ++/* Basic test for gethostid. ++ 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 ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* Initial test is run outside a chroot, to increase the likelihood of ++ success. */ ++static void ++outside_chroot (void *closure) ++{ ++ long id = gethostid (); ++ printf ("info: host ID outside chroot: 0x%lx\n", id); ++} ++ ++/* The same, but this time perform a chroot operation. */ ++static void ++in_chroot (void *closure) ++{ ++ const char *chroot_path = closure; ++ xchroot (chroot_path); ++ long id = gethostid (); ++ printf ("info: host ID in chroot: 0x%lx\n", id); ++} ++ ++static int ++do_test (void) ++{ ++ support_isolate_in_subprocess (outside_chroot, NULL); ++ ++ /* Now run the test inside a chroot. */ ++ support_become_root (); ++ if (!support_can_chroot ()) ++ /* Cannot perform further tests. */ ++ return 0; ++ ++ /* Only use nss_files. */ ++ __nss_configure_lookup ("hosts", "files"); ++ ++ /* Load the DSO outside of the chroot. */ ++ xdlopen (LIBNSS_FILES_SO, RTLD_LAZY); ++ ++ char *chroot_dir = support_create_temp_directory ("tst-gethostid-"); ++ support_isolate_in_subprocess (in_chroot, chroot_dir); ++ ++ /* Tests with /etc/hosts in the chroot. */ ++ { ++ char *path = xasprintf ("%s/etc", chroot_dir); ++ add_temp_file (path); ++ xmkdir (path, 0777); ++ free (path); ++ path = xasprintf ("%s/etc/hosts", chroot_dir); ++ add_temp_file (path); ++ ++ FILE *fp = xfopen (path, "w"); ++ xfclose (fp); ++ printf ("info: chroot test with an empty /etc/hosts file\n"); ++ support_isolate_in_subprocess (in_chroot, chroot_dir); ++ ++ char hostname[1024]; ++ int ret = gethostname (hostname, sizeof (hostname)); ++ if (ret < 0) ++ printf ("warning: invalid result from gethostname: %d\n", ret); ++ else if (strlen (hostname) == 0) ++ puts ("warning: gethostname returned empty string"); ++ else ++ { ++ printf ("info: chroot test with IPv6 address in /etc/hosts for: %s\n", ++ hostname); ++ fp = xfopen (path, "w"); ++ /* Use an IPv6 address to induce another lookup failure. */ ++ fprintf (fp, "2001:db8::1 %s\n", hostname); ++ xfclose (fp); ++ support_isolate_in_subprocess (in_chroot, chroot_dir); ++ } ++ free (path); ++ } ++ free (chroot_dir); ++ ++ return 0; ++} ++ ++#include +diff --git a/misc/tst-preadvwritev2-common.c b/misc/tst-preadvwritev2-common.c +index f889a21544..50b9da3fea 100644 +--- a/misc/tst-preadvwritev2-common.c ++++ b/misc/tst-preadvwritev2-common.c +@@ -19,9 +19,6 @@ + #include + #include + +-static void +-do_test_with_invalid_flags (void) +-{ + #ifndef RWF_HIPRI + # define RWF_HIPRI 0 + #endif +@@ -39,6 +36,68 @@ do_test_with_invalid_flags (void) + #endif + #define RWF_SUPPORTED (RWF_HIPRI | RWF_DSYNC | RWF_SYNC | RWF_NOWAIT \ + | RWF_APPEND) ++ ++static void ++do_test_with_invalid_fd (void) ++{ ++ char buf[256]; ++ struct iovec iov = { buf, sizeof buf }; ++ ++ /* Check with flag being 0 to use the fallback code which calls pwritev ++ or writev. */ ++ TEST_VERIFY (preadv2 (-1, &iov, 1, -1, 0) == -1); ++ TEST_COMPARE (errno, EBADF); ++ TEST_VERIFY (pwritev2 (-1, &iov, 1, -1, 0) == -1); ++ TEST_COMPARE (errno, EBADF); ++ ++ /* Same tests as before but with flags being different than 0. Since ++ there is no emulation for any flag value, fallback code returns ++ ENOTSUP. This is different running on a kernel with preadv2/pwritev2 ++ support, where EBADF is returned). */ ++ TEST_VERIFY (preadv2 (-1, &iov, 1, 0, RWF_HIPRI) == -1); ++ TEST_VERIFY (errno == EBADF || errno == ENOTSUP); ++ TEST_VERIFY (pwritev2 (-1, &iov, 1, 0, RWF_HIPRI) == -1); ++ TEST_VERIFY (errno == EBADF || errno == ENOTSUP); ++} ++ ++static void ++do_test_with_invalid_iov (void) ++{ ++ { ++ char buf[256]; ++ struct iovec iov; ++ ++ iov.iov_base = buf; ++ iov.iov_len = (size_t)SSIZE_MAX + 1; ++ ++ TEST_VERIFY (preadv2 (temp_fd, &iov, 1, 0, 0) == -1); ++ TEST_COMPARE (errno, EINVAL); ++ TEST_VERIFY (pwritev2 (temp_fd, &iov, 1, 0, 0) == -1); ++ TEST_COMPARE (errno, EINVAL); ++ ++ /* Same as for invalid file descriptor tests, emulation fallback ++ first checks for flag value and return ENOTSUP. */ ++ TEST_VERIFY (preadv2 (temp_fd, &iov, 1, 0, RWF_HIPRI) == -1); ++ TEST_VERIFY (errno == EINVAL || errno == ENOTSUP); ++ TEST_VERIFY (pwritev2 (temp_fd, &iov, 1, 0, RWF_HIPRI) == -1); ++ TEST_VERIFY (errno == EINVAL || errno == ENOTSUP); ++ } ++ ++ { ++ /* An invalid iovec buffer should trigger an invalid memory access ++ or an error (Linux for instance returns EFAULT). */ ++ struct iovec iov[IOV_MAX+1] = { 0 }; ++ ++ TEST_VERIFY (preadv2 (temp_fd, iov, IOV_MAX + 1, 0, RWF_HIPRI) == -1); ++ TEST_VERIFY (errno == EINVAL || errno == ENOTSUP); ++ TEST_VERIFY (pwritev2 (temp_fd, iov, IOV_MAX + 1, 0, RWF_HIPRI) == -1); ++ TEST_VERIFY (errno == EINVAL || errno == ENOTSUP); ++ } ++} ++ ++static void ++do_test_with_invalid_flags (void) ++{ + /* Set the next bit from the mask of all supported flags. */ + int invalid_flag = RWF_SUPPORTED != 0 ? __builtin_clz (RWF_SUPPORTED) : 2; + invalid_flag = 0x1 << ((sizeof (int) * CHAR_BIT) - invalid_flag); +diff --git a/misc/tst-preadvwritev2.c b/misc/tst-preadvwritev2.c +index be22802dbe..cb58cbe41e 100644 +--- a/misc/tst-preadvwritev2.c ++++ b/misc/tst-preadvwritev2.c +@@ -30,6 +30,8 @@ do_test (void) + { + do_test_with_invalid_flags (); + do_test_without_offset (); ++ do_test_with_invalid_fd (); ++ do_test_with_invalid_iov (); + + return do_test_with_offset (0); + } +diff --git a/misc/tst-preadvwritev64v2.c b/misc/tst-preadvwritev64v2.c +index 8d3cc32b28..6a9de54c78 100644 +--- a/misc/tst-preadvwritev64v2.c ++++ b/misc/tst-preadvwritev64v2.c +@@ -32,6 +32,8 @@ do_test (void) + { + do_test_with_invalid_flags (); + do_test_without_offset (); ++ do_test_with_invalid_fd (); ++ do_test_with_invalid_iov (); + + return do_test_with_offset (0); + } +diff --git a/nptl/Makefile b/nptl/Makefile +index be8066524c..5be7655529 100644 +--- a/nptl/Makefile ++++ b/nptl/Makefile +@@ -241,9 +241,9 @@ LDLIBS-tst-minstack-throw = -lstdc++ + + tests = tst-attr1 tst-attr2 tst-attr3 tst-default-attr \ + tst-mutex1 tst-mutex2 tst-mutex3 tst-mutex4 tst-mutex5 tst-mutex6 \ +- tst-mutex7 tst-mutex9 tst-mutex5a tst-mutex7a tst-mutex7robust \ +- tst-mutexpi1 tst-mutexpi2 tst-mutexpi3 tst-mutexpi4 tst-mutexpi5 \ +- tst-mutexpi5a tst-mutexpi6 tst-mutexpi7 tst-mutexpi7a \ ++ tst-mutex7 tst-mutex9 tst-mutex10 tst-mutex5a tst-mutex7a \ ++ tst-mutex7robust tst-mutexpi1 tst-mutexpi2 tst-mutexpi3 tst-mutexpi4 \ ++ tst-mutexpi5 tst-mutexpi5a tst-mutexpi6 tst-mutexpi7 tst-mutexpi7a \ + tst-mutexpi9 \ + tst-spin1 tst-spin2 tst-spin3 tst-spin4 \ + tst-cond1 tst-cond2 tst-cond3 tst-cond4 tst-cond5 tst-cond6 tst-cond7 \ +@@ -318,7 +318,10 @@ tests = tst-attr1 tst-attr2 tst-attr3 tst-default-attr \ + tst-minstack-throw \ + tst-cnd-basic tst-mtx-trylock tst-cnd-broadcast \ + tst-cnd-timedwait tst-thrd-detach tst-mtx-basic tst-thrd-sleep \ +- tst-mtx-recursive tst-tss-basic tst-call-once tst-mtx-timedlock ++ tst-mtx-recursive tst-tss-basic tst-call-once tst-mtx-timedlock \ ++ tst-rwlock-pwn \ ++ tst-rwlock-tryrdlock-stall tst-rwlock-trywrlock-stall \ ++ tst-unwind-thread + + tests-internal := tst-rwlock19 tst-rwlock20 \ + tst-sem11 tst-sem12 tst-sem13 \ +@@ -382,7 +385,8 @@ tests += tst-cancelx2 tst-cancelx3 tst-cancelx4 tst-cancelx5 \ + tst-cleanupx0 tst-cleanupx1 tst-cleanupx2 tst-cleanupx3 tst-cleanupx4 \ + tst-oncex3 tst-oncex4 + ifeq ($(build-shared),yes) +-tests += tst-atfork2 tst-tls4 tst-_res1 tst-fini1 tst-compat-forwarder ++tests += tst-atfork2 tst-tls4 tst-_res1 tst-fini1 tst-compat-forwarder \ ++ tst-audit-threads + tests-internal += tst-tls3 tst-tls3-malloc tst-tls5 tst-stackguard1 + tests-nolibpthread += tst-fini1 + ifeq ($(have-z-execstack),yes) +@@ -394,7 +398,8 @@ modules-names = tst-atfork2mod tst-tls3mod tst-tls4moda tst-tls4modb \ + tst-tls5mod tst-tls5moda tst-tls5modb tst-tls5modc \ + tst-tls5modd tst-tls5mode tst-tls5modf tst-stack4mod \ + tst-_res1mod1 tst-_res1mod2 tst-execstack-mod tst-fini1mod \ +- tst-join7mod tst-compat-forwarder-mod ++ tst-join7mod tst-compat-forwarder-mod tst-audit-threads-mod1 \ ++ tst-audit-threads-mod2 + extra-test-objs += $(addsuffix .os,$(strip $(modules-names))) \ + tst-cleanup4aux.o tst-cleanupx4aux.o + test-extras += tst-cleanup4aux tst-cleanupx4aux +@@ -709,6 +714,18 @@ endif + + $(objpfx)tst-compat-forwarder: $(objpfx)tst-compat-forwarder-mod.so + ++tst-mutex10-ENV = GLIBC_TUNABLES=glibc.elision.enable=1 ++ ++# Protect against a build using -Wl,-z,now. ++LDFLAGS-tst-audit-threads-mod1.so = -Wl,-z,lazy ++LDFLAGS-tst-audit-threads-mod2.so = -Wl,-z,lazy ++LDFLAGS-tst-audit-threads = -Wl,-z,lazy ++$(objpfx)tst-audit-threads: $(objpfx)tst-audit-threads-mod2.so ++$(objpfx)tst-audit-threads.out: $(objpfx)tst-audit-threads-mod1.so ++tst-audit-threads-ENV = LD_AUDIT=$(objpfx)tst-audit-threads-mod1.so ++ ++CFLAGS-tst-unwind-thread.c += -funwind-tables ++ + # The tests here better do not run in parallel + ifneq ($(filter %tests,$(MAKECMDGOALS)),) + .NOTPARALLEL: +diff --git a/nptl/pthread_cond_wait.c b/nptl/pthread_cond_wait.c +index 3e11054182..ebf07ca82d 100644 +--- a/nptl/pthread_cond_wait.c ++++ b/nptl/pthread_cond_wait.c +@@ -516,7 +516,7 @@ __pthread_cond_wait_common (pthread_cond_t *cond, pthread_mutex_t *mutex, + struct timespec rt; + if (__clock_gettime (CLOCK_MONOTONIC, &rt) != 0) + __libc_fatal ("clock_gettime does not support " +- "CLOCK_MONOTONIC"); ++ "CLOCK_MONOTONIC\n"); + /* Convert the absolute timeout value to a relative + timeout. */ + rt.tv_sec = abstime->tv_sec - rt.tv_sec; +diff --git a/nptl/register-atfork.c b/nptl/register-atfork.c +index 5ff1c1be8c..9edb7d4bbb 100644 +--- a/nptl/register-atfork.c ++++ b/nptl/register-atfork.c +@@ -107,13 +107,14 @@ __unregister_atfork (void *dso_handle) + } + + void +-__run_fork_handlers (enum __run_fork_handler_type who) ++__run_fork_handlers (enum __run_fork_handler_type who, _Bool do_locking) + { + struct fork_handler *runp; + + if (who == atfork_run_prepare) + { +- lll_lock (atfork_lock, LLL_PRIVATE); ++ if (do_locking) ++ lll_lock (atfork_lock, LLL_PRIVATE); + size_t sl = fork_handler_list_size (&fork_handlers); + for (size_t i = sl; i > 0; i--) + { +@@ -133,7 +134,8 @@ __run_fork_handlers (enum __run_fork_handler_type who) + else if (who == atfork_run_parent && runp->parent_handler) + runp->parent_handler (); + } +- lll_unlock (atfork_lock, LLL_PRIVATE); ++ if (do_locking) ++ lll_unlock (atfork_lock, LLL_PRIVATE); + } + } + +diff --git a/nptl/tst-audit-threads-mod1.c b/nptl/tst-audit-threads-mod1.c +new file mode 100644 +index 0000000000..615d5ee512 +--- /dev/null ++++ b/nptl/tst-audit-threads-mod1.c +@@ -0,0 +1,74 @@ ++/* Dummy audit library for test-audit-threads. ++ ++ 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 ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++/* We must use a dummy LD_AUDIT module to force the dynamic loader to ++ *not* update the real PLT, and instead use a cached value for the ++ lazy resolution result. It is the update of that cached value that ++ we are testing for correctness by doing this. */ ++ ++/* Library to be audited. */ ++#define LIB "tst-audit-threads-mod2.so" ++/* CALLNUM is the number of retNum functions. */ ++#define CALLNUM 7999 ++ ++#define CONCATX(a, b) __CONCAT (a, b) ++ ++static int previous = 0; ++ ++unsigned int ++la_version (unsigned int ver) ++{ ++ return 1; ++} ++ ++unsigned int ++la_objopen (struct link_map *map, Lmid_t lmid, uintptr_t *cookie) ++{ ++ return LA_FLG_BINDTO | LA_FLG_BINDFROM; ++} ++ ++uintptr_t ++CONCATX(la_symbind, __ELF_NATIVE_CLASS) (ElfW(Sym) *sym, ++ unsigned int ndx, ++ uintptr_t *refcook, ++ uintptr_t *defcook, ++ unsigned int *flags, ++ const char *symname) ++{ ++ const char * retnum = "retNum"; ++ char * num = strstr (symname, retnum); ++ int n; ++ /* Validate if the symbols are getting called in the correct order. ++ This code is here to verify binutils does not optimize out the PLT ++ entries that require the symbol binding. */ ++ if (num != NULL) ++ { ++ n = atoi (num); ++ assert (n >= previous); ++ assert (n <= CALLNUM); ++ previous = n; ++ } ++ return sym->st_value; ++} +diff --git a/nptl/tst-audit-threads-mod2.c b/nptl/tst-audit-threads-mod2.c +new file mode 100644 +index 0000000000..f9817dd3dc +--- /dev/null ++++ b/nptl/tst-audit-threads-mod2.c +@@ -0,0 +1,22 @@ ++/* Shared object with a huge number of functions for test-audit-threads. ++ ++ 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 ++ . */ ++ ++/* Define all the retNumN functions in a library. */ ++#define definenum ++#include "tst-audit-threads.h" +diff --git a/nptl/tst-audit-threads.c b/nptl/tst-audit-threads.c +new file mode 100644 +index 0000000000..e4bf433bd8 +--- /dev/null ++++ b/nptl/tst-audit-threads.c +@@ -0,0 +1,97 @@ ++/* Test multi-threading using LD_AUDIT. ++ ++ 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 ++ . */ ++ ++/* This test uses a dummy LD_AUDIT library (test-audit-threads-mod1) and a ++ library with a huge number of functions in order to validate lazy symbol ++ binding with an audit library. We use one thread per CPU to test that ++ concurrent lazy resolution does not have any defects which would cause ++ the process to fail. We use an LD_AUDIT library to force the testing of ++ the relocation resolution caching code in the dynamic loader i.e. ++ _dl_runtime_profile and _dl_profile_fixup. */ ++ ++#include ++#include ++#include ++#include ++ ++static int do_test (void); ++ ++/* This test usually takes less than 3s to run. However, there are cases that ++ take up to 30s. */ ++#define TIMEOUT 60 ++#define TEST_FUNCTION do_test () ++#include "../test-skeleton.c" ++ ++/* Declare the functions we are going to call. */ ++#define externnum ++#include "tst-audit-threads.h" ++#undef externnum ++ ++int num_threads; ++pthread_barrier_t barrier; ++ ++void ++sync_all (int num) ++{ ++ pthread_barrier_wait (&barrier); ++} ++ ++void ++call_all_ret_nums (void) ++{ ++ /* Call each function one at a time from all threads. */ ++#define callnum ++#include "tst-audit-threads.h" ++#undef callnum ++} ++ ++void * ++thread_main (void *unused) ++{ ++ call_all_ret_nums (); ++ return NULL; ++} ++ ++#define STR2(X) #X ++#define STR(X) STR2(X) ++ ++static int ++do_test (void) ++{ ++ int i; ++ pthread_t *threads; ++ ++ num_threads = get_nprocs (); ++ if (num_threads <= 1) ++ num_threads = 2; ++ ++ /* Used to synchronize all the threads after calling each retNumN. */ ++ xpthread_barrier_init (&barrier, NULL, num_threads); ++ ++ threads = (pthread_t *) xcalloc (num_threads, sizeof(pthread_t)); ++ for (i = 0; i < num_threads; i++) ++ threads[i] = xpthread_create(NULL, thread_main, NULL); ++ ++ for (i = 0; i < num_threads; i++) ++ xpthread_join(threads[i]); ++ ++ free (threads); ++ ++ return 0; ++} +diff --git a/nptl/tst-audit-threads.h b/nptl/tst-audit-threads.h +new file mode 100644 +index 0000000000..1c9ecc08df +--- /dev/null ++++ b/nptl/tst-audit-threads.h +@@ -0,0 +1,92 @@ ++/* Helper header for test-audit-threads. ++ ++ 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 ++ . */ ++ ++/* We use this helper to create a large number of functions, all of ++ which will be resolved lazily and thus have their PLT updated. ++ This is done to provide enough functions that we can statistically ++ observe a thread vs. PLT resolution failure if one exists. */ ++ ++#define CONCAT(a, b) a ## b ++#define NUM(x, y) CONCAT (x, y) ++ ++#define FUNC10(x) \ ++ FUNC (NUM (x, 0)); \ ++ FUNC (NUM (x, 1)); \ ++ FUNC (NUM (x, 2)); \ ++ FUNC (NUM (x, 3)); \ ++ FUNC (NUM (x, 4)); \ ++ FUNC (NUM (x, 5)); \ ++ FUNC (NUM (x, 6)); \ ++ FUNC (NUM (x, 7)); \ ++ FUNC (NUM (x, 8)); \ ++ FUNC (NUM (x, 9)) ++ ++#define FUNC100(x) \ ++ FUNC10 (NUM (x, 0)); \ ++ FUNC10 (NUM (x, 1)); \ ++ FUNC10 (NUM (x, 2)); \ ++ FUNC10 (NUM (x, 3)); \ ++ FUNC10 (NUM (x, 4)); \ ++ FUNC10 (NUM (x, 5)); \ ++ FUNC10 (NUM (x, 6)); \ ++ FUNC10 (NUM (x, 7)); \ ++ FUNC10 (NUM (x, 8)); \ ++ FUNC10 (NUM (x, 9)) ++ ++#define FUNC1000(x) \ ++ FUNC100 (NUM (x, 0)); \ ++ FUNC100 (NUM (x, 1)); \ ++ FUNC100 (NUM (x, 2)); \ ++ FUNC100 (NUM (x, 3)); \ ++ FUNC100 (NUM (x, 4)); \ ++ FUNC100 (NUM (x, 5)); \ ++ FUNC100 (NUM (x, 6)); \ ++ FUNC100 (NUM (x, 7)); \ ++ FUNC100 (NUM (x, 8)); \ ++ FUNC100 (NUM (x, 9)) ++ ++#define FUNC7000() \ ++ FUNC1000 (1); \ ++ FUNC1000 (2); \ ++ FUNC1000 (3); \ ++ FUNC1000 (4); \ ++ FUNC1000 (5); \ ++ FUNC1000 (6); \ ++ FUNC1000 (7); ++ ++#ifdef FUNC ++# undef FUNC ++#endif ++ ++#ifdef externnum ++# define FUNC(x) extern int CONCAT (retNum, x) (void) ++#endif ++ ++#ifdef definenum ++# define FUNC(x) int CONCAT (retNum, x) (void) { return x; } ++#endif ++ ++#ifdef callnum ++# define FUNC(x) CONCAT (retNum, x) (); sync_all (x) ++#endif ++ ++/* A value of 7000 functions is chosen as an arbitrarily large ++ number of functions that will allow us enough attempts to ++ verify lazy resolution operation. */ ++FUNC7000 (); +diff --git a/nptl/tst-mutex10.c b/nptl/tst-mutex10.c +new file mode 100644 +index 0000000000..e1113ca60a +--- /dev/null ++++ b/nptl/tst-mutex10.c +@@ -0,0 +1,109 @@ ++/* Testing race while enabling lock elision. ++ 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 ++ . */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static pthread_barrier_t barrier; ++static pthread_mutex_t mutex; ++static long long int iteration_count = 1000000; ++static unsigned int thread_count = 3; ++ ++static void * ++thr_func (void *arg) ++{ ++ long long int i; ++ for (i = 0; i < iteration_count; i++) ++ { ++ if ((uintptr_t) arg == 0) ++ { ++ xpthread_mutex_destroy (&mutex); ++ xpthread_mutex_init (&mutex, NULL); ++ } ++ ++ xpthread_barrier_wait (&barrier); ++ ++ /* Test if enabling lock elision works if it is enabled concurrently. ++ There was a race in FORCE_ELISION macro which leads to either ++ pthread_mutex_destroy returning EBUSY as the owner was recorded ++ by pthread_mutex_lock - in "normal mutex" code path - but was not ++ resetted in pthread_mutex_unlock - in "elision" code path. ++ Or it leads to the assertion in nptl/pthread_mutex_lock.c: ++ assert (mutex->__data.__owner == 0); ++ Please ensure that the test is run with lock elision: ++ export GLIBC_TUNABLES=glibc.elision.enable=1 */ ++ xpthread_mutex_lock (&mutex); ++ xpthread_mutex_unlock (&mutex); ++ ++ xpthread_barrier_wait (&barrier); ++ } ++ return NULL; ++} ++ ++static int ++do_test (void) ++{ ++ unsigned int i; ++ printf ("Starting %d threads to run %lld iterations.\n", ++ thread_count, iteration_count); ++ ++ pthread_t *threads = xmalloc (thread_count * sizeof (pthread_t)); ++ xpthread_barrier_init (&barrier, NULL, thread_count); ++ xpthread_mutex_init (&mutex, NULL); ++ ++ for (i = 0; i < thread_count; i++) ++ threads[i] = xpthread_create (NULL, thr_func, (void *) (uintptr_t) i); ++ ++ for (i = 0; i < thread_count; i++) ++ xpthread_join (threads[i]); ++ ++ xpthread_barrier_destroy (&barrier); ++ free (threads); ++ ++ return EXIT_SUCCESS; ++} ++ ++#define OPT_ITERATIONS 10000 ++#define OPT_THREADS 10001 ++#define CMDLINE_OPTIONS \ ++ { "iterations", required_argument, NULL, OPT_ITERATIONS }, \ ++ { "threads", required_argument, NULL, OPT_THREADS }, ++static void ++cmdline_process (int c) ++{ ++ long long int arg = strtoll (optarg, NULL, 0); ++ switch (c) ++ { ++ case OPT_ITERATIONS: ++ if (arg > 0) ++ iteration_count = arg; ++ break; ++ case OPT_THREADS: ++ if (arg > 0 && arg < 100) ++ thread_count = arg; ++ break; ++ } ++} ++#define CMDLINE_PROCESS cmdline_process ++#define TIMEOUT 50 ++#include +diff --git a/nptl/tst-rwlock-pwn.c b/nptl/tst-rwlock-pwn.c +new file mode 100644 +index 0000000000..c39dd70973 +--- /dev/null ++++ b/nptl/tst-rwlock-pwn.c +@@ -0,0 +1,87 @@ ++/* Test rwlock with PREFER_WRITER_NONRECURSIVE_NP (bug 23861). ++ 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 ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++/* We choose 10 iterations because this happens to be able to trigger the ++ stall on contemporary hardware. */ ++#define LOOPS 10 ++/* We need 3 threads to trigger bug 23861. One thread as a writer, and ++ two reader threads. The test verifies that the second-to-last reader ++ is able to notify the *last* reader that it should be done waiting. ++ If the second-to-last reader fails to notify the last reader or does ++ so incorrectly then the last reader may stall indefinitely. */ ++#define NTHREADS 3 ++ ++_Atomic int do_exit; ++pthread_rwlockattr_t mylock_attr; ++pthread_rwlock_t mylock; ++ ++void * ++run_loop (void *a) ++{ ++ while (!do_exit) ++ { ++ if (random () & 1) ++ { ++ xpthread_rwlock_wrlock (&mylock); ++ xpthread_rwlock_unlock (&mylock); ++ } ++ else ++ { ++ xpthread_rwlock_rdlock (&mylock); ++ xpthread_rwlock_unlock (&mylock); ++ } ++ } ++ return NULL; ++} ++ ++int ++do_test (void) ++{ ++ xpthread_rwlockattr_init (&mylock_attr); ++ xpthread_rwlockattr_setkind_np (&mylock_attr, ++ PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP); ++ xpthread_rwlock_init (&mylock, &mylock_attr); ++ ++ for (int n = 0; n < LOOPS; n++) ++ { ++ pthread_t tids[NTHREADS]; ++ do_exit = 0; ++ for (int i = 0; i < NTHREADS; i++) ++ tids[i] = xpthread_create (NULL, run_loop, NULL); ++ /* Let the threads run for some time. */ ++ sleep (1); ++ printf ("Exiting..."); ++ fflush (stdout); ++ do_exit = 1; ++ for (int i = 0; i < NTHREADS; i++) ++ xpthread_join (tids[i]); ++ printf ("done.\n"); ++ } ++ pthread_rwlock_destroy (&mylock); ++ pthread_rwlockattr_destroy (&mylock_attr); ++ return 0; ++} ++ ++#define TIMEOUT (DEFAULT_TIMEOUT + 3 * LOOPS) ++#include +diff --git a/nptl/tst-rwlock-tryrdlock-stall.c b/nptl/tst-rwlock-tryrdlock-stall.c +new file mode 100644 +index 0000000000..5e476da2b8 +--- /dev/null ++++ b/nptl/tst-rwlock-tryrdlock-stall.c +@@ -0,0 +1,355 @@ ++/* Bug 23844: Test for pthread_rwlock_tryrdlock stalls. ++ Copyright (C) 2019 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 ++ . */ ++ ++/* For a full analysis see comment: ++ https://sourceware.org/bugzilla/show_bug.cgi?id=23844#c14 ++ ++ Provided here for reference: ++ ++ --- Analysis of pthread_rwlock_tryrdlock() stall --- ++ A read lock begins to execute. ++ ++ In __pthread_rwlock_rdlock_full: ++ ++ We can attempt a read lock, but find that the lock is ++ in a write phase (PTHREAD_RWLOCK_WRPHASE, or WP-bit ++ is set), and the lock is held by a primary writer ++ (PTHREAD_RWLOCK_WRLOCKED is set). In this case we must ++ wait for explicit hand over from the writer to us or ++ one of the other waiters. The read lock threads are ++ about to execute: ++ ++ 341 r = (atomic_fetch_add_acquire (&rwlock->__data.__readers, ++ 342 (1 << PTHREAD_RWLOCK_READER_SHIFT)) ++ 343 + (1 << PTHREAD_RWLOCK_READER_SHIFT)); ++ ++ An unlock beings to execute. ++ ++ Then in __pthread_rwlock_wrunlock: ++ ++ 547 unsigned int r = atomic_load_relaxed (&rwlock->__data.__readers); ++ ... ++ 549 while (!atomic_compare_exchange_weak_release ++ 550 (&rwlock->__data.__readers, &r, ++ 551 ((r ^ PTHREAD_RWLOCK_WRLOCKED) ++ 552 ^ ((r >> PTHREAD_RWLOCK_READER_SHIFT) == 0 ? 0 ++ 553 : PTHREAD_RWLOCK_WRPHASE)))) ++ 554 { ++ ... ++ 556 } ++ ++ We clear PTHREAD_RWLOCK_WRLOCKED, and if there are ++ no readers so we leave the lock in PTHRAD_RWLOCK_WRPHASE. ++ ++ Back in the read lock. ++ ++ The read lock adjusts __readres as above. ++ ++ 383 while ((r & PTHREAD_RWLOCK_WRPHASE) != 0 ++ 384 && (r & PTHREAD_RWLOCK_WRLOCKED) == 0) ++ 385 { ++ ... ++ 390 if (atomic_compare_exchange_weak_acquire (&rwlock->__data.__readers, &r, ++ 391 r ^ PTHREAD_RWLOCK_WRPHASE)) ++ 392 { ++ ++ And then attemps to start the read phase. ++ ++ Assume there happens to be a tryrdlock at this point, noting ++ that PTHREAD_RWLOCK_WRLOCKED is clear, and PTHREAD_RWLOCK_WRPHASE ++ is 1. So the try lock attemps to start the read phase. ++ ++ In __pthread_rwlock_tryrdlock: ++ ++ 44 if ((r & PTHREAD_RWLOCK_WRPHASE) == 0) ++ 45 { ++ ... ++ 49 if (((r & PTHREAD_RWLOCK_WRLOCKED) != 0) ++ 50 && (rwlock->__data.__flags ++ 51 == PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP)) ++ 52 return EBUSY; ++ 53 rnew = r + (1 << PTHREAD_RWLOCK_READER_SHIFT); ++ 54 } ++ ... ++ 89 while (!atomic_compare_exchange_weak_acquire (&rwlock->__data.__readers, ++ 90 &r, rnew)); ++ ++ And succeeds. ++ ++ Back in the write unlock: ++ ++ 557 if ((r >> PTHREAD_RWLOCK_READER_SHIFT) != 0) ++ 558 { ++ ... ++ 563 if ((atomic_exchange_relaxed (&rwlock->__data.__wrphase_futex, 0) ++ 564 & PTHREAD_RWLOCK_FUTEX_USED) != 0) ++ 565 futex_wake (&rwlock->__data.__wrphase_futex, INT_MAX, private); ++ 566 } ++ ++ We note that PTHREAD_RWLOCK_FUTEX_USED is non-zero ++ and don't wake anyone. This is OK because we handed ++ over to the trylock. It will be the trylock's responsibility ++ to wake any waiters. ++ ++ Back in the read lock: ++ ++ The read lock fails to install PTHRAD_REWLOCK_WRPHASE as 0 because ++ the __readers value was adjusted by the trylock, and so it falls through ++ to waiting on the lock for explicit handover from either a new writer ++ or a new reader. ++ ++ 448 int err = futex_abstimed_wait (&rwlock->__data.__wrphase_futex, ++ 449 1 | PTHREAD_RWLOCK_FUTEX_USED, ++ 450 abstime, private); ++ ++ We use PTHREAD_RWLOCK_FUTEX_USED to indicate the futex ++ is in use. ++ ++ At this point we have readers waiting on the read lock ++ to unlock. The wrlock is done. The trylock is finishing ++ the installation of the read phase. ++ ++ 92 if ((r & PTHREAD_RWLOCK_WRPHASE) != 0) ++ 93 { ++ ... ++ 105 atomic_store_relaxed (&rwlock->__data.__wrphase_futex, 0); ++ 106 } ++ ++ The trylock does note that we were the one that ++ installed the read phase, but the comments are not ++ correct, the execution ordering above shows that ++ readers might indeed be waiting, and they are. ++ ++ The atomic_store_relaxed throws away PTHREAD_RWLOCK_FUTEX_USED, ++ and the waiting reader is never worken becuase as noted ++ above it is conditional on the futex being used. ++ ++ The solution is for the trylock thread to inspect ++ PTHREAD_RWLOCK_FUTEX_USED and wake the waiting readers. ++ ++ --- Analysis of pthread_rwlock_trywrlock() stall --- ++ ++ A write lock begins to execute, takes the write lock, ++ and then releases the lock... ++ ++ In pthread_rwlock_wrunlock(): ++ ++ 547 unsigned int r = atomic_load_relaxed (&rwlock->__data.__readers); ++ ... ++ 549 while (!atomic_compare_exchange_weak_release ++ 550 (&rwlock->__data.__readers, &r, ++ 551 ((r ^ PTHREAD_RWLOCK_WRLOCKED) ++ 552 ^ ((r >> PTHREAD_RWLOCK_READER_SHIFT) == 0 ? 0 ++ 553 : PTHREAD_RWLOCK_WRPHASE)))) ++ 554 { ++ ... ++ 556 } ++ ++ ... leaving it in the write phase with zero readers ++ (the case where we leave the write phase in place ++ during a write unlock). ++ ++ A write trylock begins to execute. ++ ++ In __pthread_rwlock_trywrlock: ++ ++ 40 while (((r & PTHREAD_RWLOCK_WRLOCKED) == 0) ++ 41 && (((r >> PTHREAD_RWLOCK_READER_SHIFT) == 0) ++ 42 || (prefer_writer && ((r & PTHREAD_RWLOCK_WRPHASE) != 0)))) ++ 43 { ++ ++ The lock is not locked. ++ ++ There are no readers. ++ ++ 45 if (atomic_compare_exchange_weak_acquire ( ++ 46 &rwlock->__data.__readers, &r, ++ 47 r | PTHREAD_RWLOCK_WRPHASE | PTHREAD_RWLOCK_WRLOCKED)) ++ ++ We atomically install the write phase and we take the ++ exclusive write lock. ++ ++ 48 { ++ 49 atomic_store_relaxed (&rwlock->__data.__writers_futex, 1); ++ ++ We get this far. ++ ++ A reader lock begins to execute. ++ ++ In pthread_rwlock_rdlock: ++ ++ 437 for (;;) ++ 438 { ++ 439 while (((wpf = atomic_load_relaxed (&rwlock->__data.__wrphase_futex)) ++ 440 | PTHREAD_RWLOCK_FUTEX_USED) == (1 | PTHREAD_RWLOCK_FUTEX_USED)) ++ 441 { ++ 442 int private = __pthread_rwlock_get_private (rwlock); ++ 443 if (((wpf & PTHREAD_RWLOCK_FUTEX_USED) == 0) ++ 444 && (!atomic_compare_exchange_weak_relaxed ++ 445 (&rwlock->__data.__wrphase_futex, ++ 446 &wpf, wpf | PTHREAD_RWLOCK_FUTEX_USED))) ++ 447 continue; ++ 448 int err = futex_abstimed_wait (&rwlock->__data.__wrphase_futex, ++ 449 1 | PTHREAD_RWLOCK_FUTEX_USED, ++ 450 abstime, private); ++ ++ We are in a write phase, so the while() on line 439 is true. ++ ++ The value of wpf does not have PTHREAD_RWLOCK_FUTEX_USED set ++ since this is the first reader to lock. ++ ++ The atomic operation sets wpf with PTHREAD_RELOCK_FUTEX_USED ++ on the expectation that this reader will be woken during ++ the handoff. ++ ++ Back in pthread_rwlock_trywrlock: ++ ++ 50 atomic_store_relaxed (&rwlock->__data.__wrphase_futex, 1); ++ 51 atomic_store_relaxed (&rwlock->__data.__cur_writer, ++ 52 THREAD_GETMEM (THREAD_SELF, tid)); ++ 53 return 0; ++ 54 } ++ ... ++ 57 } ++ ++ We write 1 to __wrphase_futex discarding PTHREAD_RWLOCK_FUTEX_USED, ++ and so in the unlock we will not awaken the waiting reader. ++ ++ The solution to this is to realize that if we did not start the write ++ phase we need not write 1 or any other value to __wrphase_futex. ++ This ensures that any readers (which saw __wrphase_futex != 0) can ++ set PTHREAD_RWLOCK_FUTEX_USED and this can be used at unlock to ++ wake them. ++ ++ If we installed the write phase then all other readers are looping ++ here: ++ ++ In __pthread_rwlock_rdlock_full: ++ ++ 437 for (;;) ++ 438 { ++ 439 while (((wpf = atomic_load_relaxed (&rwlock->__data.__wrphase_futex)) ++ 440 | PTHREAD_RWLOCK_FUTEX_USED) == (1 | PTHREAD_RWLOCK_FUTEX_USED)) ++ 441 { ++ ... ++ 508 } ++ ++ waiting for the write phase to be installed or removed before they ++ can begin waiting on __wrphase_futex (part of the algorithm), or ++ taking a concurrent read lock, and thus we can safely write 1 to ++ __wrphase_futex. ++ ++ If we did not install the write phase then the readers may already ++ be waiting on the futex, the original writer wrote 1 to __wrphase_futex ++ as part of starting the write phase, and we cannot also write 1 ++ without loosing the PTHREAD_RWLOCK_FUTEX_USED bit. ++ ++ --- ++ ++ Summary for the pthread_rwlock_tryrdlock() stall: ++ ++ The stall is caused by pthread_rwlock_tryrdlock failing to check ++ that PTHREAD_RWLOCK_FUTEX_USED is set in the __wrphase_futex futex ++ and then waking the futex. ++ ++ The fix for bug 23844 ensures that waiters on __wrphase_futex are ++ correctly woken. Before the fix the test stalls as readers can ++ wait forever on __wrphase_futex. */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* We need only one lock to reproduce the issue. We will need multiple ++ threads to get the exact case where we have a read, try, and unlock ++ all interleaving to produce the case where the readers are waiting ++ and the try fails to wake them. */ ++pthread_rwlock_t onelock; ++ ++/* The number of threads is arbitrary but empirically chosen to have ++ enough threads that we see the condition where waiting readers are ++ not woken by a successful tryrdlock. */ ++#define NTHREADS 32 ++ ++_Atomic int do_exit; ++ ++void * ++run_loop (void *arg) ++{ ++ int i = 0, ret; ++ while (!do_exit) ++ { ++ /* Arbitrarily choose if we are the writer or reader. Choose a ++ high enough ratio of readers to writers to make it likely ++ that readers block (and eventually are susceptable to ++ stalling). ++ ++ If we are a writer, take the write lock, and then unlock. ++ If we are a reader, try the lock, then lock, then unlock. */ ++ if ((i % 8) != 0) ++ xpthread_rwlock_wrlock (&onelock); ++ else ++ { ++ if ((ret = pthread_rwlock_tryrdlock (&onelock)) != 0) ++ { ++ if (ret == EBUSY) ++ xpthread_rwlock_rdlock (&onelock); ++ else ++ exit (EXIT_FAILURE); ++ } ++ } ++ /* Thread does some work and then unlocks. */ ++ xpthread_rwlock_unlock (&onelock); ++ i++; ++ } ++ return NULL; ++} ++ ++int ++do_test (void) ++{ ++ int i; ++ pthread_t tids[NTHREADS]; ++ xpthread_rwlock_init (&onelock, NULL); ++ for (i = 0; i < NTHREADS; i++) ++ tids[i] = xpthread_create (NULL, run_loop, NULL); ++ /* Run for some amount of time. Empirically speaking exercising ++ the stall via pthread_rwlock_tryrdlock is much harder, and on ++ a 3.5GHz 4 core x86_64 VM system it takes somewhere around ++ 20-200s to stall, approaching 100% stall past 200s. We can't ++ wait that long for a regression test so we just test for 20s, ++ and expect the stall to happen with a 5-10% chance (enough for ++ developers to see). */ ++ sleep (20); ++ /* Then exit. */ ++ printf ("INFO: Exiting...\n"); ++ do_exit = 1; ++ /* If any readers stalled then we will timeout waiting for them. */ ++ for (i = 0; i < NTHREADS; i++) ++ xpthread_join (tids[i]); ++ printf ("INFO: Done.\n"); ++ xpthread_rwlock_destroy (&onelock); ++ printf ("PASS: No pthread_rwlock_tryrdlock stalls detected.\n"); ++ return 0; ++} ++ ++#define TIMEOUT 30 ++#include +diff --git a/nptl/tst-rwlock-trywrlock-stall.c b/nptl/tst-rwlock-trywrlock-stall.c +new file mode 100644 +index 0000000000..14d27cbcbc +--- /dev/null ++++ b/nptl/tst-rwlock-trywrlock-stall.c +@@ -0,0 +1,108 @@ ++/* Bug 23844: Test for pthread_rwlock_trywrlock stalls. ++ Copyright (C) 2019 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 ++ . */ ++ ++/* For a full analysis see comments in tst-rwlock-tryrdlock-stall.c. ++ ++ Summary for the pthread_rwlock_trywrlock() stall: ++ ++ The stall is caused by pthread_rwlock_trywrlock setting ++ __wrphase_futex futex to 1 and loosing the ++ PTHREAD_RWLOCK_FUTEX_USED bit. ++ ++ The fix for bug 23844 ensures that waiters on __wrphase_futex are ++ correctly woken. Before the fix the test stalls as readers can ++ wait forever on __wrphase_futex. */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* We need only one lock to reproduce the issue. We will need multiple ++ threads to get the exact case where we have a read, try, and unlock ++ all interleaving to produce the case where the readers are waiting ++ and the try clears the PTHREAD_RWLOCK_FUTEX_USED bit and a ++ subsequent unlock fails to wake them. */ ++pthread_rwlock_t onelock; ++ ++/* The number of threads is arbitrary but empirically chosen to have ++ enough threads that we see the condition where waiting readers are ++ not woken by a successful unlock. */ ++#define NTHREADS 32 ++ ++_Atomic int do_exit; ++ ++void * ++run_loop (void *arg) ++{ ++ int i = 0, ret; ++ while (!do_exit) ++ { ++ /* Arbitrarily choose if we are the writer or reader. Choose a ++ high enough ratio of readers to writers to make it likely ++ that readers block (and eventually are susceptable to ++ stalling). ++ ++ If we are a writer, take the write lock, and then unlock. ++ If we are a reader, try the lock, then lock, then unlock. */ ++ if ((i % 8) != 0) ++ { ++ if ((ret = pthread_rwlock_trywrlock (&onelock)) != 0) ++ { ++ if (ret == EBUSY) ++ xpthread_rwlock_wrlock (&onelock); ++ else ++ exit (EXIT_FAILURE); ++ } ++ } ++ else ++ xpthread_rwlock_rdlock (&onelock); ++ /* Thread does some work and then unlocks. */ ++ xpthread_rwlock_unlock (&onelock); ++ i++; ++ } ++ return NULL; ++} ++ ++int ++do_test (void) ++{ ++ int i; ++ pthread_t tids[NTHREADS]; ++ xpthread_rwlock_init (&onelock, NULL); ++ for (i = 0; i < NTHREADS; i++) ++ tids[i] = xpthread_create (NULL, run_loop, NULL); ++ /* Run for some amount of time. The pthread_rwlock_tryrwlock stall ++ is very easy to trigger and happens in seconds under the test ++ conditions. */ ++ sleep (10); ++ /* Then exit. */ ++ printf ("INFO: Exiting...\n"); ++ do_exit = 1; ++ /* If any readers stalled then we will timeout waiting for them. */ ++ for (i = 0; i < NTHREADS; i++) ++ xpthread_join (tids[i]); ++ printf ("INFO: Done.\n"); ++ xpthread_rwlock_destroy (&onelock); ++ printf ("PASS: No pthread_rwlock_tryrwlock stalls detected.\n"); ++ return 0; ++} ++ ++#include +diff --git a/nptl/tst-unwind-thread.c b/nptl/tst-unwind-thread.c +new file mode 100644 +index 0000000000..d5c38e3709 +--- /dev/null ++++ b/nptl/tst-unwind-thread.c +@@ -0,0 +1,2 @@ ++#define USE_PTHREADS 1 ++#include "../elf/tst-unwind-main.c" +diff --git a/nscd/Makefile b/nscd/Makefile +index b713a84c49..eb23c01a39 100644 +--- a/nscd/Makefile ++++ b/nscd/Makefile +@@ -36,7 +36,7 @@ nscd-modules := nscd connections pwdcache getpwnam_r getpwuid_r grpcache \ + getsrvbynm_r getsrvbypt_r servicescache \ + dbg_log nscd_conf nscd_stat cache mem nscd_setup_thread \ + xmalloc xstrdup aicache initgrcache gai res_hconf \ +- netgroupcache ++ netgroupcache nscd-inet_addr + + ifeq ($(build-nscd)$(have-thread-library),yesyes) + +diff --git a/nscd/gai.c b/nscd/gai.c +index 24bdfee1db..68a4abd30e 100644 +--- a/nscd/gai.c ++++ b/nscd/gai.c +@@ -19,7 +19,6 @@ + + /* This file uses the getaddrinfo code but it compiles it without NSCD + support. We just need a few symbol renames. */ +-#define __inet_aton inet_aton + #define __ioctl ioctl + #define __getsockname getsockname + #define __socket socket +@@ -34,6 +33,12 @@ + #define __getifaddrs getifaddrs + #define __freeifaddrs freeifaddrs + ++/* We do not want to export __inet_aton_exact. Get the prototype and ++ change its visibility to hidden. */ ++#include ++__typeof__ (__inet_aton_exact) __inet_aton_exact ++ __attribute__ ((visibility ("hidden"))); ++ + /* We are nscd, so we don't want to be talking to ourselves. */ + #undef USE_NSCD + +diff --git a/nscd/gethstbynm3_r.c b/nscd/gethstbynm3_r.c +index 7beb9dce9f..f792c4fcd0 100644 +--- a/nscd/gethstbynm3_r.c ++++ b/nscd/gethstbynm3_r.c +@@ -38,8 +38,6 @@ + #define HAVE_LOOKUP_BUFFER 1 + #define HAVE_AF 1 + +-#define __inet_aton inet_aton +- + /* We are nscd, so we don't want to be talking to ourselves. */ + #undef USE_NSCD + +diff --git a/nscd/initgrcache.c b/nscd/initgrcache.c +index 2c74951f57..4764f14a45 100644 +--- a/nscd/initgrcache.c ++++ b/nscd/initgrcache.c +@@ -159,7 +159,7 @@ addinitgroupsX (struct database_dyn *db, int fd, request_header *req, + + /* This is really only for debugging. */ + if (NSS_STATUS_TRYAGAIN > status || status > NSS_STATUS_RETURN) +- __libc_fatal ("illegal status in internal_getgrouplist"); ++ __libc_fatal ("Illegal status in internal_getgrouplist.\n"); + + any_success |= status == NSS_STATUS_SUCCESS; + +diff --git a/nscd/netgroupcache.c b/nscd/netgroupcache.c +index 2b35389cc8..87059fb280 100644 +--- a/nscd/netgroupcache.c ++++ b/nscd/netgroupcache.c +@@ -113,7 +113,8 @@ do_notfound (struct database_dyn *db, int fd, request_header *req, + static time_t + addgetnetgrentX (struct database_dyn *db, int fd, request_header *req, + const char *key, uid_t uid, struct hashentry *he, +- struct datahead *dh, struct dataset **resultp) ++ struct datahead *dh, struct dataset **resultp, ++ void **tofreep) + { + if (__glibc_unlikely (debug_level > 0)) + { +@@ -139,6 +140,7 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req, + size_t group_len = strlen (key) + 1; + struct name_list *first_needed + = alloca (sizeof (struct name_list) + group_len); ++ *tofreep = NULL; + + if (netgroup_database == NULL + && __nss_database_lookup ("netgroup", NULL, NULL, &netgroup_database)) +@@ -151,6 +153,7 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req, + + memset (&data, '\0', sizeof (data)); + buffer = xmalloc (buflen); ++ *tofreep = buffer; + first_needed->next = first_needed; + memcpy (first_needed->name, key, group_len); + data.needed_groups = first_needed; +@@ -439,8 +442,6 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req, + } + + out: +- free (buffer); +- + *resultp = dataset; + + return timeout; +@@ -477,8 +478,12 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req, + group, group_len, + db, uid); + time_t timeout; ++ void *tofree; + if (result != NULL) +- timeout = result->head.timeout; ++ { ++ timeout = result->head.timeout; ++ tofree = NULL; ++ } + else + { + request_header req_get = +@@ -487,7 +492,7 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req, + .key_len = group_len + }; + timeout = addgetnetgrentX (db, -1, &req_get, group, uid, NULL, NULL, +- &result); ++ &result, &tofree); + } + + struct indataset +@@ -560,7 +565,7 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req, + ++dh->nreloads; + if (cacheable) + pthread_rwlock_unlock (&db->lock); +- return timeout; ++ goto out; + } + + if (he == NULL) +@@ -596,17 +601,30 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req, + dh->usable = false; + } + ++ out: ++ free (tofree); + return timeout; + } + + ++static time_t ++addgetnetgrentX_ignore (struct database_dyn *db, int fd, request_header *req, ++ const char *key, uid_t uid, struct hashentry *he, ++ struct datahead *dh) ++{ ++ struct dataset *ignore; ++ void *tofree; ++ time_t timeout = addgetnetgrentX (db, fd, req, key, uid, he, dh, ++ &ignore, &tofree); ++ free (tofree); ++ return timeout; ++} ++ + void + addgetnetgrent (struct database_dyn *db, int fd, request_header *req, + void *key, uid_t uid) + { +- struct dataset *ignore; +- +- addgetnetgrentX (db, fd, req, key, uid, NULL, NULL, &ignore); ++ addgetnetgrentX_ignore (db, fd, req, key, uid, NULL, NULL); + } + + +@@ -619,10 +637,8 @@ readdgetnetgrent (struct database_dyn *db, struct hashentry *he, + .type = GETNETGRENT, + .key_len = he->len + }; +- struct dataset *ignore; +- +- return addgetnetgrentX (db, -1, &req, db->data + he->key, he->owner, he, dh, +- &ignore); ++ return addgetnetgrentX_ignore ++ (db, -1, &req, db->data + he->key, he->owner, he, dh); + } + + +diff --git a/nscd/nscd-inet_addr.c b/nscd/nscd-inet_addr.c +new file mode 100644 +index 0000000000..f366b9567d +--- /dev/null ++++ b/nscd/nscd-inet_addr.c +@@ -0,0 +1,32 @@ ++/* Legacy IPv4 text-to-address functions. Version for nscd. ++ Copyright (C) 2019 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 ++ . */ ++ ++#include ++ ++/* We do not want to export __inet_aton_exact. Get the prototype and ++ change the visibility to hidden. */ ++#include ++__typeof__ (__inet_aton_exact) __inet_aton_exact ++ __attribute__ ((visibility ("hidden"))); ++ ++/* Do not provide definitions of the public symbols exported from ++ libc. */ ++#undef weak_alias ++#define weak_alias(from, to) ++ ++#include +diff --git a/nscd/nscd_conf.c b/nscd/nscd_conf.c +index 265a02434d..7293b795b6 100644 +--- a/nscd/nscd_conf.c ++++ b/nscd/nscd_conf.c +@@ -190,7 +190,10 @@ nscd_parse_file (const char *fname, struct database_dyn dbs[lastdb]) + if (!arg1) + error (0, 0, _("Must specify user name for server-user option")); + else +- server_user = xstrdup (arg1); ++ { ++ free ((char *) server_user); ++ server_user = xstrdup (arg1); ++ } + } + else if (strcmp (entry, "stat-user") == 0) + { +@@ -198,6 +201,7 @@ nscd_parse_file (const char *fname, struct database_dyn dbs[lastdb]) + error (0, 0, _("Must specify user name for stat-user option")); + else + { ++ free ((char *) stat_user); + stat_user = xstrdup (arg1); + + struct passwd *pw = getpwnam (stat_user); +diff --git a/nss/Makefile b/nss/Makefile +index 66fac7f5b8..5209fc0456 100644 +--- a/nss/Makefile ++++ b/nss/Makefile +@@ -65,6 +65,7 @@ ifeq (yes,$(build-shared)) + tests += tst-nss-files-hosts-erange + tests += tst-nss-files-hosts-multi + tests += tst-nss-files-hosts-getent ++tests += tst-nss-files-alias-leak + endif + + # If we have a thread library then we can test cancellation against +@@ -171,3 +172,5 @@ endif + $(objpfx)tst-nss-files-hosts-erange: $(libdl) + $(objpfx)tst-nss-files-hosts-multi: $(libdl) + $(objpfx)tst-nss-files-hosts-getent: $(libdl) ++$(objpfx)tst-nss-files-alias-leak: $(libdl) ++$(objpfx)tst-nss-files-alias-leak.out: $(objpfx)/libnss_files.so +diff --git a/nss/digits_dots.c b/nss/digits_dots.c +index 39bff38865..5441bce16e 100644 +--- a/nss/digits_dots.c ++++ b/nss/digits_dots.c +@@ -29,7 +29,6 @@ + #include "nsswitch.h" + + #ifdef USE_NSCD +-# define inet_aton __inet_aton + # include + #endif + +@@ -160,7 +159,7 @@ __nss_hostname_digits_dots_context (struct resolv_context *ctx, + 255.255.255.255? The test below will succeed + spuriously... ??? */ + if (af == AF_INET) +- ok = __inet_aton (name, (struct in_addr *) host_addr); ++ ok = __inet_aton_exact (name, (struct in_addr *) host_addr); + else + { + assert (af == AF_INET6); +diff --git a/nss/nss_files/files-alias.c b/nss/nss_files/files-alias.c +index cfd34b66b9..35b0bfc5d2 100644 +--- a/nss/nss_files/files-alias.c ++++ b/nss/nss_files/files-alias.c +@@ -221,6 +221,13 @@ get_next_alias (FILE *stream, const char *match, struct aliasent *result, + { + while (! feof_unlocked (listfile)) + { ++ if (room_left < 2) ++ { ++ free (old_line); ++ fclose (listfile); ++ goto no_more_room; ++ } ++ + first_unused[room_left - 1] = '\xff'; + line = fgets_unlocked (first_unused, room_left, + listfile); +@@ -229,6 +236,7 @@ get_next_alias (FILE *stream, const char *match, struct aliasent *result, + if (first_unused[room_left - 1] != '\xff') + { + free (old_line); ++ fclose (listfile); + goto no_more_room; + } + +@@ -256,6 +264,7 @@ get_next_alias (FILE *stream, const char *match, struct aliasent *result, + + __alignof__ (char *))) + { + free (old_line); ++ fclose (listfile); + goto no_more_room; + } + room_left -= ((first_unused - cp) +diff --git a/nss/nsswitch.c b/nss/nsswitch.c +index ee46f24424..3c48b4b85e 100644 +--- a/nss/nsswitch.c ++++ b/nss/nsswitch.c +@@ -235,7 +235,7 @@ __nss_next2 (service_user **ni, const char *fct_name, const char *fct2_name, + /* This is really only for debugging. */ + if (__builtin_expect (NSS_STATUS_TRYAGAIN > status + || status > NSS_STATUS_RETURN, 0)) +- __libc_fatal ("illegal status in __nss_next"); ++ __libc_fatal ("Illegal status in __nss_next.\n"); + + if (nss_next_action (*ni, status) == NSS_ACTION_RETURN) + return 1; +diff --git a/nss/tst-nss-files-alias-leak.c b/nss/tst-nss-files-alias-leak.c +new file mode 100644 +index 0000000000..26d38e2dba +--- /dev/null ++++ b/nss/tst-nss-files-alias-leak.c +@@ -0,0 +1,237 @@ ++/* Check for file descriptor leak in alias :include: processing (bug 23521). ++ 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 ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static struct support_chroot *chroot_env; ++ ++/* Number of the aliases for the "many" user. This must be large ++ enough to trigger reallocation for the pointer array, but result in ++ answers below the maximum size tried in do_test. */ ++enum { many_aliases = 30 }; ++ ++static void ++prepare (int argc, char **argv) ++{ ++ chroot_env = support_chroot_create ++ ((struct support_chroot_configuration) { } ); ++ ++ char *path = xasprintf ("%s/etc/aliases", chroot_env->path_chroot); ++ add_temp_file (path); ++ support_write_file_string ++ (path, ++ "user1: :include:/etc/aliases.user1\n" ++ "user2: :include:/etc/aliases.user2\n" ++ "comment: comment1, :include:/etc/aliases.comment\n" ++ "many: :include:/etc/aliases.many\n"); ++ free (path); ++ ++ path = xasprintf ("%s/etc/aliases.user1", chroot_env->path_chroot); ++ add_temp_file (path); ++ support_write_file_string (path, "alias1\n"); ++ free (path); ++ ++ path = xasprintf ("%s/etc/aliases.user2", chroot_env->path_chroot); ++ add_temp_file (path); ++ support_write_file_string (path, "alias1a, alias2\n"); ++ free (path); ++ ++ path = xasprintf ("%s/etc/aliases.comment", chroot_env->path_chroot); ++ add_temp_file (path); ++ support_write_file_string ++ (path, ++ /* The line must be longer than the line with the :include: ++ directive in /etc/aliases. */ ++ "# Long line. ##############################################\n" ++ "comment2\n"); ++ free (path); ++ ++ path = xasprintf ("%s/etc/aliases.many", chroot_env->path_chroot); ++ add_temp_file (path); ++ FILE *fp = xfopen (path, "w"); ++ for (int i = 0; i < many_aliases; ++i) ++ fprintf (fp, "a%d\n", i); ++ TEST_VERIFY_EXIT (! ferror (fp)); ++ xfclose (fp); ++ free (path); ++} ++ ++/* The names of the users to test. */ ++static const char *users[] = { "user1", "user2", "comment", "many" }; ++ ++static void ++check_aliases (int id, const struct aliasent *e) ++{ ++ TEST_VERIFY_EXIT (id >= 0 || id < array_length (users)); ++ const char *name = users[id]; ++ TEST_COMPARE_BLOB (e->alias_name, strlen (e->alias_name), ++ name, strlen (name)); ++ ++ switch (id) ++ { ++ case 0: ++ TEST_COMPARE (e->alias_members_len, 1); ++ TEST_COMPARE_BLOB (e->alias_members[0], strlen (e->alias_members[0]), ++ "alias1", strlen ("alias1")); ++ break; ++ ++ case 1: ++ TEST_COMPARE (e->alias_members_len, 2); ++ TEST_COMPARE_BLOB (e->alias_members[0], strlen (e->alias_members[0]), ++ "alias1a", strlen ("alias1a")); ++ TEST_COMPARE_BLOB (e->alias_members[1], strlen (e->alias_members[1]), ++ "alias2", strlen ("alias2")); ++ break; ++ ++ case 2: ++ TEST_COMPARE (e->alias_members_len, 2); ++ TEST_COMPARE_BLOB (e->alias_members[0], strlen (e->alias_members[0]), ++ "comment1", strlen ("comment1")); ++ TEST_COMPARE_BLOB (e->alias_members[1], strlen (e->alias_members[1]), ++ "comment2", strlen ("comment2")); ++ break; ++ ++ case 3: ++ TEST_COMPARE (e->alias_members_len, many_aliases); ++ for (int i = 0; i < e->alias_members_len; ++i) ++ { ++ char alias[30]; ++ int len = snprintf (alias, sizeof (alias), "a%d", i); ++ TEST_VERIFY_EXIT (len > 0); ++ TEST_COMPARE_BLOB (e->alias_members[i], strlen (e->alias_members[i]), ++ alias, len); ++ } ++ break; ++ } ++} ++ ++static int ++do_test (void) ++{ ++ /* Make sure we don't try to load the module in the chroot. */ ++ if (dlopen (LIBNSS_FILES_SO, RTLD_NOW) == NULL) ++ FAIL_EXIT1 ("could not load " LIBNSS_FILES_SO ": %s", dlerror ()); ++ ++ /* Some of these descriptors will become unavailable if there is a ++ file descriptor leak. 10 is chosen somewhat arbitrarily. The ++ array must be longer than the number of files opened by nss_files ++ at the same time (currently that number is 2). */ ++ int next_descriptors[10]; ++ for (size_t i = 0; i < array_length (next_descriptors); ++i) ++ { ++ next_descriptors[i] = dup (0); ++ TEST_VERIFY_EXIT (next_descriptors[i] > 0); ++ } ++ for (size_t i = 0; i < array_length (next_descriptors); ++i) ++ xclose (next_descriptors[i]); ++ ++ support_become_root (); ++ if (!support_can_chroot ()) ++ return EXIT_UNSUPPORTED; ++ ++ __nss_configure_lookup ("aliases", "files"); ++ ++ xchroot (chroot_env->path_chroot); ++ ++ /* Attempt various buffer sizes. If the operation succeeds, we ++ expect correct data. */ ++ for (int id = 0; id < array_length (users); ++id) ++ { ++ bool found = false; ++ for (size_t size = 1; size <= 1000; ++size) ++ { ++ void *buffer = malloc (size); ++ struct aliasent result; ++ struct aliasent *res; ++ errno = EINVAL; ++ int ret = getaliasbyname_r (users[id], &result, buffer, size, &res); ++ if (ret == 0) ++ { ++ if (res != NULL) ++ { ++ found = true; ++ check_aliases (id, res); ++ } ++ else ++ { ++ support_record_failure (); ++ printf ("error: failed lookup for user \"%s\", size %zu\n", ++ users[id], size); ++ } ++ } ++ else if (ret != ERANGE) ++ { ++ support_record_failure (); ++ printf ("error: invalid return code %d (user \%s\", size %zu)\n", ++ ret, users[id], size); ++ } ++ free (buffer); ++ ++ /* Make sure that we did not have a file descriptor leak. */ ++ for (size_t i = 0; i < array_length (next_descriptors); ++i) ++ { ++ int new_fd = dup (0); ++ if (new_fd != next_descriptors[i]) ++ { ++ support_record_failure (); ++ printf ("error: descriptor %d at index %zu leaked" ++ " (user \"%s\", size %zu)\n", ++ next_descriptors[i], i, users[id], size); ++ ++ /* Close unexpected descriptor, the leak probing ++ descriptors, and the leaked descriptor ++ next_descriptors[i]. */ ++ xclose (new_fd); ++ for (size_t j = 0; j <= i; ++j) ++ xclose (next_descriptors[j]); ++ goto next_size; ++ } ++ } ++ for (size_t i = 0; i < array_length (next_descriptors); ++i) ++ xclose (next_descriptors[i]); ++ ++ next_size: ++ ; ++ } ++ if (!found) ++ { ++ support_record_failure (); ++ printf ("error: user %s not found\n", users[id]); ++ } ++ } ++ ++ support_chroot_free (chroot_env); ++ return 0; ++} ++ ++#define PREPARE prepare ++#include +diff --git a/posix/Makefile b/posix/Makefile +index 00c62841a2..83162123f9 100644 +--- a/posix/Makefile ++++ b/posix/Makefile +@@ -96,7 +96,7 @@ tests := test-errno tstgetopt testfnm runtests runptests \ + tst-posix_fadvise tst-posix_fadvise64 \ + tst-sysconf-empty-chroot tst-glob_symlinks tst-fexecve \ + tst-glob-tilde test-ssize-max tst-spawn4 bug-regex37 \ +- bug-regex38 ++ bug-regex38 tst-regcomp-truncated + tests-internal := bug-regex5 bug-regex20 bug-regex33 \ + tst-rfc3484 tst-rfc3484-2 tst-rfc3484-3 \ + tst-glob_lstat_compat tst-spawn4-compat +@@ -194,6 +194,7 @@ $(objpfx)tst-regex2.out: $(gen-locales) + $(objpfx)tst-regexloc.out: $(gen-locales) + $(objpfx)tst-rxspencer.out: $(gen-locales) + $(objpfx)tst-rxspencer-no-utf8.out: $(gen-locales) ++$(objpfx)tst-regcomp-truncated.out: $(gen-locales) + endif + + # If we will use the generic uname implementation, we must figure out what +diff --git a/posix/regex_internal.c b/posix/regex_internal.c +index 7f0083b918..b10588f1cc 100644 +--- a/posix/regex_internal.c ++++ b/posix/regex_internal.c +@@ -317,7 +317,7 @@ build_wcs_upper_buffer (re_string_t *pstr) + mbclen = __mbrtowc (&wc, + ((const char *) pstr->raw_mbs + pstr->raw_mbs_idx + + byte_idx), remain_len, &pstr->cur_state); +- if (BE (mbclen < (size_t) -2, 1)) ++ if (BE (0 < mbclen && mbclen < (size_t) -2, 1)) + { + wchar_t wcu = __towupper (wc); + if (wcu != wc) +@@ -386,7 +386,7 @@ build_wcs_upper_buffer (re_string_t *pstr) + else + p = (const char *) pstr->raw_mbs + pstr->raw_mbs_idx + src_idx; + mbclen = __mbrtowc (&wc, p, remain_len, &pstr->cur_state); +- if (BE (mbclen < (size_t) -2, 1)) ++ if (BE (0 < mbclen && mbclen < (size_t) -2, 1)) + { + wchar_t wcu = __towupper (wc); + if (wcu != wc) +diff --git a/posix/regexec.c b/posix/regexec.c +index 73644c2341..06b8487c3e 100644 +--- a/posix/regexec.c ++++ b/posix/regexec.c +@@ -1289,8 +1289,10 @@ proceed_next_node (const re_match_context_t *mctx, Idx nregs, regmatch_t *regs, + else if (naccepted) + { + char *buf = (char *) re_string_get_buffer (&mctx->input); +- if (memcmp (buf + regs[subexp_idx].rm_so, buf + *pidx, +- naccepted) != 0) ++ if (mctx->input.valid_len - *pidx < naccepted ++ || (memcmp (buf + regs[subexp_idx].rm_so, buf + *pidx, ++ naccepted) ++ != 0)) + return -1; + } + } +diff --git a/posix/tst-regcomp-truncated.c b/posix/tst-regcomp-truncated.c +new file mode 100644 +index 0000000000..a4a1581bbc +--- /dev/null ++++ b/posix/tst-regcomp-truncated.c +@@ -0,0 +1,191 @@ ++/* Test compilation of truncated regular expressions. ++ 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 ++ . */ ++ ++/* This test constructs various patterns in an attempt to trigger ++ over-reading the regular expression compiler, such as bug ++ 23578. */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* Locales to test. */ ++static const char locales[][17] = ++ { ++ "C", ++ "en_US.UTF-8", ++ "de_DE.ISO-8859-1", ++ }; ++ ++/* Syntax options. Will be combined with other flags. */ ++static const reg_syntax_t syntaxes[] = ++ { ++ RE_SYNTAX_EMACS, ++ RE_SYNTAX_AWK, ++ RE_SYNTAX_GNU_AWK, ++ RE_SYNTAX_POSIX_AWK, ++ RE_SYNTAX_GREP, ++ RE_SYNTAX_EGREP, ++ RE_SYNTAX_POSIX_EGREP, ++ RE_SYNTAX_POSIX_BASIC, ++ RE_SYNTAX_POSIX_EXTENDED, ++ RE_SYNTAX_POSIX_MINIMAL_EXTENDED, ++ }; ++ ++/* Trailing characters placed after the initial character. */ ++static const char trailing_strings[][4] = ++ { ++ "", ++ "[", ++ "\\", ++ "[\\", ++ "(", ++ "(\\", ++ "\\(", ++ }; ++ ++static int ++do_test (void) ++{ ++ /* Staging buffer for the constructed regular expression. */ ++ char buffer[16]; ++ ++ /* Allocation used to detect over-reading by the regular expression ++ compiler. */ ++ struct support_next_to_fault ntf ++ = support_next_to_fault_allocate (sizeof (buffer)); ++ ++ /* Arbitrary Unicode codepoint at which we stop generating ++ characters. We do not probe the whole range because that would ++ take too long due to combinatorical exploision as the result of ++ combination with other flags. */ ++ static const wchar_t last_character = 0xfff; ++ ++ for (size_t locale_idx = 0; locale_idx < array_length (locales); ++ ++ locale_idx) ++ { ++ if (setlocale (LC_ALL, locales[locale_idx]) == NULL) ++ { ++ support_record_failure (); ++ printf ("error: setlocale (\"%s\"): %m", locales[locale_idx]); ++ continue; ++ } ++ if (test_verbose > 0) ++ printf ("info: testing locale \"%s\"\n", locales[locale_idx]); ++ ++ for (wchar_t wc = 0; wc <= last_character; ++wc) ++ { ++ char *after_wc; ++ if (wc == 0) ++ { ++ /* wcrtomb treats L'\0' in a special way. */ ++ *buffer = '\0'; ++ after_wc = &buffer[1]; ++ } ++ else ++ { ++ mbstate_t ps = { }; ++ size_t ret = wcrtomb (buffer, wc, &ps); ++ if (ret == (size_t) -1) ++ { ++ /* EILSEQ means that the target character set ++ cannot encode the character. */ ++ if (errno != EILSEQ) ++ { ++ support_record_failure (); ++ printf ("error: wcrtomb (0x%x) failed: %m\n", ++ (unsigned) wc); ++ } ++ continue; ++ } ++ TEST_VERIFY_EXIT (ret != 0); ++ after_wc = &buffer[ret]; ++ } ++ ++ for (size_t trailing_idx = 0; ++ trailing_idx < array_length (trailing_strings); ++ ++trailing_idx) ++ { ++ char *after_trailing ++ = stpcpy (after_wc, trailing_strings[trailing_idx]); ++ ++ for (int do_nul = 0; do_nul < 2; ++do_nul) ++ { ++ char *after_nul; ++ if (do_nul) ++ { ++ *after_trailing = '\0'; ++ after_nul = &after_trailing[1]; ++ } ++ else ++ after_nul = after_trailing; ++ ++ size_t length = after_nul - buffer; ++ ++ /* Make sure that the faulting region starts ++ after the used portion of the buffer. */ ++ char *ntf_start = ntf.buffer + sizeof (buffer) - length; ++ memcpy (ntf_start, buffer, length); ++ ++ for (const reg_syntax_t *psyntax = syntaxes; ++ psyntax < array_end (syntaxes); ++psyntax) ++ for (int do_icase = 0; do_icase < 2; ++do_icase) ++ { ++ re_syntax_options = *psyntax; ++ if (do_icase) ++ re_syntax_options |= RE_ICASE; ++ ++ regex_t reg; ++ memset (®, 0, sizeof (reg)); ++ const char *msg = re_compile_pattern ++ (ntf_start, length, ®); ++ if (msg != NULL) ++ { ++ if (test_verbose > 0) ++ { ++ char *quoted = support_quote_blob ++ (buffer, length); ++ printf ("info: compilation failed for pattern" ++ " \"%s\", syntax 0x%lx: %s\n", ++ quoted, re_syntax_options, msg); ++ free (quoted); ++ } ++ } ++ else ++ regfree (®); ++ } ++ } ++ } ++ } ++ } ++ ++ support_next_to_fault_free (&ntf); ++ ++ return 0; ++} ++ ++#include +diff --git a/resolv/Makefile b/resolv/Makefile +index ea395ac3eb..d36eedd34a 100644 +--- a/resolv/Makefile ++++ b/resolv/Makefile +@@ -34,6 +34,9 @@ routines := herror inet_addr inet_ntop inet_pton nsap_addr res_init \ + tests = tst-aton tst-leaks tst-inet_ntop + xtests = tst-leaks2 + ++tests-internal += tst-inet_aton_exact ++ ++ + generate := mtrace-tst-leaks.out tst-leaks.mtrace tst-leaks2.mtrace + + extra-libs := libresolv libnss_dns +@@ -54,8 +57,10 @@ tests += \ + tst-resolv-binary \ + tst-resolv-edns \ + tst-resolv-network \ ++ tst-resolv-nondecimal \ + tst-resolv-res_init-multi \ + tst-resolv-search \ ++ tst-resolv-trailing \ + + # These tests need libdl. + ifeq (yes,$(build-shared)) +@@ -190,9 +195,11 @@ $(objpfx)tst-resolv-res_init-multi: $(objpfx)libresolv.so \ + $(shared-thread-library) + $(objpfx)tst-resolv-res_init-thread: $(libdl) $(objpfx)libresolv.so \ + $(shared-thread-library) ++$(objpfx)tst-resolv-nondecimal: $(objpfx)libresolv.so $(shared-thread-library) + $(objpfx)tst-resolv-qtypes: $(objpfx)libresolv.so $(shared-thread-library) + $(objpfx)tst-resolv-rotate: $(objpfx)libresolv.so $(shared-thread-library) + $(objpfx)tst-resolv-search: $(objpfx)libresolv.so $(shared-thread-library) ++$(objpfx)tst-resolv-trailing: $(objpfx)libresolv.so $(shared-thread-library) + $(objpfx)tst-resolv-threads: \ + $(libdl) $(objpfx)libresolv.so $(shared-thread-library) + $(objpfx)tst-resolv-canonname: \ +diff --git a/resolv/Versions b/resolv/Versions +index b05778d965..9a82704af7 100644 +--- a/resolv/Versions ++++ b/resolv/Versions +@@ -27,6 +27,7 @@ libc { + __h_errno; __resp; + + __res_iclose; ++ __inet_aton_exact; + __inet_pton_length; + __resolv_context_get; + __resolv_context_get_preinit; +diff --git a/resolv/gai_misc.c b/resolv/gai_misc.c +index e7c3b63cc5..80a2cff835 100644 +--- a/resolv/gai_misc.c ++++ b/resolv/gai_misc.c +@@ -261,8 +261,11 @@ __gai_enqueue_request (struct gaicb *gaicbp) + /* We cannot create a thread in the moment and there is + also no thread running. This is a problem. `errno' is + set to EAGAIN if this is only a temporary problem. */ +- assert (lastp->next == newp); +- lastp->next = NULL; ++ assert (requests == newp || lastp->next == newp); ++ if (lastp != NULL) ++ lastp->next = NULL; ++ else ++ requests = NULL; + requests_tail = lastp; + + newp->next = freelist; +diff --git a/resolv/inet_addr.c b/resolv/inet_addr.c +index 022f7ea084..41b6166a5b 100644 +--- a/resolv/inet_addr.c ++++ b/resolv/inet_addr.c +@@ -1,3 +1,21 @@ ++/* Legacy IPv4 text-to-address functions. ++ Copyright (C) 2019 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 ++ . */ ++ + /* + * Copyright (c) 1983, 1990, 1993 + * The Regents of the University of California. All rights reserved. +@@ -78,106 +96,122 @@ + #include + #include + +-/* +- * Ascii internet address interpretation routine. +- * The value returned is in network order. +- */ +-in_addr_t +-__inet_addr(const char *cp) { +- struct in_addr val; +- +- if (__inet_aton(cp, &val)) +- return (val.s_addr); +- return (INADDR_NONE); ++/* Check whether "cp" is a valid ASCII representation of an IPv4 ++ Internet address and convert it to a binary address. Returns 1 if ++ the address is valid, 0 if not. This replaces inet_addr, the ++ return value from which cannot distinguish between failure and a ++ local broadcast address. Write a pointer to the first ++ non-converted character to *endp. */ ++static int ++inet_aton_end (const char *cp, struct in_addr *addr, const char **endp) ++{ ++ static const in_addr_t max[4] = { 0xffffffff, 0xffffff, 0xffff, 0xff }; ++ in_addr_t val; ++ char c; ++ union iaddr ++ { ++ uint8_t bytes[4]; ++ uint32_t word; ++ } res; ++ uint8_t *pp = res.bytes; ++ int digit; ++ ++ int saved_errno = errno; ++ __set_errno (0); ++ ++ res.word = 0; ++ ++ c = *cp; ++ for (;;) ++ { ++ /* Collect number up to ``.''. Values are specified as for C: ++ 0x=hex, 0=octal, isdigit=decimal. */ ++ if (!isdigit (c)) ++ goto ret_0; ++ { ++ char *endp; ++ unsigned long ul = strtoul (cp, &endp, 0); ++ if (ul == ULONG_MAX && errno == ERANGE) ++ goto ret_0; ++ if (ul > 0xfffffffful) ++ goto ret_0; ++ val = ul; ++ digit = cp != endp; ++ cp = endp; ++ } ++ c = *cp; ++ if (c == '.') ++ { ++ /* Internet format: ++ a.b.c.d ++ a.b.c (with c treated as 16 bits) ++ a.b (with b treated as 24 bits). */ ++ if (pp > res.bytes + 2 || val > 0xff) ++ goto ret_0; ++ *pp++ = val; ++ c = *++cp; ++ } ++ else ++ break; ++ } ++ /* Check for trailing characters. */ ++ if (c != '\0' && (!isascii (c) || !isspace (c))) ++ goto ret_0; ++ /* Did we get a valid digit? */ ++ if (!digit) ++ goto ret_0; ++ ++ /* Check whether the last part is in its limits depending on the ++ number of parts in total. */ ++ if (val > max[pp - res.bytes]) ++ goto ret_0; ++ ++ if (addr != NULL) ++ addr->s_addr = res.word | htonl (val); ++ *endp = cp; ++ ++ __set_errno (saved_errno); ++ return 1; ++ ++ ret_0: ++ __set_errno (saved_errno); ++ return 0; + } +-weak_alias (__inet_addr, inet_addr) + +-/* +- * Check whether "cp" is a valid ascii representation +- * of an Internet address and convert to a binary address. +- * Returns 1 if the address is valid, 0 if not. +- * This replaces inet_addr, the return value from which +- * cannot distinguish between failure and a local broadcast address. +- */ + int +-__inet_aton(const char *cp, struct in_addr *addr) ++__inet_aton_exact (const char *cp, struct in_addr *addr) + { +- static const in_addr_t max[4] = { 0xffffffff, 0xffffff, 0xffff, 0xff }; +- in_addr_t val; +- char c; +- union iaddr { +- uint8_t bytes[4]; +- uint32_t word; +- } res; +- uint8_t *pp = res.bytes; +- int digit; +- +- int saved_errno = errno; +- __set_errno (0); +- +- res.word = 0; +- +- c = *cp; +- for (;;) { +- /* +- * Collect number up to ``.''. +- * Values are specified as for C: +- * 0x=hex, 0=octal, isdigit=decimal. +- */ +- if (!isdigit(c)) +- goto ret_0; +- { +- char *endp; +- unsigned long ul = strtoul (cp, (char **) &endp, 0); +- if (ul == ULONG_MAX && errno == ERANGE) +- goto ret_0; +- if (ul > 0xfffffffful) +- goto ret_0; +- val = ul; +- digit = cp != endp; +- cp = endp; +- } +- c = *cp; +- if (c == '.') { +- /* +- * Internet format: +- * a.b.c.d +- * a.b.c (with c treated as 16 bits) +- * a.b (with b treated as 24 bits) +- */ +- if (pp > res.bytes + 2 || val > 0xff) +- goto ret_0; +- *pp++ = val; +- c = *++cp; +- } else +- break; +- } +- /* +- * Check for trailing characters. +- */ +- if (c != '\0' && (!isascii(c) || !isspace(c))) +- goto ret_0; +- /* +- * Did we get a valid digit? +- */ +- if (!digit) +- goto ret_0; +- +- /* Check whether the last part is in its limits depending on +- the number of parts in total. */ +- if (val > max[pp - res.bytes]) +- goto ret_0; +- +- if (addr != NULL) +- addr->s_addr = res.word | htonl (val); ++ struct in_addr val; ++ const char *endp; ++ /* Check that inet_aton_end parsed the entire string. */ ++ if (inet_aton_end (cp, &val, &endp) != 0 && *endp == 0) ++ { ++ *addr = val; ++ return 1; ++ } ++ else ++ return 0; ++} ++libc_hidden_def (__inet_aton_exact) + +- __set_errno (saved_errno); +- return (1); ++/* inet_aton ignores trailing garbage. */ ++int ++__inet_aton_ignore_trailing (const char *cp, struct in_addr *addr) ++{ ++ const char *endp; ++ return inet_aton_end (cp, addr, &endp); ++} ++weak_alias (__inet_aton_ignore_trailing, inet_aton) + +-ret_0: +- __set_errno (saved_errno); +- return (0); ++/* ASCII IPv4 Internet address interpretation routine. The value ++ returned is in network order. */ ++in_addr_t ++__inet_addr (const char *cp) ++{ ++ struct in_addr val; ++ const char *endp; ++ if (inet_aton_end (cp, &val, &endp)) ++ return val.s_addr; ++ return INADDR_NONE; + } +-weak_alias (__inet_aton, inet_aton) +-libc_hidden_def (__inet_aton) +-libc_hidden_weak (inet_aton) ++weak_alias (__inet_addr, inet_addr) +diff --git a/resolv/nss_dns/dns-host.c b/resolv/nss_dns/dns-host.c +index 5dc2829cd1..99c3b61e1c 100644 +--- a/resolv/nss_dns/dns-host.c ++++ b/resolv/nss_dns/dns-host.c +@@ -274,11 +274,26 @@ gethostbyname3_context (struct resolv_context *ctx, + return status; + } + ++/* Verify that the name looks like a host name. There is no point in ++ sending a query which will not produce a usable name in the ++ response. */ ++static enum nss_status ++check_name (const char *name, int *h_errnop) ++{ ++ if (res_hnok (name)) ++ return NSS_STATUS_SUCCESS; ++ *h_errnop = HOST_NOT_FOUND; ++ return NSS_STATUS_NOTFOUND; ++} ++ + enum nss_status + _nss_dns_gethostbyname2_r (const char *name, int af, struct hostent *result, + char *buffer, size_t buflen, int *errnop, + int *h_errnop) + { ++ enum nss_status status = check_name (name, h_errnop); ++ if (status != NSS_STATUS_SUCCESS) ++ return status; + return _nss_dns_gethostbyname3_r (name, af, result, buffer, buflen, errnop, + h_errnop, NULL, NULL); + } +@@ -289,6 +304,9 @@ _nss_dns_gethostbyname_r (const char *name, struct hostent *result, + char *buffer, size_t buflen, int *errnop, + int *h_errnop) + { ++ enum nss_status status = check_name (name, h_errnop); ++ if (status != NSS_STATUS_SUCCESS) ++ return status; + struct resolv_context *ctx = __resolv_context_get (); + if (ctx == NULL) + { +@@ -296,7 +314,7 @@ _nss_dns_gethostbyname_r (const char *name, struct hostent *result, + *h_errnop = NETDB_INTERNAL; + return NSS_STATUS_UNAVAIL; + } +- enum nss_status status = NSS_STATUS_NOTFOUND; ++ status = NSS_STATUS_NOTFOUND; + if (res_use_inet6 ()) + status = gethostbyname3_context (ctx, name, AF_INET6, result, buffer, + buflen, errnop, h_errnop, NULL, NULL); +@@ -313,6 +331,9 @@ _nss_dns_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat, + char *buffer, size_t buflen, int *errnop, + int *herrnop, int32_t *ttlp) + { ++ enum nss_status status = check_name (name, herrnop); ++ if (status != NSS_STATUS_SUCCESS) ++ return status; + struct resolv_context *ctx = __resolv_context_get (); + if (ctx == NULL) + { +@@ -347,7 +368,6 @@ _nss_dns_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat, + int ans2p_malloced = 0; + + int olderr = errno; +- enum nss_status status; + int n = __res_context_search (ctx, name, C_IN, T_QUERY_A_AND_AAAA, + host_buffer.buf->buf, 2048, &host_buffer.ptr, + &ans2p, &nans2p, &resplen2, &ans2p_malloced); +diff --git a/resolv/res_init.c b/resolv/res_init.c +index f5e52cbbb9..94743a252e 100644 +--- a/resolv/res_init.c ++++ b/resolv/res_init.c +@@ -399,8 +399,16 @@ res_vinit_1 (FILE *fp, struct resolv_conf_parser *parser) + cp = parser->buffer + sizeof ("nameserver") - 1; + while (*cp == ' ' || *cp == '\t') + cp++; ++ ++ /* Ignore trailing contents on the name server line. */ ++ { ++ char *el; ++ if ((el = strpbrk (cp, " \t\n")) != NULL) ++ *el = '\0'; ++ } ++ + struct sockaddr *sa; +- if ((*cp != '\0') && (*cp != '\n') && __inet_aton (cp, &a)) ++ if ((*cp != '\0') && (*cp != '\n') && __inet_aton_exact (cp, &a)) + { + sa = allocate_address_v4 (a, NAMESERVER_PORT); + if (sa == NULL) +@@ -410,9 +418,6 @@ res_vinit_1 (FILE *fp, struct resolv_conf_parser *parser) + { + struct in6_addr a6; + char *el; +- +- if ((el = strpbrk (cp, " \t\n")) != NULL) +- *el = '\0'; + if ((el = strchr (cp, SCOPE_DELIMITER)) != NULL) + *el = '\0'; + if ((*cp != '\0') && (__inet_pton (AF_INET6, cp, &a6) > 0)) +@@ -472,7 +477,7 @@ res_vinit_1 (FILE *fp, struct resolv_conf_parser *parser) + char separator = *cp; + *cp = 0; + struct resolv_sortlist_entry e; +- if (__inet_aton (net, &a)) ++ if (__inet_aton_exact (net, &a)) + { + e.addr = a; + if (is_sort_mask (separator)) +@@ -484,7 +489,7 @@ res_vinit_1 (FILE *fp, struct resolv_conf_parser *parser) + cp++; + separator = *cp; + *cp = 0; +- if (__inet_aton (net, &a)) ++ if (__inet_aton_exact (net, &a)) + e.mask = a.s_addr; + else + e.mask = net_mask (e.addr); +diff --git a/resolv/tst-aton.c b/resolv/tst-aton.c +index 08110a007a..eb734d7758 100644 +--- a/resolv/tst-aton.c ++++ b/resolv/tst-aton.c +@@ -1,11 +1,29 @@ ++/* Test legacy IPv4 text-to-address function inet_aton. ++ Copyright (C) 1998-2019 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 ++ . */ ++ ++#include + #include + #include + #include + #include + #include + +- +-static struct tests ++static const struct tests + { + const char *input; + int valid; +@@ -16,6 +34,7 @@ static struct tests + { "-1", 0, 0 }, + { "256", 1, 0x00000100 }, + { "256.", 0, 0 }, ++ { "255a", 0, 0 }, + { "256a", 0, 0 }, + { "0x100", 1, 0x00000100 }, + { "0200.0x123456", 1, 0x80123456 }, +@@ -40,7 +59,12 @@ static struct tests + { "1.2.256.4", 0, 0 }, + { "1.2.3.0x100", 0, 0 }, + { "323543357756889", 0, 0 }, +- { "10.1.2.3.4", 0, 0}, ++ { "10.1.2.3.4", 0, 0 }, ++ { "192.0.2.1", 1, 0xc0000201 }, ++ { "192.0.2.2\nX", 1, 0xc0000202 }, ++ { "192.0.2.3 Y", 1, 0xc0000203 }, ++ { "192.0.2.3Z", 0, 0 }, ++ { "192.000.002.010", 1, 0xc0000208 }, + }; + + +@@ -50,7 +74,7 @@ do_test (void) + int result = 0; + size_t cnt; + +- for (cnt = 0; cnt < sizeof (tests) / sizeof (tests[0]); ++cnt) ++ for (cnt = 0; cnt < array_length (tests); ++cnt) + { + struct in_addr addr; + +@@ -73,5 +97,4 @@ do_test (void) + return result; + } + +-#define TEST_FUNCTION do_test () +-#include "../test-skeleton.c" ++#include +diff --git a/resolv/tst-inet_aton_exact.c b/resolv/tst-inet_aton_exact.c +new file mode 100644 +index 0000000000..0fdfa3d6aa +--- /dev/null ++++ b/resolv/tst-inet_aton_exact.c +@@ -0,0 +1,47 @@ ++/* Test internal legacy IPv4 text-to-address function __inet_aton_exact. ++ Copyright (C) 2019 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 ++ . */ ++ ++#include ++#include ++ ++static int ++do_test (void) ++{ ++ struct in_addr addr = { }; ++ ++ TEST_COMPARE (__inet_aton_exact ("192.0.2.1", &addr), 1); ++ TEST_COMPARE (ntohl (addr.s_addr), 0xC0000201); ++ ++ TEST_COMPARE (__inet_aton_exact ("192.000.002.010", &addr), 1); ++ TEST_COMPARE (ntohl (addr.s_addr), 0xC0000208); ++ TEST_COMPARE (__inet_aton_exact ("0xC0000234", &addr), 1); ++ TEST_COMPARE (ntohl (addr.s_addr), 0xC0000234); ++ ++ /* Trailing content is not accepted. */ ++ TEST_COMPARE (__inet_aton_exact ("192.0.2.2X", &addr), 0); ++ TEST_COMPARE (__inet_aton_exact ("192.0.2.3 Y", &addr), 0); ++ TEST_COMPARE (__inet_aton_exact ("192.0.2.4\nZ", &addr), 0); ++ TEST_COMPARE (__inet_aton_exact ("192.0.2.5\tT", &addr), 0); ++ TEST_COMPARE (__inet_aton_exact ("192.0.2.6 Y", &addr), 0); ++ TEST_COMPARE (__inet_aton_exact ("192.0.2.7\n", &addr), 0); ++ TEST_COMPARE (__inet_aton_exact ("192.0.2.8\t", &addr), 0); ++ ++ return 0; ++} ++ ++#include +diff --git a/resolv/tst-resolv-network.c b/resolv/tst-resolv-network.c +index 4b862d57e6..735e38d0f8 100644 +--- a/resolv/tst-resolv-network.c ++++ b/resolv/tst-resolv-network.c +@@ -149,6 +149,9 @@ handle_code (const struct resolv_response_context *ctx, + resolv_response_add_data (b, &rrtype, sizeof (rrtype)); + } + break; ++ case 104: ++ send_ptr (b, qname, qclass, qtype, "host.example"); ++ break; + default: + FAIL_EXIT1 ("invalid QNAME: %s (code %d)", qname, code); + } +@@ -257,6 +260,9 @@ do_test (void) + "error: TRY_AGAIN\n"); + check_netent ("code103.example", getnetbyname ("code103.example"), + "error: NO_RECOVERY\n"); ++ /* Test bug #17630. */ ++ check_netent ("code104.example", getnetbyname ("code104.example"), ++ "error: TRY_AGAIN\n"); + + /* Lookup by address, success cases. */ + check_reverse (1, +diff --git a/resolv/tst-resolv-nondecimal.c b/resolv/tst-resolv-nondecimal.c +new file mode 100644 +index 0000000000..a0df6f332a +--- /dev/null ++++ b/resolv/tst-resolv-nondecimal.c +@@ -0,0 +1,139 @@ ++/* Test name resolution behavior for octal, hexadecimal IPv4 addresses. ++ Copyright (C) 2019 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 ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static void ++response (const struct resolv_response_context *ctx, ++ struct resolv_response_builder *b, ++ const char *qname, uint16_t qclass, uint16_t qtype) ++{ ++ /* The tests are not supposed send any DNS queries. */ ++ FAIL_EXIT1 ("unexpected DNS query for %s/%d/%d", qname, qclass, qtype); ++} ++ ++static void ++run_query_addrinfo (const char *query, const char *address) ++{ ++ char *quoted_query = support_quote_string (query); ++ ++ struct addrinfo *ai; ++ struct addrinfo hints = ++ { ++ .ai_socktype = SOCK_STREAM, ++ .ai_protocol = IPPROTO_TCP, ++ }; ++ ++ char *context = xasprintf ("getaddrinfo \"%s\" AF_INET", quoted_query); ++ char *expected = xasprintf ("address: STREAM/TCP %s 80\n", address); ++ hints.ai_family = AF_INET; ++ int ret = getaddrinfo (query, "80", &hints, &ai); ++ check_addrinfo (context, ai, ret, expected); ++ if (ret == 0) ++ freeaddrinfo (ai); ++ free (context); ++ ++ context = xasprintf ("getaddrinfo \"%s\" AF_UNSPEC", quoted_query); ++ hints.ai_family = AF_UNSPEC; ++ ret = getaddrinfo (query, "80", &hints, &ai); ++ check_addrinfo (context, ai, ret, expected); ++ if (ret == 0) ++ freeaddrinfo (ai); ++ free (expected); ++ free (context); ++ ++ context = xasprintf ("getaddrinfo \"%s\" AF_INET6", quoted_query); ++ expected = xasprintf ("flags: AI_V4MAPPED\n" ++ "address: STREAM/TCP ::ffff:%s 80\n", ++ address); ++ hints.ai_family = AF_INET6; ++ hints.ai_flags = AI_V4MAPPED; ++ ret = getaddrinfo (query, "80", &hints, &ai); ++ check_addrinfo (context, ai, ret, expected); ++ if (ret == 0) ++ freeaddrinfo (ai); ++ free (expected); ++ free (context); ++ ++ free (quoted_query); ++} ++ ++static void ++run_query (const char *query, const char *address) ++{ ++ char *quoted_query = support_quote_string (query); ++ char *context = xasprintf ("gethostbyname (\"%s\")", quoted_query); ++ char *expected = xasprintf ("name: %s\n" ++ "address: %s\n", query, address); ++ check_hostent (context, gethostbyname (query), expected); ++ free (context); ++ ++ context = xasprintf ("gethostbyname_r \"%s\"", quoted_query); ++ struct hostent storage; ++ char buf[4096]; ++ struct hostent *e = NULL; ++ TEST_COMPARE (gethostbyname_r (query, &storage, buf, sizeof (buf), ++ &e, &h_errno), 0); ++ check_hostent (context, e, expected); ++ free (context); ++ ++ context = xasprintf ("gethostbyname2 (\"%s\", AF_INET)", quoted_query); ++ check_hostent (context, gethostbyname2 (query, AF_INET), expected); ++ free (context); ++ ++ context = xasprintf ("gethostbyname2_r \"%s\" AF_INET", quoted_query); ++ e = NULL; ++ TEST_COMPARE (gethostbyname2_r (query, AF_INET, &storage, buf, sizeof (buf), ++ &e, &h_errno), 0); ++ check_hostent (context, e, expected); ++ free (context); ++ free (expected); ++ ++ free (quoted_query); ++ ++ /* The gethostbyname tests are always valid for getaddrinfo, but not ++ vice versa. */ ++ run_query_addrinfo (query, address); ++} ++ ++static int ++do_test (void) ++{ ++ struct resolv_test *aux = resolv_test_start ++ ((struct resolv_redirect_config) ++ { ++ .response_callback = response, ++ }); ++ ++ run_query ("192.000.002.010", "192.0.2.8"); ++ ++ /* Hexadecimal numbers are not accepted by gethostbyname. */ ++ run_query_addrinfo ("0xc0000210", "192.0.2.16"); ++ run_query_addrinfo ("192.0x234", "192.0.2.52"); ++ ++ resolv_test_end (aux); ++ ++ return 0; ++} ++ ++#include +diff --git a/resolv/tst-resolv-trailing.c b/resolv/tst-resolv-trailing.c +new file mode 100644 +index 0000000000..7504bdae57 +--- /dev/null ++++ b/resolv/tst-resolv-trailing.c +@@ -0,0 +1,136 @@ ++/* Test name resolution behavior with trailing characters. ++ Copyright (C) 2019 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 ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static void ++response (const struct resolv_response_context *ctx, ++ struct resolv_response_builder *b, ++ const char *qname, uint16_t qclass, uint16_t qtype) ++{ ++ /* The tests are not supposed send any DNS queries. */ ++ FAIL_EXIT1 ("unexpected DNS query for %s/%d/%d", qname, qclass, qtype); ++} ++ ++static int ++do_test (void) ++{ ++ struct resolv_test *aux = resolv_test_start ++ ((struct resolv_redirect_config) ++ { ++ .response_callback = response, ++ }); ++ ++ static const char *const queries[] = ++ { ++ "192.0.2.1 ", ++ "192.0.2.2\t", ++ "192.0.2.3\n", ++ "192.0.2.4 X", ++ "192.0.2.5\tY", ++ "192.0.2.6\nZ", ++ "192.0.2. ", ++ "192.0.2.\t", ++ "192.0.2.\n", ++ "192.0.2. X", ++ "192.0.2.\tY", ++ "192.0.2.\nZ", ++ "2001:db8::1 ", ++ "2001:db8::2\t", ++ "2001:db8::3\n", ++ "2001:db8::4 X", ++ "2001:db8::5\tY", ++ "2001:db8::6\nZ", ++ }; ++ for (size_t query_idx = 0; query_idx < array_length (queries); ++query_idx) ++ { ++ const char *query = queries[query_idx]; ++ struct hostent storage; ++ char buf[4096]; ++ struct hostent *e; ++ ++ h_errno = 0; ++ TEST_VERIFY (gethostbyname (query) == NULL); ++ TEST_COMPARE (h_errno, HOST_NOT_FOUND); ++ ++ h_errno = 0; ++ e = NULL; ++ TEST_COMPARE (gethostbyname_r (query, &storage, buf, sizeof (buf), ++ &e, &h_errno), 0); ++ TEST_VERIFY (e == NULL); ++ TEST_COMPARE (h_errno, HOST_NOT_FOUND); ++ ++ h_errno = 0; ++ TEST_VERIFY (gethostbyname2 (query, AF_INET) == NULL); ++ TEST_COMPARE (h_errno, HOST_NOT_FOUND); ++ ++ h_errno = 0; ++ e = NULL; ++ TEST_COMPARE (gethostbyname2_r (query, AF_INET, ++ &storage, buf, sizeof (buf), ++ &e, &h_errno), 0); ++ TEST_VERIFY (e == NULL); ++ TEST_COMPARE (h_errno, HOST_NOT_FOUND); ++ ++ h_errno = 0; ++ TEST_VERIFY (gethostbyname2 (query, AF_INET6) == NULL); ++ TEST_COMPARE (h_errno, HOST_NOT_FOUND); ++ ++ h_errno = 0; ++ e = NULL; ++ TEST_COMPARE (gethostbyname2_r (query, AF_INET6, ++ &storage, buf, sizeof (buf), ++ &e, &h_errno), 0); ++ TEST_VERIFY (e == NULL); ++ TEST_COMPARE (h_errno, HOST_NOT_FOUND); ++ ++ static const int gai_flags[] = ++ { ++ 0, ++ AI_ADDRCONFIG, ++ AI_NUMERICHOST, ++ AI_IDN, ++ AI_IDN | AI_NUMERICHOST, ++ AI_V4MAPPED, ++ AI_V4MAPPED | AI_NUMERICHOST, ++ }; ++ for (size_t gai_flags_idx; gai_flags_idx < array_length (gai_flags); ++ ++gai_flags_idx) ++ { ++ struct addrinfo hints = { .ai_flags = gai_flags[gai_flags_idx], }; ++ struct addrinfo *ai; ++ hints.ai_family = AF_INET; ++ TEST_COMPARE (getaddrinfo (query, "80", &hints, &ai), EAI_NONAME); ++ hints.ai_family = AF_INET6; ++ TEST_COMPARE (getaddrinfo (query, "80", &hints, &ai), EAI_NONAME); ++ hints.ai_family = AF_UNSPEC; ++ TEST_COMPARE (getaddrinfo (query, "80", &hints, &ai), EAI_NONAME); ++ } ++ }; ++ ++ resolv_test_end (aux); ++ ++ return 0; ++} ++ ++#include +diff --git a/stdlib/test-bz22786.c b/stdlib/test-bz22786.c +index e7837f98c1..8035e8a394 100644 +--- a/stdlib/test-bz22786.c ++++ b/stdlib/test-bz22786.c +@@ -26,49 +26,39 @@ + #include + #include + #include ++#include ++#include ++#include ++#include + #include + #include + + 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; ++ char *dir = support_create_temp_directory ("bz22786."); ++ char *lnk = xasprintf ("%s/symlink", dir); ++ const size_t path_len = (size_t) INT_MAX + strlen (lnk) + 1; + ++ struct support_blob_repeat repeat ++ = support_blob_repeat_allocate ("a", 1, path_len); ++ char *path = repeat.start; + if (path == NULL) + { +- printf ("malloc (%zu): %m\n", path_len); ++ printf ("Repeated allocation (%zu bytes): %m\n", path_len); ++ /* On 31-bit s390 the malloc will always fail as we do not have ++ so much memory, and we want to mark the test unsupported. ++ Likewise on systems with little physical memory the test will ++ fail and should be unsupported. */ + return EXIT_UNSUPPORTED; + } + +- /* Construct very long path = "bz22786/symlink/aaaa....." */ +- char *p = mempcpy (path, lnk, sizeof (lnk) - 1); ++ TEST_VERIFY_EXIT (symlink (".", lnk) == 0); ++ ++ /* Construct very long path = "/tmp/bz22786.XXXX/symlink/aaaa....." */ ++ char *p = mempcpy (path, lnk, strlen (lnk)); + *(p++) = '/'; +- memset (p, 'a', path_len - (path - p) - 2); +- p[path_len - (path - p) - 1] = '\0'; ++ p[path_len - (p - path) - 1] = '\0'; + + /* This call crashes before the fix for bz22786 on 32-bit platforms. */ + p = realpath (path, NULL); +@@ -81,7 +71,9 @@ do_test (void) + + /* Cleanup. */ + unlink (lnk); +- rmdir (dir); ++ support_blob_repeat_free (&repeat); ++ free (lnk); ++ free (dir); + + return 0; + } +diff --git a/stdlib/tst-setcontext9.c b/stdlib/tst-setcontext9.c +index 4636ce9030..009928235d 100644 +--- a/stdlib/tst-setcontext9.c ++++ b/stdlib/tst-setcontext9.c +@@ -41,30 +41,59 @@ f2 (void) + } + + static void +-f1 (void) ++f1b (void) + { +- puts ("start f1"); +- if (getcontext (&ctx[2]) != 0) +- { +- printf ("%s: getcontext: %m\n", __FUNCTION__); +- exit (EXIT_FAILURE); +- } + if (done) + { +- puts ("set context in f1"); ++ puts ("set context in f1b"); + if (setcontext (&ctx[3]) != 0) + { + printf ("%s: setcontext: %m\n", __FUNCTION__); + exit (EXIT_FAILURE); + } + } ++ exit (EXIT_FAILURE); ++} ++ ++static void ++f1a (void) ++{ ++ static char st2[32768]; ++ puts ("start f1a"); ++ if (getcontext (&ctx[2]) != 0) ++ { ++ printf ("%s: getcontext: %m\n", __FUNCTION__); ++ exit (EXIT_FAILURE); ++ } ++ ctx[2].uc_stack.ss_sp = st2; ++ ctx[2].uc_stack.ss_size = sizeof st2; ++ ctx[2].uc_link = &ctx[0]; ++ makecontext (&ctx[2], (void (*) (void)) f1b, 0); + f2 (); + } + ++/* The execution path through the test looks like this: ++ do_test (call) ++ -> "making contexts" ++ -> "swap contexts" ++ f1a (via swapcontext to ctx[1], with alternate stack) ++ -> "start f1a" ++ f2 (call) ++ -> "swap contexts in f2" ++ f1b (via swapcontext to ctx[2], with alternate stack) ++ -> "set context in f1b" ++ do_test (via setcontext to ctx[3], main stack) ++ -> "setcontext" ++ f2 (via setcontext to ctx[4], with alternate stack) ++ -> "end f2" ++ ++ We must use an alternate stack for f1b, because if we don't then the ++ result of executing an earlier caller may overwrite registers ++ spilled to the stack in f2. */ + static int + do_test (void) + { +- char st1[32768]; ++ static char st1[32768]; + puts ("making contexts"); + if (getcontext (&ctx[0]) != 0) + { +@@ -79,7 +108,7 @@ do_test (void) + ctx[1].uc_stack.ss_sp = st1; + ctx[1].uc_stack.ss_size = sizeof st1; + ctx[1].uc_link = &ctx[0]; +- makecontext (&ctx[1], (void (*) (void)) f1, 0); ++ makecontext (&ctx[1], (void (*) (void)) f1a, 0); + puts ("swap contexts"); + if (swapcontext (&ctx[3], &ctx[1]) != 0) + { +diff --git a/stdlib/tst-strtod-overflow.c b/stdlib/tst-strtod-overflow.c +index d14638d68e..dc53c1e521 100644 +--- a/stdlib/tst-strtod-overflow.c ++++ b/stdlib/tst-strtod-overflow.c +@@ -19,6 +19,8 @@ + #include + #include + #include ++#include ++#include + + #define EXPONENT "e-2147483649" + #define SIZE 214748364 +@@ -26,21 +28,23 @@ + static int + do_test (void) + { +- char *p = malloc (1 + SIZE + sizeof (EXPONENT)); +- if (p == NULL) ++ struct support_blob_repeat repeat = support_blob_repeat_allocate ++ ("0", 1, 1 + SIZE + sizeof (EXPONENT)); ++ if (repeat.size == 0) + { +- puts ("malloc failed, cannot test for overflow"); +- return 0; ++ puts ("warning: memory allocation failed, cannot test for overflow"); ++ return EXIT_UNSUPPORTED; + } ++ char *p = repeat.start; + p[0] = '1'; +- memset (p + 1, '0', SIZE); + memcpy (p + 1 + SIZE, EXPONENT, sizeof (EXPONENT)); + double d = strtod (p, NULL); + if (d != 0) + { +- printf ("strtod returned wrong value: %a\n", d); ++ printf ("error: strtod returned wrong value: %a\n", d); + return 1; + } ++ support_blob_repeat_free (&repeat); + return 0; + } + +diff --git a/string/Makefile b/string/Makefile +index 680431f921..aa2da9ca72 100644 +--- a/string/Makefile ++++ b/string/Makefile +@@ -64,6 +64,12 @@ tests := tester inl-tester noinl-tester testcopy test-ffs \ + # This test allocates a lot of memory and can run for a long time. + xtests = tst-strcoll-overflow + ++# This test needs libdl. ++ifeq (yes,$(build-shared)) ++tests += test-strerror-errno ++LDLIBS-test-strerror-errno = $(libdl) ++endif ++ + ifeq ($(run-built-tests),yes) + tests-special += $(objpfx)tst-svc-cmp.out + endif +diff --git a/string/strcasestr.c b/string/strcasestr.c +index 5909fe3cdb..421764bd1b 100644 +--- a/string/strcasestr.c ++++ b/string/strcasestr.c +@@ -37,8 +37,9 @@ + /* Two-Way algorithm. */ + #define RETURN_TYPE char * + #define AVAILABLE(h, h_l, j, n_l) \ +- (((j) + (n_l) <= (h_l)) || ((h_l) += __strnlen ((void*)((h) + (h_l)), 512), \ +- (j) + (n_l) <= (h_l))) ++ (((j) + (n_l) <= (h_l)) \ ++ || ((h_l) += __strnlen ((void*)((h) + (h_l)), (n_l) + 512), \ ++ (j) + (n_l) <= (h_l))) + #define CHECK_EOL (1) + #define RET0_IF_0(a) if (!a) goto ret0 + #define CANON_ELEMENT(c) TOLOWER (c) +diff --git a/string/strstr.c b/string/strstr.c +index 265e9f310c..79ebcc7532 100644 +--- a/string/strstr.c ++++ b/string/strstr.c +@@ -33,8 +33,9 @@ + + #define RETURN_TYPE char * + #define AVAILABLE(h, h_l, j, n_l) \ +- (((j) + (n_l) <= (h_l)) || ((h_l) += __strnlen ((void*)((h) + (h_l)), 512), \ +- (j) + (n_l) <= (h_l))) ++ (((j) + (n_l) <= (h_l)) \ ++ || ((h_l) += __strnlen ((void*)((h) + (h_l)), (n_l) + 512), \ ++ (j) + (n_l) <= (h_l))) + #define CHECK_EOL (1) + #define RET0_IF_0(a) if (!a) goto ret0 + #define FASTSEARCH(S,C,N) (void*) strchr ((void*)(S), (C)) +diff --git a/string/test-strerror-errno.c b/string/test-strerror-errno.c +new file mode 100644 +index 0000000000..8e744e7ed9 +--- /dev/null ++++ b/string/test-strerror-errno.c +@@ -0,0 +1,61 @@ ++/* BZ #24024 strerror and errno test. ++ ++ Copyright (C) 2019 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 ++ . */ ++ ++#include ++#include ++#include ++ ++#include ++#include ++ ++/* malloc is allowed to change errno to a value different than 0, even when ++ there is no actual error. This happens for example when the memory ++ allocation through sbrk fails. Simulate this by interposing our own ++ malloc implementation which sets errno to ENOMEM and calls the original ++ malloc. */ ++void ++*malloc (size_t size) ++{ ++ static void *(*real_malloc) (size_t size); ++ ++ if (!real_malloc) ++ real_malloc = dlsym (RTLD_NEXT, "malloc"); ++ ++ errno = ENOMEM; ++ ++ return (*real_malloc) (size); ++} ++ ++/* strerror must not change the value of errno. Unfortunately due to GCC bug ++ #88576, this happens when -fmath-errno is used. This simple test checks ++ that it doesn't happen. */ ++static int ++do_test (void) ++{ ++ char *msg; ++ ++ errno = 0; ++ msg = strerror (-3); ++ (void) msg; ++ TEST_COMPARE (errno, 0); ++ ++ return 0; ++} ++ ++#include +diff --git a/string/test-strstr.c b/string/test-strstr.c +index 8d99716ff3..5861b01b73 100644 +--- a/string/test-strstr.c ++++ b/string/test-strstr.c +@@ -151,6 +151,32 @@ check2 (void) + } + } + ++#define N 1024 ++ ++static void ++pr23637 (void) ++{ ++ char *h = (char*) buf1; ++ char *n = (char*) buf2; ++ ++ for (int i = 0; i < N; i++) ++ { ++ n[i] = 'x'; ++ h[i] = ' '; ++ h[i + N] = 'x'; ++ } ++ ++ n[N] = '\0'; ++ h[N * 2] = '\0'; ++ ++ /* Ensure we don't match at the first 'x'. */ ++ h[0] = 'x'; ++ ++ char *exp_result = stupid_strstr (h, n); ++ FOR_EACH_IMPL (impl, 0) ++ check_result (impl, h, n, exp_result); ++} ++ + static int + test_main (void) + { +@@ -158,6 +184,7 @@ test_main (void) + + check1 (); + check2 (); ++ pr23637 (); + + printf ("%23s", ""); + FOR_EACH_IMPL (impl, 0) +@@ -202,6 +229,9 @@ test_main (void) + do_test (15, 9, hlen, klen, 1); + do_test (15, 15, hlen, klen, 0); + do_test (15, 15, hlen, klen, 1); ++ ++ do_test (15, 15, hlen + klen * 4, klen * 4, 0); ++ do_test (15, 15, hlen + klen * 4, klen * 4, 1); + } + + do_test (0, 0, page_size - 1, 16, 0); +diff --git a/support/Makefile b/support/Makefile +index 652d2cdf69..b43fa524a7 100644 +--- a/support/Makefile ++++ b/support/Makefile +@@ -25,6 +25,7 @@ extra-libs-others = $(extra-libs) + extra-libs-noinstall := $(extra-libs) + + libsupport-routines = \ ++ blob_repeat \ + check \ + check_addrinfo \ + check_dns_packet \ +@@ -43,6 +44,7 @@ libsupport-routines = \ + support_capture_subprocess \ + support_capture_subprocess_check \ + support_chroot \ ++ support_descriptors \ + support_enter_mount_namespace \ + support_enter_network_namespace \ + support_format_address_family \ +@@ -54,6 +56,7 @@ libsupport-routines = \ + support_isolate_in_subprocess \ + support_openpty \ + support_quote_blob \ ++ support_quote_string \ + support_record_failure \ + support_run_diff \ + support_shared_allocate \ +@@ -120,6 +123,7 @@ libsupport-routines = \ + xpthread_mutexattr_settype \ + xpthread_once \ + xpthread_rwlock_init \ ++ xpthread_rwlock_destroy \ + xpthread_rwlock_rdlock \ + xpthread_rwlock_unlock \ + xpthread_rwlock_wrlock \ +@@ -154,9 +158,12 @@ endif + tests = \ + README-testing \ + tst-support-namespace \ ++ tst-support_blob_repeat \ + tst-support_capture_subprocess \ ++ tst-support_descriptors \ + tst-support_format_dns_packet \ + tst-support_quote_blob \ ++ tst-support_quote_string \ + tst-support_record_failure \ + tst-test_compare \ + tst-test_compare_blob \ +diff --git a/support/blob_repeat.c b/support/blob_repeat.c +new file mode 100644 +index 0000000000..718846d81d +--- /dev/null ++++ b/support/blob_repeat.c +@@ -0,0 +1,302 @@ ++/* Repeating a memory blob, with alias mapping optimization. ++ 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 ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* Small allocations should use malloc directly instead of the mmap ++ optimization because mappings carry a lot of overhead. */ ++static const size_t maximum_small_size = 4 * 1024 * 1024; ++ ++/* Set *RESULT to LEFT * RIGHT. Return true if the multiplication ++ overflowed. See . */ ++static inline bool ++check_mul_overflow_size_t (size_t left, size_t right, size_t *result) ++{ ++#if __GNUC__ >= 5 ++ return __builtin_mul_overflow (left, right, result); ++#else ++ /* size_t is unsigned so the behavior on overflow is defined. */ ++ *result = left * right; ++ size_t half_size_t = ((size_t) 1) << (8 * sizeof (size_t) / 2); ++ if (__glibc_unlikely ((left | right) >= half_size_t)) ++ { ++ if (__glibc_unlikely (right != 0 && *result / right != left)) ++ return true; ++ } ++ return false; ++#endif ++} ++ ++/* Internal helper for fill. */ ++static void ++fill0 (char *target, const char *element, size_t element_size, ++ size_t count) ++{ ++ while (count > 0) ++ { ++ memcpy (target, element, element_size); ++ target += element_size; ++ --count; ++ } ++} ++ ++/* Fill the buffer at TARGET with COUNT copies of the ELEMENT_SIZE ++ bytes starting at ELEMENT. */ ++static void ++fill (char *target, const char *element, size_t element_size, ++ size_t count) ++{ ++ if (element_size == 0 || count == 0) ++ return; ++ else if (element_size == 1) ++ memset (target, element[0], count); ++ else if (element_size == sizeof (wchar_t)) ++ { ++ wchar_t wc; ++ memcpy (&wc, element, sizeof (wc)); ++ wmemset ((wchar_t *) target, wc, count); ++ } ++ else if (element_size < 1024 && count > 4096) ++ { ++ /* Use larger copies for really small element sizes. */ ++ char buffer[8192]; ++ size_t buffer_count = sizeof (buffer) / element_size; ++ fill0 (buffer, element, element_size, buffer_count); ++ while (count > 0) ++ { ++ size_t copy_count = buffer_count; ++ if (copy_count > count) ++ copy_count = count; ++ size_t copy_bytes = copy_count * element_size; ++ memcpy (target, buffer, copy_bytes); ++ target += copy_bytes; ++ count -= copy_count; ++ } ++ } ++ else ++ fill0 (target, element, element_size, count); ++} ++ ++/* Use malloc instead of mmap for small allocations and unusual size ++ combinations. */ ++static struct support_blob_repeat ++allocate_malloc (size_t total_size, const void *element, size_t element_size, ++ size_t count) ++{ ++ void *buffer = malloc (total_size); ++ if (buffer == NULL) ++ return (struct support_blob_repeat) { 0 }; ++ fill (buffer, element, element_size, count); ++ return (struct support_blob_repeat) ++ { ++ .start = buffer, ++ .size = total_size, ++ .use_malloc = true ++ }; ++} ++ ++/* Return the least common multiple of PAGE_SIZE and ELEMENT_SIZE, ++ avoiding overflow. This assumes that PAGE_SIZE is a power of ++ two. */ ++static size_t ++minimum_stride_size (size_t page_size, size_t element_size) ++{ ++ TEST_VERIFY_EXIT (page_size > 0); ++ TEST_VERIFY_EXIT (element_size > 0); ++ ++ /* Compute the number of trailing zeros common to both sizes. */ ++ unsigned int common_zeros = __builtin_ctzll (page_size | element_size); ++ ++ /* In the product, this power of two appears twice, but in the least ++ common multiple, it appears only once. Therefore, shift one ++ factor. */ ++ size_t multiple; ++ if (check_mul_overflow_size_t (page_size >> common_zeros, element_size, ++ &multiple)) ++ return 0; ++ return multiple; ++} ++ ++/* Allocations larger than maximum_small_size potentially use mmap ++ with alias mappings. */ ++static struct support_blob_repeat ++allocate_big (size_t total_size, const void *element, size_t element_size, ++ size_t count) ++{ ++ unsigned long page_size = xsysconf (_SC_PAGESIZE); ++ size_t stride_size = minimum_stride_size (page_size, element_size); ++ if (stride_size == 0) ++ { ++ errno = EOVERFLOW; ++ return (struct support_blob_repeat) { 0 }; ++ } ++ ++ /* Ensure that the stride size is at least maximum_small_size. This ++ is necessary to reduce the number of distinct mappings. */ ++ if (stride_size < maximum_small_size) ++ stride_size ++ = ((maximum_small_size + stride_size - 1) / stride_size) * stride_size; ++ ++ if (stride_size > total_size) ++ /* The mmap optimization would not save anything. */ ++ return allocate_malloc (total_size, element, element_size, count); ++ ++ /* Reserve the memory region. If we cannot create the mapping, ++ there is no reason to set up the backing file. */ ++ void *target = mmap (NULL, total_size, PROT_NONE, ++ MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); ++ if (target == MAP_FAILED) ++ return (struct support_blob_repeat) { 0 }; ++ ++ /* Create the backing file for the repeated mapping. Call mkstemp ++ directly to remove the resources backing the temporary file ++ immediately, once support_blob_repeat_free is called. Using ++ create_temp_file would result in a warning during post-test ++ cleanup. */ ++ int fd; ++ { ++ char *temppath = xasprintf ("%s/support_blob_repeat-XXXXXX", test_dir); ++ fd = mkstemp (temppath); ++ if (fd < 0) ++ FAIL_EXIT1 ("mkstemp (\"%s\"): %m", temppath); ++ xunlink (temppath); ++ free (temppath); ++ } ++ ++ /* Make sure that there is backing storage, so that the fill ++ operation will not fault. */ ++ if (posix_fallocate (fd, 0, stride_size) != 0) ++ FAIL_EXIT1 ("posix_fallocate (%zu): %m", stride_size); ++ ++ /* The stride size must still be a multiple of the page size and ++ element size. */ ++ TEST_VERIFY_EXIT ((stride_size % page_size) == 0); ++ TEST_VERIFY_EXIT ((stride_size % element_size) == 0); ++ ++ /* Fill the backing store. */ ++ { ++ void *ptr = mmap (target, stride_size, PROT_READ | PROT_WRITE, ++ MAP_FIXED | MAP_FILE | MAP_SHARED, fd, 0); ++ if (ptr == MAP_FAILED) ++ { ++ int saved_errno = errno; ++ xmunmap (target, total_size); ++ xclose (fd); ++ errno = saved_errno; ++ return (struct support_blob_repeat) { 0 }; ++ } ++ if (ptr != target) ++ FAIL_EXIT1 ("mapping of %zu bytes moved from %p to %p", ++ stride_size, target, ptr); ++ ++ /* Write the repeating data. */ ++ fill (target, element, element_size, stride_size / element_size); ++ ++ /* Return to a PROT_NONE mapping, just to be on the safe side. */ ++ ptr = mmap (target, stride_size, PROT_NONE, ++ MAP_FIXED | MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); ++ if (ptr == MAP_FAILED) ++ FAIL_EXIT1 ("Failed to reinstate PROT_NONE mapping: %m"); ++ if (ptr != target) ++ FAIL_EXIT1 ("PROT_NONE mapping of %zu bytes moved from %p to %p", ++ stride_size, target, ptr); ++ } ++ ++ /* Create the alias mappings. */ ++ { ++ size_t remaining_size = total_size; ++ char *current = target; ++ int flags = MAP_FIXED | MAP_FILE | MAP_PRIVATE; ++#ifdef MAP_NORESERVE ++ flags |= MAP_NORESERVE; ++#endif ++ while (remaining_size > 0) ++ { ++ size_t to_map = stride_size; ++ if (to_map > remaining_size) ++ to_map = remaining_size; ++ void *ptr = mmap (current, to_map, PROT_READ | PROT_WRITE, ++ flags, fd, 0); ++ if (ptr == MAP_FAILED) ++ { ++ int saved_errno = errno; ++ xmunmap (target, total_size); ++ xclose (fd); ++ errno = saved_errno; ++ return (struct support_blob_repeat) { 0 }; ++ } ++ if (ptr != current) ++ FAIL_EXIT1 ("MAP_PRIVATE mapping of %zu bytes moved from %p to %p", ++ to_map, target, ptr); ++ remaining_size -= to_map; ++ current += to_map; ++ } ++ } ++ ++ xclose (fd); ++ ++ return (struct support_blob_repeat) ++ { ++ .start = target, ++ .size = total_size, ++ .use_malloc = false ++ }; ++} ++ ++struct support_blob_repeat ++support_blob_repeat_allocate (const void *element, size_t element_size, ++ size_t count) ++{ ++ size_t total_size; ++ if (check_mul_overflow_size_t (element_size, count, &total_size)) ++ { ++ errno = EOVERFLOW; ++ return (struct support_blob_repeat) { 0 }; ++ } ++ if (total_size <= maximum_small_size) ++ return allocate_malloc (total_size, element, element_size, count); ++ else ++ return allocate_big (total_size, element, element_size, count); ++} ++ ++void ++support_blob_repeat_free (struct support_blob_repeat *blob) ++{ ++ if (blob->size > 0) ++ { ++ int saved_errno = errno; ++ if (blob->use_malloc) ++ free (blob->start); ++ else ++ xmunmap (blob->start, blob->size); ++ errno = saved_errno; ++ } ++ *blob = (struct support_blob_repeat) { 0 }; ++} +diff --git a/support/blob_repeat.h b/support/blob_repeat.h +new file mode 100644 +index 0000000000..8e9d7ff5f1 +--- /dev/null ++++ b/support/blob_repeat.h +@@ -0,0 +1,44 @@ ++/* Repeating a memory blob, with alias mapping optimization. ++ 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 ++ . */ ++ ++#ifndef SUPPORT_BLOB_REPEAT_H ++#define SUPPORT_BLOB_REPEAT_H ++ ++#include ++#include ++ ++struct support_blob_repeat ++{ ++ void *start; ++ size_t size; ++ bool use_malloc; ++}; ++ ++/* Return an allocation of COUNT elements, each of ELEMENT_SIZE bytes, ++ initialized with the bytes starting at ELEMENT. The memory is ++ writable (and thus counts towards the commit charge). In case of ++ on error, all members of the return struct are zero-initialized, ++ and errno is set accordingly. */ ++struct support_blob_repeat support_blob_repeat_allocate (const void *element, ++ size_t element_size, ++ size_t count); ++ ++/* Deallocate the blob created by support_blob_repeat_allocate. */ ++void support_blob_repeat_free (struct support_blob_repeat *); ++ ++#endif /* SUPPORT_BLOB_REPEAT_H */ +diff --git a/support/check.h b/support/check.h +index b3a4645e92..10468b74d8 100644 +--- a/support/check.h ++++ b/support/check.h +@@ -170,6 +170,10 @@ int support_report_failure (int status) + /* Internal function used to test the failure recording framework. */ + void support_record_failure_reset (void); + ++/* Returns true or false depending on whether there have been test ++ failures or not. */ ++int support_record_failure_is_failed (void); ++ + __END_DECLS + + #endif /* SUPPORT_CHECK_H */ +diff --git a/support/descriptors.h b/support/descriptors.h +new file mode 100644 +index 0000000000..8ec4cbbdfb +--- /dev/null ++++ b/support/descriptors.h +@@ -0,0 +1,47 @@ ++/* Monitoring file descriptor usage. ++ 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 ++ . */ ++ ++#ifndef SUPPORT_DESCRIPTORS_H ++#define SUPPORT_DESCRIPTORS_H ++ ++#include ++ ++/* Opaque pointer, for capturing file descriptor lists. */ ++struct support_descriptors; ++ ++/* Record the currently open file descriptors and store them in the ++ returned list. Terminate the process if the listing operation ++ fails. */ ++struct support_descriptors *support_descriptors_list (void); ++ ++/* Deallocate the list of descriptors. */ ++void support_descriptors_free (struct support_descriptors *); ++ ++/* Write the list of descriptors to STREAM, adding PREFIX to each ++ line. */ ++void support_descriptors_dump (struct support_descriptors *, ++ const char *prefix, FILE *stream); ++ ++/* Check for file descriptor leaks and other file descriptor changes: ++ Compare the current list of descriptors with the passed list. ++ Record a test failure if there are additional open descriptors, ++ descriptors have been closed, or if a change in file descriptor can ++ be detected. */ ++void support_descriptors_check (struct support_descriptors *); ++ ++#endif /* SUPPORT_DESCRIPTORS_H */ +diff --git a/support/support.h b/support/support.h +index b61fe0735c..4ea92e1c21 100644 +--- a/support/support.h ++++ b/support/support.h +@@ -65,6 +65,11 @@ void support_write_file_string (const char *path, const char *contents); + the result). */ + char *support_quote_blob (const void *blob, size_t length); + ++/* Quote the contents of the string, in such a way that the result ++ string can be included in a C literal (in single/double quotes, ++ without putting the quotes into the result). */ ++char *support_quote_string (const char *); ++ + /* Error-checking wrapper functions which terminate the process on + error. */ + +diff --git a/support/support_capture_subprocess.c b/support/support_capture_subprocess.c +index 6d2029e13b..93f6ea3102 100644 +--- a/support/support_capture_subprocess.c ++++ b/support/support_capture_subprocess.c +@@ -59,8 +59,12 @@ support_capture_subprocess (void (*callback) (void *), void *closure) + + int stdout_pipe[2]; + xpipe (stdout_pipe); ++ TEST_VERIFY (stdout_pipe[0] > STDERR_FILENO); ++ TEST_VERIFY (stdout_pipe[1] > STDERR_FILENO); + int stderr_pipe[2]; + xpipe (stderr_pipe); ++ TEST_VERIFY (stderr_pipe[0] > STDERR_FILENO); ++ TEST_VERIFY (stderr_pipe[1] > STDERR_FILENO); + + TEST_VERIFY (fflush (stdout) == 0); + TEST_VERIFY (fflush (stderr) == 0); +@@ -72,6 +76,8 @@ support_capture_subprocess (void (*callback) (void *), void *closure) + xclose (stderr_pipe[0]); + xdup2 (stdout_pipe[1], STDOUT_FILENO); + xdup2 (stderr_pipe[1], STDERR_FILENO); ++ xclose (stdout_pipe[1]); ++ xclose (stderr_pipe[1]); + callback (closure); + _exit (0); + } +diff --git a/support/support_descriptors.c b/support/support_descriptors.c +new file mode 100644 +index 0000000000..d66cf55080 +--- /dev/null ++++ b/support/support_descriptors.c +@@ -0,0 +1,274 @@ ++/* Monitoring file descriptor usage. ++ 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 ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++struct procfs_descriptor ++{ ++ int fd; ++ char *link_target; ++ dev_t dev; ++ ino64_t ino; ++}; ++ ++/* Used with qsort. */ ++static int ++descriptor_compare (const void *l, const void *r) ++{ ++ const struct procfs_descriptor *left = l; ++ const struct procfs_descriptor *right = r; ++ /* Cannot overflow due to limited file descriptor range. */ ++ return left->fd - right->fd; ++} ++ ++#define DYNARRAY_STRUCT descriptor_list ++#define DYNARRAY_ELEMENT struct procfs_descriptor ++#define DYNARRAY_PREFIX descriptor_list_ ++#define DYNARRAY_ELEMENT_FREE(e) free ((e)->link_target) ++#define DYNARRAY_INITIAL_SIZE 0 ++#include ++ ++struct support_descriptors ++{ ++ struct descriptor_list list; ++}; ++ ++struct support_descriptors * ++support_descriptors_list (void) ++{ ++ struct support_descriptors *result = xmalloc (sizeof (*result)); ++ descriptor_list_init (&result->list); ++ ++ DIR *fds = opendir ("/proc/self/fd"); ++ if (fds == NULL) ++ FAIL_EXIT1 ("opendir (\"/proc/self/fd\"): %m"); ++ ++ while (true) ++ { ++ errno = 0; ++ struct dirent64 *e = readdir64 (fds); ++ if (e == NULL) ++ { ++ if (errno != 0) ++ FAIL_EXIT1 ("readdir: %m"); ++ break; ++ } ++ ++ if (e->d_name[0] == '.') ++ continue; ++ ++ char *endptr; ++ long int fd = strtol (e->d_name, &endptr, 10); ++ if (*endptr != '\0' || fd < 0 || fd > INT_MAX) ++ FAIL_EXIT1 ("readdir: invalid file descriptor name: /proc/self/fd/%s", ++ e->d_name); ++ ++ /* Skip the descriptor which is used to enumerate the ++ descriptors. */ ++ if (fd == dirfd (fds)) ++ continue; ++ ++ char *target; ++ { ++ char *path = xasprintf ("/proc/self/fd/%ld", fd); ++ target = xreadlink (path); ++ free (path); ++ } ++ struct stat64 st; ++ if (fstat64 (fd, &st) != 0) ++ FAIL_EXIT1 ("readdir: fstat64 (%ld) failed: %m", fd); ++ ++ struct procfs_descriptor *item = descriptor_list_emplace (&result->list); ++ if (item == NULL) ++ FAIL_EXIT1 ("descriptor_list_emplace: %m"); ++ item->fd = fd; ++ item->link_target = target; ++ item->dev = st.st_dev; ++ item->ino = st.st_ino; ++ } ++ ++ closedir (fds); ++ ++ /* Perform a merge join between descrs and current. This assumes ++ that the arrays are sorted by file descriptor. */ ++ ++ qsort (descriptor_list_begin (&result->list), ++ descriptor_list_size (&result->list), ++ sizeof (struct procfs_descriptor), descriptor_compare); ++ ++ return result; ++} ++ ++void ++support_descriptors_free (struct support_descriptors *descrs) ++{ ++ descriptor_list_free (&descrs->list); ++ free (descrs); ++} ++ ++void ++support_descriptors_dump (struct support_descriptors *descrs, ++ const char *prefix, FILE *fp) ++{ ++ struct procfs_descriptor *end = descriptor_list_end (&descrs->list); ++ for (struct procfs_descriptor *d = descriptor_list_begin (&descrs->list); ++ d != end; ++d) ++ { ++ char *quoted = support_quote_string (d->link_target); ++ fprintf (fp, "%s%d: target=\"%s\" major=%lld minor=%lld ino=%lld\n", ++ prefix, d->fd, quoted, ++ (long long int) major (d->dev), ++ (long long int) minor (d->dev), ++ (long long int) d->ino); ++ free (quoted); ++ } ++} ++ ++static void ++dump_mismatch (bool *first, ++ struct support_descriptors *descrs, ++ struct support_descriptors *current) ++{ ++ if (*first) ++ *first = false; ++ else ++ return; ++ ++ puts ("error: Differences found in descriptor set"); ++ puts ("Reference descriptor set:"); ++ support_descriptors_dump (descrs, " ", stdout); ++ puts ("Current descriptor set:"); ++ support_descriptors_dump (current, " ", stdout); ++ puts ("Differences:"); ++} ++ ++static void ++report_closed_descriptor (bool *first, ++ struct support_descriptors *descrs, ++ struct support_descriptors *current, ++ struct procfs_descriptor *left) ++{ ++ support_record_failure (); ++ dump_mismatch (first, descrs, current); ++ printf ("error: descriptor %d was closed\n", left->fd); ++} ++ ++static void ++report_opened_descriptor (bool *first, ++ struct support_descriptors *descrs, ++ struct support_descriptors *current, ++ struct procfs_descriptor *right) ++{ ++ support_record_failure (); ++ dump_mismatch (first, descrs, current); ++ char *quoted = support_quote_string (right->link_target); ++ printf ("error: descriptor %d was opened (\"%s\")\n", right->fd, quoted); ++ free (quoted); ++} ++ ++void ++support_descriptors_check (struct support_descriptors *descrs) ++{ ++ struct support_descriptors *current = support_descriptors_list (); ++ ++ /* Perform a merge join between descrs and current. This assumes ++ that the arrays are sorted by file descriptor. */ ++ ++ struct procfs_descriptor *left = descriptor_list_begin (&descrs->list); ++ struct procfs_descriptor *left_end = descriptor_list_end (&descrs->list); ++ struct procfs_descriptor *right = descriptor_list_begin (¤t->list); ++ struct procfs_descriptor *right_end = descriptor_list_end (¤t->list); ++ ++ bool first = true; ++ while (left != left_end && right != right_end) ++ { ++ if (left->fd == right->fd) ++ { ++ if (strcmp (left->link_target, right->link_target) != 0) ++ { ++ support_record_failure (); ++ char *left_quoted = support_quote_string (left->link_target); ++ char *right_quoted = support_quote_string (right->link_target); ++ dump_mismatch (&first, descrs, current); ++ printf ("error: descriptor %d changed from \"%s\" to \"%s\"\n", ++ left->fd, left_quoted, right_quoted); ++ free (left_quoted); ++ free (right_quoted); ++ } ++ if (left->dev != right->dev) ++ { ++ support_record_failure (); ++ dump_mismatch (&first, descrs, current); ++ printf ("error: descriptor %d changed device" ++ " from %lld:%lld to %lld:%lld\n", ++ left->fd, ++ (long long int) major (left->dev), ++ (long long int) minor (left->dev), ++ (long long int) major (right->dev), ++ (long long int) minor (right->dev)); ++ } ++ if (left->ino != right->ino) ++ { ++ support_record_failure (); ++ dump_mismatch (&first, descrs, current); ++ printf ("error: descriptor %d changed ino from %lld to %lld\n", ++ left->fd, ++ (long long int) left->ino, (long long int) right->ino); ++ } ++ ++left; ++ ++right; ++ } ++ else if (left->fd < right->fd) ++ { ++ /* Gap on the right. */ ++ report_closed_descriptor (&first, descrs, current, left); ++ ++left; ++ } ++ else ++ { ++ /* Gap on the left. */ ++ TEST_VERIFY_EXIT (left->fd > right->fd); ++ report_opened_descriptor (&first, descrs, current, right); ++ ++right; ++ } ++ } ++ ++ while (left != left_end) ++ { ++ /* Closed descriptors (more descriptors on the left). */ ++ report_closed_descriptor (&first, descrs, current, left); ++ ++left; ++ } ++ ++ while (right != right_end) ++ { ++ /* Opened descriptors (more descriptors on the right). */ ++ report_opened_descriptor (&first, descrs, current, right); ++ ++right; ++ } ++ ++ support_descriptors_free (current); ++} +diff --git a/support/support_quote_string.c b/support/support_quote_string.c +new file mode 100644 +index 0000000000..d324371b13 +--- /dev/null ++++ b/support/support_quote_string.c +@@ -0,0 +1,26 @@ ++/* Quote a string so that it can be used in C literals. ++ 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 ++ . */ ++ ++#include ++#include ++ ++char * ++support_quote_string (const char *str) ++{ ++ return support_quote_blob (str, strlen (str)); ++} +diff --git a/support/support_record_failure.c b/support/support_record_failure.c +index 356798f556..17ab1d80ef 100644 +--- a/support/support_record_failure.c ++++ b/support/support_record_failure.c +@@ -104,3 +104,11 @@ support_record_failure_reset (void) + __atomic_store_n (&state->failed, 0, __ATOMIC_RELAXED); + __atomic_add_fetch (&state->counter, 0, __ATOMIC_RELAXED); + } ++ ++int ++support_record_failure_is_failed (void) ++{ ++ /* Relaxed MO is sufficient because we need (blocking) external ++ synchronization for reliable test error reporting anyway. */ ++ return __atomic_load_n (&state->failed, __ATOMIC_RELAXED); ++} +diff --git a/support/support_test_main.c b/support/support_test_main.c +index 23429779ac..fa3c2e06de 100644 +--- a/support/support_test_main.c ++++ b/support/support_test_main.c +@@ -30,6 +30,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -86,6 +87,19 @@ static pid_t test_pid; + /* The cleanup handler passed to test_main. */ + static void (*cleanup_function) (void); + ++static void ++print_timestamp (const char *what, struct timeval tv) ++{ ++ struct tm tm; ++ if (gmtime_r (&tv.tv_sec, &tm) == NULL) ++ printf ("%s: %lld.%06d\n", ++ what, (long long int) tv.tv_sec, (int) tv.tv_usec); ++ else ++ printf ("%s: %04d-%02d-%02dT%02d:%02d:%02d.%06d\n", ++ what, 1900 + tm.tm_year, tm.tm_mon + 1, tm.tm_mday, ++ tm.tm_hour, tm.tm_min, tm.tm_sec, (int) tv.tv_usec); ++} ++ + /* Timeout handler. We kill the child and exit with an error. */ + static void + __attribute__ ((noreturn)) +@@ -94,6 +108,13 @@ signal_handler (int sig) + int killed; + int status; + ++ /* Do this first to avoid further interference from the ++ subprocess. */ ++ struct timeval now; ++ bool now_available = gettimeofday (&now, NULL) == 0; ++ struct stat64 st; ++ bool st_available = fstat64 (STDOUT_FILENO, &st) == 0 && st.st_mtime != 0; ++ + assert (test_pid > 1); + /* Kill the whole process group. */ + kill (-test_pid, SIGKILL); +@@ -144,6 +165,13 @@ signal_handler (int sig) + printf ("Timed out: killed the child process but it exited %d\n", + WEXITSTATUS (status)); + ++ if (now_available) ++ print_timestamp ("Termination time", now); ++ if (st_available) ++ print_timestamp ("Last write to standard output", ++ (struct timeval) { st.st_mtim.tv_sec, ++ st.st_mtim.tv_nsec / 1000 }); ++ + /* Exit with an error. */ + exit (1); + } +diff --git a/support/tst-support_blob_repeat.c b/support/tst-support_blob_repeat.c +new file mode 100644 +index 0000000000..1978c14488 +--- /dev/null ++++ b/support/tst-support_blob_repeat.c +@@ -0,0 +1,85 @@ ++/* Tests for ++ 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 ++ . */ ++ ++#include ++#include ++#include ++ ++static int ++do_test (void) ++{ ++ struct support_blob_repeat repeat ++ = support_blob_repeat_allocate ("5", 1, 5); ++ TEST_COMPARE_BLOB (repeat.start, repeat.size, "55555", 5); ++ support_blob_repeat_free (&repeat); ++ ++ repeat = support_blob_repeat_allocate ("ABC", 3, 3); ++ TEST_COMPARE_BLOB (repeat.start, repeat.size, "ABCABCABC", 9); ++ support_blob_repeat_free (&repeat); ++ ++ repeat = support_blob_repeat_allocate ("abc", 4, 3); ++ TEST_COMPARE_BLOB (repeat.start, repeat.size, "abc\0abc\0abc", 12); ++ support_blob_repeat_free (&repeat); ++ ++ size_t gigabyte = 1U << 30; ++ repeat = support_blob_repeat_allocate ("X", 1, gigabyte + 1); ++ if (repeat.start == NULL) ++ puts ("warning: not enough memory for 1 GiB mapping"); ++ else ++ { ++ TEST_COMPARE (repeat.size, gigabyte + 1); ++ { ++ unsigned char *p = repeat.start; ++ for (size_t i = 0; i < gigabyte + 1; ++i) ++ if (p[i] != 'X') ++ FAIL_EXIT1 ("invalid byte 0x%02x at %zu", p[i], i); ++ ++ /* Check that there is no sharing across the mapping. */ ++ p[0] = 'Y'; ++ p[1U << 24] = 'Z'; ++ for (size_t i = 0; i < gigabyte + 1; ++i) ++ if (i == 0) ++ TEST_COMPARE (p[i], 'Y'); ++ else if (i == 1U << 24) ++ TEST_COMPARE (p[i], 'Z'); ++ else if (p[i] != 'X') ++ FAIL_EXIT1 ("invalid byte 0x%02x at %zu", p[i], i); ++ } ++ } ++ support_blob_repeat_free (&repeat); ++ ++ repeat = support_blob_repeat_allocate ("012345678", 9, 10 * 1000 * 1000); ++ if (repeat.start == NULL) ++ puts ("warning: not enough memory for large mapping"); ++ else ++ { ++ unsigned char *p = repeat.start; ++ for (int i = 0; i < 10 * 1000 * 1000; ++i) ++ for (int j = 0; j <= 8; ++j) ++ if (p[i * 9 + j] != '0' + j) ++ { ++ printf ("error: element %d index %d\n", i, j); ++ TEST_COMPARE (p[i * 9 + j], '0' + j); ++ } ++ } ++ support_blob_repeat_free (&repeat); ++ ++ return 0; ++} ++ ++#include +diff --git a/support/tst-support_descriptors.c b/support/tst-support_descriptors.c +new file mode 100644 +index 0000000000..5e9e824bc3 +--- /dev/null ++++ b/support/tst-support_descriptors.c +@@ -0,0 +1,198 @@ ++/* Tests for monitoring file descriptor usage. ++ 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 ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* This is the next free descriptor that the subprocess will pick. */ ++static int free_descriptor; ++ ++static void ++subprocess_no_change (void *closure) ++{ ++ struct support_descriptors *descrs = support_descriptors_list (); ++ int fd = xopen ("/dev/null", O_WRONLY, 0); ++ TEST_COMPARE (fd, free_descriptor); ++ xclose (fd); ++ support_descriptors_free (descrs); ++} ++ ++static void ++subprocess_closed_descriptor (void *closure) ++{ ++ int fd = xopen ("/dev/null", O_WRONLY, 0); ++ TEST_COMPARE (fd, free_descriptor); ++ struct support_descriptors *descrs = support_descriptors_list (); ++ xclose (fd); ++ support_descriptors_check (descrs); /* Will report failure. */ ++ puts ("EOT"); ++ support_descriptors_free (descrs); ++} ++ ++static void ++subprocess_opened_descriptor (void *closure) ++{ ++ struct support_descriptors *descrs = support_descriptors_list (); ++ int fd = xopen ("/dev/null", O_WRONLY, 0); ++ TEST_COMPARE (fd, free_descriptor); ++ support_descriptors_check (descrs); /* Will report failure. */ ++ puts ("EOT"); ++ support_descriptors_free (descrs); ++} ++ ++static void ++subprocess_changed_descriptor (void *closure) ++{ ++ int fd = xopen ("/dev/null", O_WRONLY, 0); ++ TEST_COMPARE (fd, free_descriptor); ++ struct support_descriptors *descrs = support_descriptors_list (); ++ xclose (fd); ++ TEST_COMPARE (xopen ("/dev", O_DIRECTORY | O_RDONLY, 0), fd); ++ support_descriptors_check (descrs); /* Will report failure. */ ++ puts ("EOT"); ++ support_descriptors_free (descrs); ++} ++ ++static void ++report_subprocess_output (const char *name, ++ struct support_capture_subprocess *proc) ++{ ++ printf ("info: BEGIN %s output\n" ++ "%s" ++ "info: END %s output\n", ++ name, proc->out.buffer, name); ++} ++ ++/* Use an explicit flag to preserve failure status across ++ support_record_failure_reset calls. */ ++static bool good = true; ++ ++static void ++test_run (void) ++{ ++ struct support_capture_subprocess proc = support_capture_subprocess ++ (&subprocess_no_change, NULL); ++ support_capture_subprocess_check (&proc, "subprocess_no_change", ++ 0, sc_allow_none); ++ support_capture_subprocess_free (&proc); ++ ++ char *expected = xasprintf ("\nDifferences:\n" ++ "error: descriptor %d was closed\n" ++ "EOT\n", ++ free_descriptor); ++ good = good && !support_record_failure_is_failed (); ++ proc = support_capture_subprocess (&subprocess_closed_descriptor, NULL); ++ good = good && support_record_failure_is_failed (); ++ support_record_failure_reset (); /* Discard the reported error. */ ++ report_subprocess_output ("subprocess_closed_descriptor", &proc); ++ TEST_VERIFY (strstr (proc.out.buffer, expected) != NULL); ++ support_capture_subprocess_check (&proc, "subprocess_closed_descriptor", ++ 0, sc_allow_stdout); ++ support_capture_subprocess_free (&proc); ++ free (expected); ++ ++ expected = xasprintf ("\nDifferences:\n" ++ "error: descriptor %d was opened (\"/dev/null\")\n" ++ "EOT\n", ++ free_descriptor); ++ good = good && !support_record_failure_is_failed (); ++ proc = support_capture_subprocess (&subprocess_opened_descriptor, NULL); ++ good = good && support_record_failure_is_failed (); ++ support_record_failure_reset (); /* Discard the reported error. */ ++ report_subprocess_output ("subprocess_opened_descriptor", &proc); ++ TEST_VERIFY (strstr (proc.out.buffer, expected) != NULL); ++ support_capture_subprocess_check (&proc, "subprocess_opened_descriptor", ++ 0, sc_allow_stdout); ++ support_capture_subprocess_free (&proc); ++ free (expected); ++ ++ expected = xasprintf ("\nDifferences:\n" ++ "error: descriptor %d changed from \"/dev/null\"" ++ " to \"/dev\"\n" ++ "error: descriptor %d changed ino ", ++ free_descriptor, free_descriptor); ++ good = good && !support_record_failure_is_failed (); ++ proc = support_capture_subprocess (&subprocess_changed_descriptor, NULL); ++ good = good && support_record_failure_is_failed (); ++ support_record_failure_reset (); /* Discard the reported error. */ ++ report_subprocess_output ("subprocess_changed_descriptor", &proc); ++ TEST_VERIFY (strstr (proc.out.buffer, expected) != NULL); ++ support_capture_subprocess_check (&proc, "subprocess_changed_descriptor", ++ 0, sc_allow_stdout); ++ support_capture_subprocess_free (&proc); ++ free (expected); ++} ++ ++static int ++do_test (void) ++{ ++ puts ("info: initial descriptor set"); ++ { ++ struct support_descriptors *descrs = support_descriptors_list (); ++ support_descriptors_dump (descrs, "info: ", stdout); ++ support_descriptors_free (descrs); ++ } ++ ++ free_descriptor = xopen ("/dev/null", O_WRONLY, 0); ++ puts ("info: descriptor set with additional free descriptor"); ++ { ++ struct support_descriptors *descrs = support_descriptors_list (); ++ support_descriptors_dump (descrs, "info: ", stdout); ++ support_descriptors_free (descrs); ++ } ++ TEST_VERIFY (free_descriptor >= 3); ++ xclose (free_descriptor); ++ ++ /* Initial test run without a sentinel descriptor. The presence of ++ such a descriptor exercises different conditions in the list ++ comparison in support_descriptors_check. */ ++ test_run (); ++ ++ /* Allocate a sentinel descriptor at the end of the descriptor list, ++ after free_descriptor. */ ++ int sentinel_fd; ++ { ++ int fd = xopen ("/dev/full", O_WRONLY, 0); ++ TEST_COMPARE (fd, free_descriptor); ++ sentinel_fd = dup (fd); ++ TEST_VERIFY_EXIT (sentinel_fd > fd); ++ xclose (fd); ++ } ++ puts ("info: descriptor set with sentinel descriptor"); ++ { ++ struct support_descriptors *descrs = support_descriptors_list (); ++ support_descriptors_dump (descrs, "info: ", stdout); ++ support_descriptors_free (descrs); ++ } ++ ++ /* Second test run with sentinel descriptor. */ ++ test_run (); ++ ++ xclose (sentinel_fd); ++ ++ return !good; ++} ++ ++#include +diff --git a/support/tst-support_quote_string.c b/support/tst-support_quote_string.c +new file mode 100644 +index 0000000000..3c004759b7 +--- /dev/null ++++ b/support/tst-support_quote_string.c +@@ -0,0 +1,60 @@ ++/* Test the support_quote_string function. ++ 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 ++ . */ ++ ++#include ++#include ++#include ++#include ++ ++static int ++do_test (void) ++{ ++ char *p = support_quote_string (""); ++ TEST_COMPARE (strlen (p), 0); ++ free (p); ++ p = support_quote_string ("X"); ++ TEST_COMPARE (strlen (p), 1); ++ TEST_COMPARE (p[0], 'X'); ++ free (p); ++ ++ /* Check escaping of backslash-escaped characters, and lack of ++ escaping for other shell meta-characters. */ ++ p = support_quote_string ("$()*?`@[]{}~\'\"X"); ++ TEST_COMPARE (strcmp (p, "$()*?`@[]{}~\\'\\\"X"), 0); ++ free (p); ++ ++ /* Check lack of escaping for letters and digits. */ ++#define LETTERS_AND_DIGTS \ ++ "abcdefghijklmnopqrstuvwxyz" \ ++ "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \ ++ "0123456789" ++ p = support_quote_string (LETTERS_AND_DIGTS "@"); ++ TEST_COMPARE (strcmp (p, LETTERS_AND_DIGTS "@"), 0); ++ free (p); ++ ++ /* Check escaping of control characters and other non-printable ++ characters. */ ++ p = support_quote_string ("\r\n\t\a\b\f\v\1\177\200\377@"); ++ TEST_COMPARE (strcmp (p, "\\r\\n\\t\\a\\b\\f\\v\\001" ++ "\\177\\200\\377@"), 0); ++ free (p); ++ ++ return 0; ++} ++ ++#include +diff --git a/support/xpthread_rwlock_destroy.c b/support/xpthread_rwlock_destroy.c +new file mode 100644 +index 0000000000..6d6e953569 +--- /dev/null ++++ b/support/xpthread_rwlock_destroy.c +@@ -0,0 +1,26 @@ ++/* pthread_rwlock_destroy with error checking. ++ Copyright (C) 2019 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 ++ . */ ++ ++#include ++ ++void ++xpthread_rwlock_destroy (pthread_rwlock_t *rwlock) ++{ ++ xpthread_check_return ("pthread_rwlock_destroy", ++ pthread_rwlock_destroy (rwlock)); ++} +diff --git a/support/xthread.h b/support/xthread.h +index 623f5ad0ac..1af7728087 100644 +--- a/support/xthread.h ++++ b/support/xthread.h +@@ -84,6 +84,7 @@ void xpthread_rwlockattr_setkind_np (pthread_rwlockattr_t *attr, int pref); + void xpthread_rwlock_wrlock (pthread_rwlock_t *rwlock); + void xpthread_rwlock_rdlock (pthread_rwlock_t *rwlock); + void xpthread_rwlock_unlock (pthread_rwlock_t *rwlock); ++void xpthread_rwlock_destroy (pthread_rwlock_t *rwlock); + + __END_DECLS + +diff --git a/sysdeps/aarch64/dl-irel.h b/sysdeps/aarch64/dl-irel.h +index 5889ee187b..bef71ed0f3 100644 +--- a/sysdeps/aarch64/dl-irel.h ++++ b/sysdeps/aarch64/dl-irel.h +@@ -47,7 +47,7 @@ elf_irela (const ElfW(Rela) *reloc) + *reloc_addr = value; + } + else +- __libc_fatal ("unexpected reloc type in static binary"); ++ __libc_fatal ("Unexpected reloc type in static binary.\n"); + } + + #endif +diff --git a/sysdeps/alpha/fpu/libm-test-ulps b/sysdeps/alpha/fpu/libm-test-ulps +index 12a6127ddf..3fc18d57d7 100644 +--- a/sysdeps/alpha/fpu/libm-test-ulps ++++ b/sysdeps/alpha/fpu/libm-test-ulps +@@ -1006,7 +1006,9 @@ ildouble: 2 + ldouble: 2 + + Function: "cos": ++double: 1 + float: 1 ++idouble: 1 + ifloat: 1 + ildouble: 1 + ldouble: 1 +@@ -1932,7 +1934,9 @@ ildouble: 1 + ldouble: 1 + + Function: "pow": ++double: 1 + float: 1 ++idouble: 1 + ifloat: 1 + ildouble: 2 + ldouble: 2 +@@ -1962,7 +1966,9 @@ ildouble: 2 + ldouble: 2 + + Function: "sin": ++double: 1 + float: 1 ++idouble: 1 + ifloat: 1 + ildouble: 1 + ldouble: 1 +@@ -1992,7 +1998,9 @@ ildouble: 3 + ldouble: 3 + + Function: "sincos": ++double: 1 + float: 1 ++idouble: 1 + ifloat: 1 + ildouble: 1 + ldouble: 1 +diff --git a/sysdeps/arm/dl-irel.h b/sysdeps/arm/dl-irel.h +index a7b6456075..be6eb7743e 100644 +--- a/sysdeps/arm/dl-irel.h ++++ b/sysdeps/arm/dl-irel.h +@@ -46,7 +46,7 @@ elf_irel (const Elf32_Rel *reloc) + *reloc_addr = value; + } + else +- __libc_fatal ("unexpected reloc type in static binary"); ++ __libc_fatal ("Unexpected reloc type in static binary.\n"); + } + + #endif /* dl-irel.h */ +diff --git a/sysdeps/generic/unwind-dw2.c b/sysdeps/generic/unwind-dw2.c +index 082609b34a..724c16a7f0 100644 +--- a/sysdeps/generic/unwind-dw2.c ++++ b/sysdeps/generic/unwind-dw2.c +@@ -843,7 +843,7 @@ execute_cfa_program (const unsigned char *insn_ptr, + struct frame_state_reg_info *old_rs = fs->regs.prev; + #ifdef _LIBC + if (old_rs == NULL) +- __libc_fatal ("invalid DWARF unwind data"); ++ __libc_fatal ("Invalid DWARF unwind data.\n"); + else + #endif + { +diff --git a/sysdeps/htl/pt-getspecific.c b/sysdeps/htl/pt-getspecific.c +index a0227a67f6..64ddf9551a 100644 +--- a/sysdeps/htl/pt-getspecific.c ++++ b/sysdeps/htl/pt-getspecific.c +@@ -36,3 +36,4 @@ __pthread_getspecific (pthread_key_t key) + return self->thread_specifics[key]; + } + strong_alias (__pthread_getspecific, pthread_getspecific); ++hidden_def (__pthread_getspecific) +diff --git a/sysdeps/htl/pt-setspecific.c b/sysdeps/htl/pt-setspecific.c +index a46a12f157..02aff417ef 100644 +--- a/sysdeps/htl/pt-setspecific.c ++++ b/sysdeps/htl/pt-setspecific.c +@@ -48,3 +48,4 @@ __pthread_setspecific (pthread_key_t key, const void *value) + return 0; + } + strong_alias (__pthread_setspecific, pthread_setspecific); ++hidden_def (__pthread_setspecific) +diff --git a/sysdeps/htl/pthreadP.h b/sysdeps/htl/pthreadP.h +index 132ac1718e..71c2fcd9c6 100644 +--- a/sysdeps/htl/pthreadP.h ++++ b/sysdeps/htl/pthreadP.h +@@ -68,6 +68,8 @@ struct __pthread_cancelation_handler **___pthread_get_cleanup_stack (void) attri + + #if IS_IN (libpthread) + hidden_proto (__pthread_key_create) ++hidden_proto (__pthread_getspecific) ++hidden_proto (__pthread_setspecific) + hidden_proto (_pthread_mutex_init) + #endif + +diff --git a/sysdeps/i386/dl-cet.c b/sysdeps/i386/dl-cet.c +deleted file mode 100644 +index 5d9a4e8d51..0000000000 +--- a/sysdeps/i386/dl-cet.c ++++ /dev/null +@@ -1,67 +0,0 @@ +-/* Linux/i386 CET initializers function. +- Copyright (C) 2018 Free Software Foundation, Inc. +- +- 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 +- . */ +- +- +-#define LINKAGE static inline +-#define _dl_cet_check cet_check +-#include +-#undef _dl_cet_check +- +-#ifdef SHARED +-void +-_dl_cet_check (struct link_map *main_map, const char *program) +-{ +- cet_check (main_map, program); +- +- if ((GL(dl_x86_feature_1)[0] & GNU_PROPERTY_X86_FEATURE_1_SHSTK)) +- { +- /* Replace _dl_runtime_resolve and _dl_runtime_profile with +- _dl_runtime_resolve_shstk and _dl_runtime_profile_shstk, +- respectively if SHSTK is enabled. */ +- extern void _dl_runtime_resolve (Elf32_Word) attribute_hidden; +- extern void _dl_runtime_resolve_shstk (Elf32_Word) attribute_hidden; +- extern void _dl_runtime_profile (Elf32_Word) attribute_hidden; +- extern void _dl_runtime_profile_shstk (Elf32_Word) attribute_hidden; +- unsigned int i; +- struct link_map *l; +- Elf32_Addr *got; +- +- if (main_map->l_info[DT_JMPREL]) +- { +- got = (Elf32_Addr *) D_PTR (main_map, l_info[DT_PLTGOT]); +- if (got[2] == (Elf32_Addr) &_dl_runtime_resolve) +- got[2] = (Elf32_Addr) &_dl_runtime_resolve_shstk; +- else if (got[2] == (Elf32_Addr) &_dl_runtime_profile) +- got[2] = (Elf32_Addr) &_dl_runtime_profile_shstk; +- } +- +- i = main_map->l_searchlist.r_nlist; +- while (i-- > 0) +- { +- l = main_map->l_initfini[i]; +- if (l->l_info[DT_JMPREL]) +- { +- got = (Elf32_Addr *) D_PTR (l, l_info[DT_PLTGOT]); +- if (got[2] == (Elf32_Addr) &_dl_runtime_resolve) +- got[2] = (Elf32_Addr) &_dl_runtime_resolve_shstk; +- else if (got[2] == (Elf32_Addr) &_dl_runtime_profile) +- got[2] = (Elf32_Addr) &_dl_runtime_profile_shstk; +- } +- } +- } +-} +-#endif +diff --git a/sysdeps/i386/dl-irel.h b/sysdeps/i386/dl-irel.h +index 55303180c7..bcaf0668ac 100644 +--- a/sysdeps/i386/dl-irel.h ++++ b/sysdeps/i386/dl-irel.h +@@ -45,7 +45,7 @@ elf_irel (const Elf32_Rel *reloc) + *reloc_addr = value; + } + else +- __libc_fatal ("unexpected reloc type in static binary"); ++ __libc_fatal ("Unexpected reloc type in static binary.\n"); + } + + #endif /* dl-irel.h */ +diff --git a/sysdeps/i386/dl-machine.h b/sysdeps/i386/dl-machine.h +index 1afdcbd9ea..f6cfb90e21 100644 +--- a/sysdeps/i386/dl-machine.h ++++ b/sysdeps/i386/dl-machine.h +@@ -67,6 +67,11 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile) + Elf32_Addr *got; + extern void _dl_runtime_resolve (Elf32_Word) attribute_hidden; + extern void _dl_runtime_profile (Elf32_Word) attribute_hidden; ++ extern void _dl_runtime_resolve_shstk (Elf32_Word) attribute_hidden; ++ extern void _dl_runtime_profile_shstk (Elf32_Word) attribute_hidden; ++ /* Check if SHSTK is enabled by kernel. */ ++ bool shstk_enabled ++ = (GL(dl_x86_feature_1)[0] & GNU_PROPERTY_X86_FEATURE_1_SHSTK) != 0; + + if (l->l_info[DT_JMPREL] && lazy) + { +@@ -93,7 +98,9 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile) + end in this function. */ + if (__glibc_unlikely (profile)) + { +- got[2] = (Elf32_Addr) &_dl_runtime_profile; ++ got[2] = (shstk_enabled ++ ? (Elf32_Addr) &_dl_runtime_profile_shstk ++ : (Elf32_Addr) &_dl_runtime_profile); + + if (GLRO(dl_profile) != NULL + && _dl_name_match_p (GLRO(dl_profile), l)) +@@ -104,7 +111,9 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile) + else + /* This function will get called to fix up the GOT entry indicated by + the offset on the stack, and then jump to the resolved address. */ +- got[2] = (Elf32_Addr) &_dl_runtime_resolve; ++ got[2] = (shstk_enabled ++ ? (Elf32_Addr) &_dl_runtime_resolve_shstk ++ : (Elf32_Addr) &_dl_runtime_resolve); + } + + return lazy; +diff --git a/sysdeps/i386/start.S b/sysdeps/i386/start.S +index 91035fa83f..e35e9bd31b 100644 +--- a/sysdeps/i386/start.S ++++ b/sysdeps/i386/start.S +@@ -52,10 +52,11 @@ + NULL + */ + +- .text +- .globl _start +- .type _start,@function +-_start: ++#include ++ ++ENTRY (_start) ++ /* Clearing frame pointer is insufficient, use CFI. */ ++ cfi_undefined (eip) + /* Clear the frame pointer. The ABI suggests this be done, to mark + the outermost frame obviously. */ + xorl %ebp, %ebp +@@ -131,6 +132,7 @@ _start: + 1: movl (%esp), %ebx + ret + #endif ++END (_start) + + /* To fulfill the System V/i386 ABI we need this symbol. Yuck, it's so + meaningless since we don't support machines < 80386. */ +diff --git a/sysdeps/ia64/fpu/e_exp2f.S b/sysdeps/ia64/fpu/e_exp2f.S +index 77bc6ea686..3010a95a2d 100644 +--- a/sysdeps/ia64/fpu/e_exp2f.S ++++ b/sysdeps/ia64/fpu/e_exp2f.S +@@ -221,7 +221,7 @@ LOCAL_OBJECT_END(T_table) + + + .section .text +-GLOBAL_LIBM_ENTRY(__exp2f) ++WEAK_LIBM_ENTRY(exp2f) + + + {.mfi +@@ -468,10 +468,10 @@ OUT_RANGE_exp2: + } + ;; + +-GLOBAL_LIBM_END(__exp2f) ++WEAK_LIBM_END(exp2f) + libm_alias_float_other (__exp2, exp2) + #ifdef SHARED +-.symver __exp2f,exp2f@@GLIBC_2.27 ++.symver exp2f,exp2f@@GLIBC_2.27 + .weak __exp2f_compat + .set __exp2f_compat,__exp2f + .symver __exp2f_compat,exp2f@GLIBC_2.2 +diff --git a/sysdeps/ia64/fpu/e_log2f.S b/sysdeps/ia64/fpu/e_log2f.S +index 5ca3bd61ea..e4ea094344 100644 +--- a/sysdeps/ia64/fpu/e_log2f.S ++++ b/sysdeps/ia64/fpu/e_log2f.S +@@ -252,7 +252,7 @@ LOCAL_OBJECT_END(T_table) + + + .section .text +-GLOBAL_LIBM_ENTRY(__log2f) ++WEAK_LIBM_ENTRY(log2f) + + { .mfi + alloc r32=ar.pfs,1,4,4,0 +@@ -491,10 +491,10 @@ SPECIAL_log2f: + br.ret.sptk b0;; + } + +-GLOBAL_LIBM_END(__log2f) ++WEAK_LIBM_END(log2f) + libm_alias_float_other (__log2, log2) + #ifdef SHARED +-.symver __log2f,log2f@@GLIBC_2.27 ++.symver log2f,log2f@@GLIBC_2.27 + .weak __log2f_compat + .set __log2f_compat,__log2f + .symver __log2f_compat,log2f@GLIBC_2.2 +diff --git a/sysdeps/ia64/fpu/e_powf.S b/sysdeps/ia64/fpu/e_powf.S +index 7449f8c7d5..945d5cdf28 100644 +--- a/sysdeps/ia64/fpu/e_powf.S ++++ b/sysdeps/ia64/fpu/e_powf.S +@@ -868,7 +868,7 @@ data8 0xEAC0C6E7DD24392F , 0x00003FFF + LOCAL_OBJECT_END(pow_tbl2) + + .section .text +-GLOBAL_LIBM_ENTRY(__powf) ++WEAK_LIBM_ENTRY(powf) + + // Get exponent of x. Will be used to calculate K. + { .mfi +@@ -2002,10 +2002,10 @@ POW_OVER_UNDER_ERROR: + } + ;; + +-GLOBAL_LIBM_END(__powf) ++WEAK_LIBM_END(powf) + libm_alias_float_other (__pow, pow) + #ifdef SHARED +-.symver __powf,powf@@GLIBC_2.27 ++.symver powf,powf@@GLIBC_2.27 + .weak __powf_compat + .set __powf_compat,__powf + .symver __powf_compat,powf@GLIBC_2.2 +diff --git a/sysdeps/ieee754/soft-fp/s_fdiv.c b/sysdeps/ieee754/soft-fp/s_fdiv.c +index 341339f5ed..7a15cbeee6 100644 +--- a/sysdeps/ieee754/soft-fp/s_fdiv.c ++++ b/sysdeps/ieee754/soft-fp/s_fdiv.c +@@ -25,6 +25,16 @@ + #undef fdivl + + #include ++#include ++ ++/* R_f[01] are not set in cases where they are not used in packing, ++ but the compiler does not see that they are set in all cases where ++ they are used, resulting in warnings that they may be used ++ uninitialized. The location of the warning differs in different ++ versions of GCC, it may be where R is defined using a macro or it ++ may be where the macro is defined. This happens only with -O1. */ ++DIAG_PUSH_NEEDS_COMMENT; ++DIAG_IGNORE_NEEDS_COMMENT (8, "-Wmaybe-uninitialized"); + #include + #include + #include +@@ -53,4 +63,6 @@ __fdiv (double x, double y) + CHECK_NARROW_DIV (ret, x, y); + return ret; + } ++DIAG_POP_NEEDS_COMMENT; ++ + libm_alias_float_double (div) +diff --git a/sysdeps/nptl/bits/thread-shared-types.h b/sysdeps/nptl/bits/thread-shared-types.h +index 1e2092a05d..05c94e7a71 100644 +--- a/sysdeps/nptl/bits/thread-shared-types.h ++++ b/sysdeps/nptl/bits/thread-shared-types.h +@@ -124,7 +124,27 @@ struct __pthread_mutex_s + unsigned int __nusers; + #endif + /* KIND must stay at this position in the structure to maintain +- binary compatibility with static initializers. */ ++ binary compatibility with static initializers. ++ ++ Concurrency notes: ++ The __kind of a mutex is initialized either by the static ++ PTHREAD_MUTEX_INITIALIZER or by a call to pthread_mutex_init. ++ ++ After a mutex has been initialized, the __kind of a mutex is usually not ++ changed. BUT it can be set to -1 in pthread_mutex_destroy or elision can ++ be enabled. This is done concurrently in the pthread_mutex_*lock functions ++ by using the macro FORCE_ELISION. This macro is only defined for ++ architectures which supports lock elision. ++ ++ For elision, there are the flags PTHREAD_MUTEX_ELISION_NP and ++ PTHREAD_MUTEX_NO_ELISION_NP which can be set in addition to the already set ++ type of a mutex. ++ Before a mutex is initialized, only PTHREAD_MUTEX_NO_ELISION_NP can be set ++ with pthread_mutexattr_settype. ++ After a mutex has been initialized, the functions pthread_mutex_*lock can ++ enable elision - if the mutex-type and the machine supports it - by setting ++ the flag PTHREAD_MUTEX_ELISION_NP. This is done concurrently. Afterwards ++ the lock / unlock functions are using specific elision code-paths. */ + int __kind; + __PTHREAD_COMPAT_PADDING_MID + #if __PTHREAD_MUTEX_NUSERS_AFTER_KIND +diff --git a/sysdeps/nptl/fork.c b/sysdeps/nptl/fork.c +index ec56a827eb..1a9429b579 100644 +--- a/sysdeps/nptl/fork.c ++++ b/sysdeps/nptl/fork.c +@@ -55,7 +55,7 @@ __libc_fork (void) + but our current fork implementation is not. */ + bool multiple_threads = THREAD_GETMEM (THREAD_SELF, header.multiple_threads); + +- __run_fork_handlers (atfork_run_prepare); ++ __run_fork_handlers (atfork_run_prepare, multiple_threads); + + /* If we are not running multiple threads, we do not have to + preserve lock state. If fork runs from a signal handler, only +@@ -134,7 +134,7 @@ __libc_fork (void) + __rtld_lock_initialize (GL(dl_load_lock)); + + /* Run the handlers registered for the child. */ +- __run_fork_handlers (atfork_run_child); ++ __run_fork_handlers (atfork_run_child, multiple_threads); + } + else + { +@@ -149,7 +149,7 @@ __libc_fork (void) + } + + /* Run the handlers registered for the parent. */ +- __run_fork_handlers (atfork_run_parent); ++ __run_fork_handlers (atfork_run_parent, multiple_threads); + } + + return pid; +diff --git a/sysdeps/nptl/fork.h b/sysdeps/nptl/fork.h +index 6eab61c121..bef2b7a8a6 100644 +--- a/sysdeps/nptl/fork.h ++++ b/sysdeps/nptl/fork.h +@@ -52,9 +52,11 @@ enum __run_fork_handler_type + - atfork_run_child: run all the CHILD_HANDLER and unlocks the internal + lock. + - atfork_run_parent: run all the PARENT_HANDLER and unlocks the internal +- lock. */ +-extern void __run_fork_handlers (enum __run_fork_handler_type who) +- attribute_hidden; ++ lock. ++ ++ Perform locking only if DO_LOCKING. */ ++extern void __run_fork_handlers (enum __run_fork_handler_type who, ++ _Bool do_locking) attribute_hidden; + + /* C library side function to register new fork handlers. */ + extern int __register_atfork (void (*__prepare) (void), +diff --git a/sysdeps/nptl/futex-internal.h b/sysdeps/nptl/futex-internal.h +index 1a5624789d..6fd27f0df6 100644 +--- a/sysdeps/nptl/futex-internal.h ++++ b/sysdeps/nptl/futex-internal.h +@@ -197,7 +197,7 @@ futex_wake (unsigned int* futex_word, int processes_to_wake, int private); + static __always_inline __attribute__ ((__noreturn__)) void + futex_fatal_error (void) + { +- __libc_fatal ("The futex facility returned an unexpected error code."); ++ __libc_fatal ("The futex facility returned an unexpected error code.\n"); + } + + #endif /* futex-internal.h */ +diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c +index 553833d1f2..c91b281e31 100644 +--- a/sysdeps/posix/getaddrinfo.c ++++ b/sysdeps/posix/getaddrinfo.c +@@ -488,7 +488,7 @@ gaih_inet (const char *name, const struct gaih_service *service, + malloc_name = true; + } + +- if (__inet_aton (name, (struct in_addr *) at->addr) != 0) ++ if (__inet_aton_exact (name, (struct in_addr *) at->addr) != 0) + { + if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET) + at->family = AF_INET; +diff --git a/sysdeps/powerpc/nptl/tcb-offsets.sym b/sysdeps/powerpc/nptl/tcb-offsets.sym +index e5bb2b376d..4c01615ad0 100644 +--- a/sysdeps/powerpc/nptl/tcb-offsets.sym ++++ b/sysdeps/powerpc/nptl/tcb-offsets.sym +@@ -21,7 +21,6 @@ DSO_SLOT2 (offsetof (tcbhead_t, dso_slot2) - TLS_TCB_OFFSET - sizeof (tcbhead_ + #ifdef __powerpc64__ + TCB_AT_PLATFORM (offsetof (tcbhead_t, at_platform) - TLS_TCB_OFFSET - sizeof(tcbhead_t)) + #endif +-TM_CAPABLE (offsetof (tcbhead_t, tm_capable) - TLS_TCB_OFFSET - sizeof (tcbhead_t)) + #ifndef __powerpc64__ + TCB_AT_PLATFORM (offsetof (tcbhead_t, at_platform) - TLS_TCB_OFFSET - sizeof(tcbhead_t)) + PADDING (offsetof (tcbhead_t, padding) - TLS_TCB_OFFSET - sizeof(tcbhead_t)) +diff --git a/sysdeps/powerpc/nptl/tls.h b/sysdeps/powerpc/nptl/tls.h +index f88fed5ecf..8317ca7cfa 100644 +--- a/sysdeps/powerpc/nptl/tls.h ++++ b/sysdeps/powerpc/nptl/tls.h +@@ -67,8 +67,7 @@ typedef struct + uint32_t padding; + uint32_t at_platform; + #endif +- /* Indicate if HTM capable (ISA 2.07). */ +- uint32_t tm_capable; ++ uint32_t __unused; + /* Reservation for AT_PLATFORM data - powerpc64. */ + #ifdef __powerpc64__ + uint32_t at_platform; +@@ -142,7 +141,6 @@ register void *__thread_register __asm__ ("r13"); + # define TLS_INIT_TP(tcbp) \ + ({ \ + __thread_register = (void *) (tcbp) + TLS_TCB_OFFSET; \ +- THREAD_SET_TM_CAPABLE (__tcb_hwcap & PPC_FEATURE2_HAS_HTM ? 1 : 0); \ + THREAD_SET_HWCAP (__tcb_hwcap); \ + THREAD_SET_AT_PLATFORM (__tcb_platform); \ + NULL; \ +@@ -151,8 +149,6 @@ register void *__thread_register __asm__ ("r13"); + /* Value passed to 'clone' for initialization of the thread register. */ + # define TLS_DEFINE_INIT_TP(tp, pd) \ + void *tp = (void *) (pd) + TLS_TCB_OFFSET + TLS_PRE_TCB_SIZE; \ +- (((tcbhead_t *) ((char *) tp - TLS_TCB_OFFSET))[-1].tm_capable) = \ +- THREAD_GET_TM_CAPABLE (); \ + (((tcbhead_t *) ((char *) tp - TLS_TCB_OFFSET))[-1].hwcap) = \ + THREAD_GET_HWCAP (); \ + (((tcbhead_t *) ((char *) tp - TLS_TCB_OFFSET))[-1].at_platform) = \ +@@ -210,13 +206,6 @@ register void *__thread_register __asm__ ("r13"); + + TLS_PRE_TCB_SIZE))[-1].pointer_guard \ + = THREAD_GET_POINTER_GUARD()) + +-/* tm_capable field in TCB head. */ +-# define THREAD_GET_TM_CAPABLE() \ +- (((tcbhead_t *) ((char *) __thread_register \ +- - TLS_TCB_OFFSET))[-1].tm_capable) +-# define THREAD_SET_TM_CAPABLE(value) \ +- (THREAD_GET_TM_CAPABLE () = (value)) +- + /* hwcap field in TCB head. */ + # define THREAD_GET_HWCAP() \ + (((tcbhead_t *) ((char *) __thread_register \ +diff --git a/sysdeps/powerpc/powerpc32/dl-irel.h b/sysdeps/powerpc/powerpc32/dl-irel.h +index a7368b2582..61d0e4cf61 100644 +--- a/sysdeps/powerpc/powerpc32/dl-irel.h ++++ b/sysdeps/powerpc/powerpc32/dl-irel.h +@@ -46,7 +46,7 @@ elf_irela (const Elf32_Rela *reloc) + *reloc_addr = value; + } + else +- __libc_fatal ("unexpected reloc type in static binary"); ++ __libc_fatal ("Unexpected reloc type in static binary.\n"); + } + + #endif /* dl-irel.h */ +diff --git a/sysdeps/powerpc/powerpc32/sysdep.h b/sysdeps/powerpc/powerpc32/sysdep.h +index 5f1294ead3..93097c5459 100644 +--- a/sysdeps/powerpc/powerpc32/sysdep.h ++++ b/sysdeps/powerpc/powerpc32/sysdep.h +@@ -90,24 +90,7 @@ GOT_LABEL: ; \ + cfi_endproc; \ + ASM_SIZE_DIRECTIVE(name) + +-#if !IS_IN(rtld) && !defined(__SPE__) +-# define ABORT_TRANSACTION_IMPL \ +- cmpwi 2,0; \ +- beq 1f; \ +- lwz 0,TM_CAPABLE(2); \ +- cmpwi 0,0; \ +- beq 1f; \ +- li 11,_ABORT_SYSCALL; \ +- tabort. 11; \ +- .align 4; \ +-1: +-#else +-# define ABORT_TRANSACTION_IMPL +-#endif +-#define ABORT_TRANSACTION ABORT_TRANSACTION_IMPL +- + #define DO_CALL(syscall) \ +- ABORT_TRANSACTION \ + li 0,syscall; \ + sc + +diff --git a/sysdeps/powerpc/powerpc64/addmul_1.S b/sysdeps/powerpc/powerpc64/addmul_1.S +index 48e3b1b290..e450d6a52c 100644 +--- a/sysdeps/powerpc/powerpc64/addmul_1.S ++++ b/sysdeps/powerpc/powerpc64/addmul_1.S +@@ -34,16 +34,27 @@ + #define N r5 + #define VL r6 + ++#define R27SAVE (-40) ++#define R28SAVE (-32) ++#define R29SAVE (-24) ++#define R30SAVE (-16) ++#define R31SAVE (-8) ++ + ENTRY_TOCLESS (FUNC, 5) +- std r31, -8(r1) ++ std r31, R31SAVE(r1) + rldicl. r0, N, 0, 62 +- std r30, -16(r1) ++ std r30, R30SAVE(r1) + cmpdi VL, r0, 2 +- std r29, -24(r1) ++ std r29, R29SAVE(r1) + addi N, N, 3 +- std r28, -32(r1) ++ std r28, R28SAVE(r1) + srdi N, N, 2 +- std r27, -40(r1) ++ std r27, R27SAVE(r1) ++ cfi_offset(r31, R31SAVE) ++ cfi_offset(r30, R30SAVE) ++ cfi_offset(r29, R29SAVE) ++ cfi_offset(r28, R28SAVE) ++ cfi_offset(r27, R27SAVE) + mtctr N + beq cr0, L(b00) + blt cr6, L(b01) +@@ -199,10 +210,10 @@ L(end): mulld r0, r9, VL + addic r11, r11, 1 + #endif + addze RP, r8 +- ld r31, -8(r1) +- ld r30, -16(r1) +- ld r29, -24(r1) +- ld r28, -32(r1) +- ld r27, -40(r1) ++ ld r31, R31SAVE(r1) ++ ld r30, R30SAVE(r1) ++ ld r29, R29SAVE(r1) ++ ld r28, R28SAVE(r1) ++ ld r27, R27SAVE(r1) + blr + END(FUNC) +diff --git a/sysdeps/powerpc/powerpc64/dl-irel.h b/sysdeps/powerpc/powerpc64/dl-irel.h +index ab13c04358..2fd0ee8a86 100644 +--- a/sysdeps/powerpc/powerpc64/dl-irel.h ++++ b/sysdeps/powerpc/powerpc64/dl-irel.h +@@ -57,7 +57,7 @@ elf_irela (const Elf64_Rela *reloc) + #endif + } + else +- __libc_fatal ("unexpected reloc type in static binary"); ++ __libc_fatal ("Unexpected reloc type in static binary.\n"); + } + + #endif /* dl-irel.h */ +diff --git a/sysdeps/powerpc/powerpc64/lshift.S b/sysdeps/powerpc/powerpc64/lshift.S +index 8b6396ee6c..855d6f2993 100644 +--- a/sysdeps/powerpc/powerpc64/lshift.S ++++ b/sysdeps/powerpc/powerpc64/lshift.S +@@ -26,11 +26,15 @@ + #define TNC r0 + #define U0 r30 + #define U1 r31 ++#define U0SAVE (-16) ++#define U1SAVE (-8) + #define RETVAL r5 + + ENTRY_TOCLESS (__mpn_lshift, 5) +- std U1, -8(r1) +- std U0, -16(r1) ++ std U1, U1SAVE(r1) ++ std U0, U0SAVE(r1) ++ cfi_offset(U1, U1SAVE) ++ cfi_offset(U0, U0SAVE) + subfic TNC, CNT, 64 + sldi r7, N, RP + add UP, UP, r7 +@@ -170,8 +174,8 @@ L(cj3): or r10, r12, r7 + L(cj2): std r10, -32(RP) + std r8, -40(RP) + +-L(ret): ld U1, -8(r1) +- ld U0, -16(r1) ++L(ret): ld U1, U1SAVE(r1) ++ ld U0, U0SAVE(r1) + mr RP, RETVAL + blr + END(__mpn_lshift) +diff --git a/sysdeps/powerpc/powerpc64/mul_1.S b/sysdeps/powerpc/powerpc64/mul_1.S +index 953ded8028..cade365258 100644 +--- a/sysdeps/powerpc/powerpc64/mul_1.S ++++ b/sysdeps/powerpc/powerpc64/mul_1.S +@@ -24,9 +24,14 @@ + #define N r5 + #define VL r6 + ++#define R26SAVE (-48) ++#define R27SAVE (-40) ++ + ENTRY_TOCLESS (__mpn_mul_1, 5) +- std r27, -40(r1) +- std r26, -48(r1) ++ std r27, R27SAVE(r1) ++ std r26, R26SAVE(r1) ++ cfi_offset(r27, R27SAVE) ++ cfi_offset(r26, R26SAVE) + li r12, 0 + ld r26, 0(UP) + +@@ -129,7 +134,7 @@ L(end): mulld r0, r26, VL + std r0, 0(RP) + std r7, 8(RP) + L(ret): addze RP, r8 +- ld r27, -40(r1) +- ld r26, -48(r1) ++ ld r27, R27SAVE(r1) ++ ld r26, R26SAVE(r1) + blr + END(__mpn_mul_1) +diff --git a/sysdeps/powerpc/powerpc64/sysdep.h b/sysdeps/powerpc/powerpc64/sysdep.h +index 2df1d9b6e6..50e64f9ce2 100644 +--- a/sysdeps/powerpc/powerpc64/sysdep.h ++++ b/sysdeps/powerpc/powerpc64/sysdep.h +@@ -263,24 +263,7 @@ LT_LABELSUFFIX(name,_name_end): ; \ + TRACEBACK_MASK(name,mask); \ + END_2(name) + +-#if !IS_IN(rtld) +-# define ABORT_TRANSACTION_IMPL \ +- cmpdi 13,0; \ +- beq 1f; \ +- lwz 0,TM_CAPABLE(13); \ +- cmpwi 0,0; \ +- beq 1f; \ +- li 11,_ABORT_SYSCALL; \ +- tabort. 11; \ +- .p2align 4; \ +-1: +-#else +-# define ABORT_TRANSACTION_IMPL +-#endif +-#define ABORT_TRANSACTION ABORT_TRANSACTION_IMPL +- + #define DO_CALL(syscall) \ +- ABORT_TRANSACTION \ + li 0,syscall; \ + sc + +diff --git a/sysdeps/powerpc/sysdep.h b/sysdeps/powerpc/sysdep.h +index 8a6d236caa..c8bf25e870 100644 +--- a/sysdeps/powerpc/sysdep.h ++++ b/sysdeps/powerpc/sysdep.h +@@ -21,8 +21,6 @@ + */ + #define _SYSDEPS_SYSDEP_H 1 + #include +-#include +-#include + + #define PPC_FEATURE_970 (PPC_FEATURE_POWER4 + PPC_FEATURE_HAS_ALTIVEC) + +@@ -166,22 +164,4 @@ + #define ALIGNARG(log2) log2 + #define ASM_SIZE_DIRECTIVE(name) .size name,.-name + +-#else +- +-/* Linux kernel powerpc documentation [1] states issuing a syscall inside a +- transaction is not recommended and may lead to undefined behavior. It +- also states syscalls do not abort transactions. To avoid such traps, +- we abort transaction just before syscalls. +- +- [1] Documentation/powerpc/transactional_memory.txt [Syscalls] */ +-#if !IS_IN(rtld) && !defined(__SPE__) +-# define ABORT_TRANSACTION \ +- ({ \ +- if (THREAD_GET_TM_CAPABLE ()) \ +- __libc_tabort (_ABORT_SYSCALL); \ +- }) +-#else +-# define ABORT_TRANSACTION +-#endif +- + #endif /* __ASSEMBLER__ */ +diff --git a/sysdeps/riscv/rv64/rvd/libm-test-ulps b/sysdeps/riscv/rv64/rvd/libm-test-ulps +index f8feadcd0d..61be2df60d 100644 +--- a/sysdeps/riscv/rv64/rvd/libm-test-ulps ++++ b/sysdeps/riscv/rv64/rvd/libm-test-ulps +@@ -1006,6 +1006,8 @@ ildouble: 2 + ldouble: 2 + + Function: "cos": ++double: 1 ++idouble: 1 + ildouble: 1 + ldouble: 1 + +@@ -1348,9 +1350,9 @@ ildouble: 4 + ldouble: 4 + + Function: Imaginary part of "ctan_towardzero": +-double: 1 ++double: 2 + float: 2 +-idouble: 1 ++idouble: 2 + ifloat: 2 + ildouble: 5 + ldouble: 5 +@@ -1898,10 +1900,12 @@ ldouble: 2 + Function: "log_upward": + double: 1 + idouble: 1 +-ildouble: 1 +-ldouble: 1 ++ildouble: 2 ++ldouble: 2 + + Function: "pow": ++double: 1 ++idouble: 1 + ildouble: 2 + ldouble: 2 + +@@ -1930,6 +1934,8 @@ ildouble: 2 + ldouble: 2 + + Function: "sin": ++double: 1 ++idouble: 1 + ildouble: 1 + ldouble: 1 + +@@ -1952,6 +1958,8 @@ ildouble: 3 + ldouble: 3 + + Function: "sincos": ++double: 1 ++idouble: 1 + ildouble: 1 + ldouble: 1 + +diff --git a/sysdeps/riscv/rvf/math_private.h b/sysdeps/riscv/rvf/math_private.h +index cdb7858fc8..ca587620cb 100644 +--- a/sysdeps/riscv/rvf/math_private.h ++++ b/sysdeps/riscv/rvf/math_private.h +@@ -72,8 +72,8 @@ libc_fesetround_riscv (int round) + static __always_inline void + libc_feholdexcept_setround_riscv (fenv_t *envp, int round) + { +- libc_fesetround_riscv (round); + libc_feholdexcept_riscv (envp); ++ libc_fesetround_riscv (round); + } + + #define libc_feholdexcept_setround libc_feholdexcept_setround_riscv +diff --git a/sysdeps/riscv/start.S b/sysdeps/riscv/start.S +index 4635ddb5eb..2d6f06e630 100644 +--- a/sysdeps/riscv/start.S ++++ b/sysdeps/riscv/start.S +@@ -43,6 +43,10 @@ + __libc_start_main wants this in a5. */ + + ENTRY (ENTRY_POINT) ++ /* Terminate call stack by noting ra is undefined. Use a dummy ++ .cfi_label to force starting the FDE. */ ++ .cfi_label .Ldummy ++ cfi_undefined (ra) + call .Lload_gp + mv a5, a0 /* rtld_fini. */ + /* main may be in a shared library. */ +@@ -54,7 +58,8 @@ ENTRY (ENTRY_POINT) + lla a4, __libc_csu_fini + mv a6, sp /* stack_end. */ + +- tail __libc_start_main@plt ++ call __libc_start_main@plt ++ ebreak + END (ENTRY_POINT) + + /* Dynamic links need the global pointer to be initialized prior to calling +diff --git a/sysdeps/s390/dl-irel.h b/sysdeps/s390/dl-irel.h +index d8ba7ba427..ecb24f0a9b 100644 +--- a/sysdeps/s390/dl-irel.h ++++ b/sysdeps/s390/dl-irel.h +@@ -46,7 +46,7 @@ elf_irela (const ElfW(Rela) *reloc) + *reloc_addr = value; + } + else +- __libc_fatal ("unexpected reloc type in static binary"); ++ __libc_fatal ("Unexpected reloc type in static binary.\n"); + } + + #endif /* dl-irel.h */ +diff --git a/sysdeps/sparc/sparc32/dl-irel.h b/sysdeps/sparc/sparc32/dl-irel.h +index ffca36864f..cf47cda834 100644 +--- a/sysdeps/sparc/sparc32/dl-irel.h ++++ b/sysdeps/sparc/sparc32/dl-irel.h +@@ -56,7 +56,7 @@ elf_irela (const Elf32_Rela *reloc) + else if (r_type == R_SPARC_NONE) + ; + else +- __libc_fatal ("unexpected reloc type in static binary"); ++ __libc_fatal ("Unexpected reloc type in static binary.\n"); + } + + #endif /* dl-irel.h */ +diff --git a/sysdeps/sparc/sparc64/dl-irel.h b/sysdeps/sparc/sparc64/dl-irel.h +index c5cd3057ac..446fed1836 100644 +--- a/sysdeps/sparc/sparc64/dl-irel.h ++++ b/sysdeps/sparc/sparc64/dl-irel.h +@@ -59,7 +59,7 @@ elf_irela (const Elf64_Rela *reloc) + else if (r_type == R_SPARC_NONE) + ; + else +- __libc_fatal ("unexpected reloc type in static binary"); ++ __libc_fatal ("Unexpected reloc type in static binary.\n"); + } + + #endif /* dl-irel.h */ +diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile +index f71cc39c7e..773aaea0e9 100644 +--- a/sysdeps/unix/sysv/linux/Makefile ++++ b/sysdeps/unix/sysv/linux/Makefile +@@ -161,6 +161,7 @@ inhibit-glue = yes + + ifeq ($(subdir),dirent) + sysdep_routines += getdirentries getdirentries64 ++tests-internal += tst-readdir64-compat + endif + + ifeq ($(subdir),nis) +diff --git a/sysdeps/unix/sysv/linux/arm/atomic-machine.h b/sysdeps/unix/sysv/linux/arm/atomic-machine.h +index ad165274d8..a5d244e65e 100644 +--- a/sysdeps/unix/sysv/linux/arm/atomic-machine.h ++++ b/sysdeps/unix/sysv/linux/arm/atomic-machine.h +@@ -49,16 +49,23 @@ + declarations of A_OLDVAL et al because when NEWVAL or OLDVAL is of the + form *PTR and PTR has a 'volatile ... *' type, then __typeof (*PTR) has + a 'volatile ...' type and this triggers -Wvolatile-register-var to +- complain about 'register volatile ... asm ("reg")'. */ ++ complain about 'register volatile ... asm ("reg")'. ++ ++ We use the same union trick in the declaration of A_PTR because when ++ MEM is of the from *PTR and PTR has a 'const ... *' type, then __typeof ++ (*PTR) has a 'const ...' type and this enables the compiler to substitute ++ the variable with its initializer in asm statements, which may cause the ++ corresponding operand to appear in a different register. */ + #ifdef __thumb2__ + /* Thumb-2 has ldrex/strex. However it does not have barrier instructions, + so we still need to use the kernel helper. */ + # define __arm_assisted_compare_and_exchange_val_32_acq(mem, newval, oldval) \ +- ({ union { __typeof (oldval) a; uint32_t v; } oldval_arg = { .a = (oldval) };\ ++ ({ union { __typeof (mem) a; uint32_t v; } mem_arg = { .a = (mem) }; \ ++ union { __typeof (oldval) a; uint32_t v; } oldval_arg = { .a = (oldval) };\ + union { __typeof (newval) a; uint32_t v; } newval_arg = { .a = (newval) };\ + register uint32_t a_oldval asm ("r0"); \ + register uint32_t a_newval asm ("r1") = newval_arg.v; \ +- register __typeof (mem) a_ptr asm ("r2") = (mem); \ ++ register uint32_t a_ptr asm ("r2") = mem_arg.v; \ + register uint32_t a_tmp asm ("r3"); \ + register uint32_t a_oldval2 asm ("r4") = oldval_arg.v; \ + __asm__ __volatile__ \ +@@ -79,11 +86,12 @@ + (__typeof (oldval)) a_tmp; }) + #else + # define __arm_assisted_compare_and_exchange_val_32_acq(mem, newval, oldval) \ +- ({ union { __typeof (oldval) a; uint32_t v; } oldval_arg = { .a = (oldval) };\ ++ ({ union { __typeof (mem) a; uint32_t v; } mem_arg = { .a = (mem) }; \ ++ union { __typeof (oldval) a; uint32_t v; } oldval_arg = { .a = (oldval) };\ + union { __typeof (newval) a; uint32_t v; } newval_arg = { .a = (newval) };\ + register uint32_t a_oldval asm ("r0"); \ + register uint32_t a_newval asm ("r1") = newval_arg.v; \ +- register __typeof (mem) a_ptr asm ("r2") = (mem); \ ++ register uint32_t a_ptr asm ("r2") = mem_arg.v; \ + register uint32_t a_tmp asm ("r3"); \ + register uint32_t a_oldval2 asm ("r4") = oldval_arg.v; \ + __asm__ __volatile__ \ +diff --git a/sysdeps/unix/sysv/linux/bits/types/siginfo_t.h b/sysdeps/unix/sysv/linux/bits/types/siginfo_t.h +index 33766d1813..43c4e009a4 100644 +--- a/sysdeps/unix/sysv/linux/bits/types/siginfo_t.h ++++ b/sysdeps/unix/sysv/linux/bits/types/siginfo_t.h +@@ -107,7 +107,7 @@ typedef struct + /* SIGPOLL. */ + struct + { +- long int si_band; /* Band event for SIGPOLL. */ ++ __SI_BAND_TYPE si_band; /* Band event for SIGPOLL. */ + int si_fd; + } _sigpoll; + +diff --git a/sysdeps/unix/sysv/linux/getdents64.c b/sysdeps/unix/sysv/linux/getdents64.c +index 3bde0cf4f0..46eb5f4419 100644 +--- a/sysdeps/unix/sysv/linux/getdents64.c ++++ b/sysdeps/unix/sysv/linux/getdents64.c +@@ -33,41 +33,90 @@ strong_alias (__getdents64, __getdents) + # include + + # if SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_2) +-# include ++# include ++# include + +-/* kernel definition of as of 3.2. */ +-struct compat_linux_dirent ++static ssize_t ++handle_overflow (int fd, __off64_t offset, ssize_t count) + { +- /* Both d_ino and d_off are compat_ulong_t which are defined in all +- architectures as 'u32'. */ +- uint32_t d_ino; +- uint32_t d_off; +- unsigned short d_reclen; +- char d_name[1]; +-}; ++ /* If this is the first entry in the buffer, we can report the ++ error. */ ++ if (offset == 0) ++ { ++ __set_errno (EOVERFLOW); ++ return -1; ++ } ++ ++ /* Otherwise, seek to the overflowing entry, so that the next call ++ will report the error, and return the data read so far. */ ++ if (__lseek64 (fd, offset, SEEK_SET) != 0) ++ return -1; ++ return count; ++} + + ssize_t + __old_getdents64 (int fd, char *buf, size_t nbytes) + { +- ssize_t retval = INLINE_SYSCALL_CALL (getdents, fd, buf, nbytes); ++ /* We do not move the individual directory entries. This is only ++ possible if the target type (struct __old_dirent64) is smaller ++ than the source type. */ ++ _Static_assert (offsetof (struct __old_dirent64, d_name) ++ <= offsetof (struct dirent64, d_name), ++ "__old_dirent64 is larger than dirent64"); ++ _Static_assert (__alignof__ (struct __old_dirent64) ++ <= __alignof__ (struct dirent64), ++ "alignment of __old_dirent64 is larger than dirent64"); + +- /* The kernel added the d_type value after the name. Change this now. */ +- if (retval != -1) ++ ssize_t retval = INLINE_SYSCALL_CALL (getdents64, fd, buf, nbytes); ++ if (retval > 0) + { +- union +- { +- struct compat_linux_dirent k; +- struct dirent u; +- } *kbuf = (void *) buf; ++ /* This is the marker for the first entry. Offset 0 is reserved ++ for the first entry (see rewinddir). Here, we use it as a ++ marker for the first entry in the buffer. We never actually ++ seek to offset 0 because handle_overflow reports the error ++ directly, so it does not matter that the offset is incorrect ++ if entries have been read from the descriptor before (so that ++ the descriptor is not actually at offset 0). */ ++ __off64_t previous_offset = 0; + +- while ((char *) kbuf < buf + retval) ++ char *p = buf; ++ char *end = buf + retval; ++ while (p < end) + { +- char d_type = *((char *) kbuf + kbuf->k.d_reclen - 1); +- memmove (kbuf->u.d_name, kbuf->k.d_name, +- strlen (kbuf->k.d_name) + 1); +- kbuf->u.d_type = d_type; ++ struct dirent64 *source = (struct dirent64 *) p; ++ ++ /* Copy out the fixed-size data. */ ++ __ino_t ino = source->d_ino; ++ __off64_t offset = source->d_off; ++ unsigned int reclen = source->d_reclen; ++ unsigned char type = source->d_type; ++ ++ /* Check for ino_t overflow. */ ++ if (__glibc_unlikely (ino != source->d_ino)) ++ return handle_overflow (fd, previous_offset, p - buf); ++ ++ /* Convert to the target layout. Use a separate struct and ++ memcpy to side-step aliasing issues. */ ++ struct __old_dirent64 result; ++ result.d_ino = ino; ++ result.d_off = offset; ++ result.d_reclen = reclen; ++ result.d_type = type; ++ ++ /* Write the fixed-sized part of the result to the ++ buffer. */ ++ size_t result_name_offset = offsetof (struct __old_dirent64, d_name); ++ memcpy (p, &result, result_name_offset); ++ ++ /* Adjust the position of the name if necessary. Copy ++ everything until the end of the record, including the ++ terminating NUL byte. */ ++ if (result_name_offset != offsetof (struct dirent64, d_name)) ++ memmove (p + result_name_offset, source->d_name, ++ reclen - offsetof (struct dirent64, d_name)); + +- kbuf = (void *) ((char *) kbuf + kbuf->k.d_reclen); ++ p += reclen; ++ previous_offset = offset; + } + } + return retval; +diff --git a/sysdeps/unix/sysv/linux/gethostid.c b/sysdeps/unix/sysv/linux/gethostid.c +index 2e20f034dc..ee0190e7f9 100644 +--- a/sysdeps/unix/sysv/linux/gethostid.c ++++ b/sysdeps/unix/sysv/linux/gethostid.c +@@ -102,12 +102,12 @@ gethostid (void) + { + int ret = __gethostbyname_r (hostname, &hostbuf, + tmpbuf.data, tmpbuf.length, &hp, &herr); +- if (ret == 0) ++ if (ret == 0 && hp != NULL) + break; + else + { + /* Enlarge the buffer on ERANGE. */ +- if (herr == NETDB_INTERNAL && errno == ERANGE) ++ if (ret != 0 && herr == NETDB_INTERNAL && errno == ERANGE) + { + if (!scratch_buffer_grow (&tmpbuf)) + return 0; +diff --git a/sysdeps/unix/sysv/linux/if_index.c b/sysdeps/unix/sysv/linux/if_index.c +index e3d08982d9..782fc5e175 100644 +--- a/sysdeps/unix/sysv/linux/if_index.c ++++ b/sysdeps/unix/sysv/linux/if_index.c +@@ -38,11 +38,6 @@ __if_nametoindex (const char *ifname) + return 0; + #else + struct ifreq ifr; +- int fd = __opensock (); +- +- if (fd < 0) +- return 0; +- + if (strlen (ifname) >= IFNAMSIZ) + { + __set_errno (ENODEV); +@@ -50,6 +45,12 @@ __if_nametoindex (const char *ifname) + } + + strncpy (ifr.ifr_name, ifname, sizeof (ifr.ifr_name)); ++ ++ int fd = __opensock (); ++ ++ if (fd < 0) ++ return 0; ++ + if (__ioctl (fd, SIOCGIFINDEX, &ifr) < 0) + { + int saved_errno = errno; +diff --git a/sysdeps/unix/sysv/linux/kernel_sigaction.h b/sysdeps/unix/sysv/linux/kernel_sigaction.h +index 2dbec08099..1c36146d46 100644 +--- a/sysdeps/unix/sysv/linux/kernel_sigaction.h ++++ b/sysdeps/unix/sysv/linux/kernel_sigaction.h +@@ -1,19 +1,27 @@ + #ifndef _KERNEL_SIGACTION_H + # define _KERNEL_SIGACTION_H + ++#ifdef SA_RESTORER ++# define HAS_SA_RESTORER 1 ++#endif ++ + /* This is the sigaction structure from the Linux 3.2 kernel. */ + struct kernel_sigaction + { + __sighandler_t k_sa_handler; + unsigned long sa_flags; +-#ifdef SA_RESTORER ++#ifdef HAS_SA_RESTORER + void (*sa_restorer) (void); + #endif ++ /* glibc sigset is larger than kernel expected one, however sigaction ++ passes the kernel expected size on rt_sigaction syscall. */ + sigset_t sa_mask; + }; + +-#ifndef SA_RESTORER ++#ifndef SET_SA_RESTORER + # define SET_SA_RESTORER(kact, act) ++#endif ++#ifndef RESET_SA_RESTORER + # define RESET_SA_RESTORER(act, kact) + #endif + +diff --git a/sysdeps/unix/sysv/linux/m68k/kernel_sigaction.h b/sysdeps/unix/sysv/linux/m68k/kernel_sigaction.h +index 54972feb13..464b351d6d 100644 +--- a/sysdeps/unix/sysv/linux/m68k/kernel_sigaction.h ++++ b/sysdeps/unix/sysv/linux/m68k/kernel_sigaction.h +@@ -1,22 +1,4 @@ +-#ifndef _KERNEL_SIGACTION_H +-# define _KERNEL_SIGACTION_H +- +-#include +- +-#define SA_RESTORER 0x04000000 +- +-/* This is the sigaction structure from the Linux 3.2 kernel. */ +-struct kernel_sigaction +-{ +- __sighandler_t k_sa_handler; +- sigset_t sa_mask; +- unsigned long sa_flags; +- void (*sa_restorer) (void); +-}; +- +-#define SET_SA_RESTORER(kact, act) \ +- (kact)->sa_restorer = (act)->sa_restorer +-#define RESET_SA_RESTORER(act, kact) \ +- (act)->sa_restorer = (kact)->sa_restorer +- +-#endif ++/* m68k does not define SA_RESTORER, but does have sa_restorer member ++ on kernel sigaction struct. */ ++#define HAS_SA_RESTORER 1 ++#include +diff --git a/sysdeps/unix/sysv/linux/netlink_assert_response.c b/sysdeps/unix/sysv/linux/netlink_assert_response.c +index f31ccb52ff..6afc3a17ce 100644 +--- a/sysdeps/unix/sysv/linux/netlink_assert_response.c ++++ b/sysdeps/unix/sysv/linux/netlink_assert_response.c +@@ -72,12 +72,12 @@ __netlink_assert_response (int fd, ssize_t result) + char message[200]; + if (family < 0) + __snprintf (message, sizeof (message), +- "Unexpected error %d on netlink descriptor %d", ++ "Unexpected error %d on netlink descriptor %d.\n", + error_code, fd); + else + __snprintf (message, sizeof (message), + "Unexpected error %d on netlink descriptor %d" +- " (address family %d)", ++ " (address family %d).\n", + error_code, fd, family); + __libc_fatal (message); + } +diff --git a/sysdeps/unix/sysv/linux/nios2/kernel_sigaction.h b/sysdeps/unix/sysv/linux/nios2/kernel_sigaction.h +index 4ada322104..89f9bcedfd 100644 +--- a/sysdeps/unix/sysv/linux/nios2/kernel_sigaction.h ++++ b/sysdeps/unix/sysv/linux/nios2/kernel_sigaction.h +@@ -1,8 +1,9 @@ + /* NIOS2 uses the generic Linux UAPI but defines SA_RESTORER. */ + #define SA_RESTORER 0x04000000 +-#include + + #define SET_SA_RESTORER(kact, act) \ + (kact)->sa_restorer = (act)->sa_restorer + #define RESET_SA_RESTORER(act, kact) \ + (act)->sa_restorer = (kact)->sa_restorer ++ ++#include +diff --git a/sysdeps/unix/sysv/linux/powerpc/elision-conf.c b/sysdeps/unix/sysv/linux/powerpc/elision-conf.c +index 906882a65e..fc82bd1ad8 100644 +--- a/sysdeps/unix/sysv/linux/powerpc/elision-conf.c ++++ b/sysdeps/unix/sysv/linux/powerpc/elision-conf.c +@@ -127,6 +127,26 @@ elision_init (int argc __attribute__ ((unused)), + TUNABLE_CALLBACK (set_elision_skip_trylock_internal_abort)); + #endif + ++ /* Linux from 3.9 through 4.2 do not abort HTM transaction on syscalls, ++ instead it suspends the transaction and resumes it when returning to ++ usercode. The side-effects of the syscall will always remain visible, ++ even if the transaction is aborted. This is an issue when a transaction ++ is used along with futex syscall, on pthread_cond_wait for instance, ++ where futex might succeed but the transaction is rolled back leading ++ the condition variable object in an inconsistent state. ++ ++ Glibc used to prevent it by always aborting a transaction before issuing ++ a syscall. Linux 4.2 also decided to abort active transaction in ++ syscalls which makes the glibc workaround superflours. Worse, glibc ++ transaction abortions leads to a performance issues on recent kernels. ++ ++ So Lock Elision is just enabled when it has been explict set (either ++ by tunables of by a configure switch) and if kernel aborts HTM ++ transactions on syscalls (PPC_FEATURE2_HTM_NOSC) */ ++ ++ __pthread_force_elision = (__pthread_force_elision ++ && GLRO (dl_hwcap2) & PPC_FEATURE2_HTM_NOSC); ++ + if (!__pthread_force_elision) + __elision_aconf.try_tbegin = 0; /* Disable elision on rwlocks. */ + } +diff --git a/sysdeps/unix/sysv/linux/powerpc/force-elision.h b/sysdeps/unix/sysv/linux/powerpc/force-elision.h +index fe5d6ceade..d8f5a4b1c7 100644 +--- a/sysdeps/unix/sysv/linux/powerpc/force-elision.h ++++ b/sysdeps/unix/sysv/linux/powerpc/force-elision.h +@@ -18,9 +18,45 @@ + + /* Automatically enable elision for existing user lock kinds. */ + #define FORCE_ELISION(m, s) \ +- if (__pthread_force_elision \ +- && (m->__data.__kind & PTHREAD_MUTEX_ELISION_FLAGS_NP) == 0) \ ++ if (__pthread_force_elision) \ + { \ +- mutex->__data.__kind |= PTHREAD_MUTEX_ELISION_NP; \ +- s; \ ++ /* See concurrency notes regarding __kind in \ ++ struct __pthread_mutex_s in \ ++ sysdeps/nptl/bits/thread-shared-types.h. \ ++ \ ++ There are the following cases for the kind of a mutex \ ++ (The mask PTHREAD_MUTEX_ELISION_FLAGS_NP covers the flags \ ++ PTHREAD_MUTEX_ELISION_NP and PTHREAD_MUTEX_NO_ELISION_NP where \ ++ only one of both flags can be set): \ ++ - both flags are not set: \ ++ This is the first lock operation for this mutex. Enable \ ++ elision as it is not enabled so far. \ ++ Note: It can happen that multiple threads are calling e.g. \ ++ pthread_mutex_lock at the same time as the first lock \ ++ operation for this mutex. Then elision is enabled for this \ ++ mutex by multiple threads. Storing with relaxed MO is enough \ ++ as all threads will store the same new value for the kind of \ ++ the mutex. But we have to ensure that we always use the \ ++ elision path regardless if this thread has enabled elision or \ ++ another one. \ ++ \ ++ - PTHREAD_MUTEX_ELISION_NP flag is set: \ ++ Elision was already enabled for this mutex by a previous lock \ ++ operation. See case above. Just use the elision path. \ ++ \ ++ - PTHREAD_MUTEX_NO_ELISION_NP flag is set: \ ++ Elision was explicitly disabled by pthread_mutexattr_settype. \ ++ Do not use the elision path. \ ++ Note: The flag PTHREAD_MUTEX_NO_ELISION_NP will never be \ ++ changed after mutex initialization. */ \ ++ int mutex_kind = atomic_load_relaxed (&((m)->__data.__kind)); \ ++ if ((mutex_kind & PTHREAD_MUTEX_ELISION_FLAGS_NP) == 0) \ ++ { \ ++ mutex_kind |= PTHREAD_MUTEX_ELISION_NP; \ ++ atomic_store_relaxed (&((m)->__data.__kind), mutex_kind); \ ++ } \ ++ if ((mutex_kind & PTHREAD_MUTEX_ELISION_NP) != 0) \ ++ { \ ++ s; \ ++ } \ + } +diff --git a/sysdeps/unix/sysv/linux/powerpc/kernel_sigaction.h b/sysdeps/unix/sysv/linux/powerpc/kernel_sigaction.h +index aef3d5a3b3..bac03ee45d 100644 +--- a/sysdeps/unix/sysv/linux/powerpc/kernel_sigaction.h ++++ b/sysdeps/unix/sysv/linux/powerpc/kernel_sigaction.h +@@ -1,9 +1,10 @@ + /* powerpc kernel sigaction is similar to generic Linux UAPI one, + but the architecture also defines SA_RESTORER. */ + #define SA_RESTORER 0x04000000 +-#include + + #define SET_SA_RESTORER(kact, act) \ + (kact)->sa_restorer = (act)->sa_restorer + #define RESET_SA_RESTORER(act, kact) \ + (act)->sa_restorer = (kact)->sa_restorer ++ ++#include +diff --git a/sysdeps/unix/sysv/linux/powerpc/not-errno.h b/sysdeps/unix/sysv/linux/powerpc/not-errno.h +deleted file mode 100644 +index 27da21bdf1..0000000000 +--- a/sysdeps/unix/sysv/linux/powerpc/not-errno.h ++++ /dev/null +@@ -1,30 +0,0 @@ +-/* Syscall wrapper that do not set errno. Linux powerpc version. +- 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 +- . */ +- +-/* __access_noerrno is used during process initialization in elf/dl-tunables.c +- before the TCB is initialized, prohibiting the usage of +- ABORT_TRANSACTION. */ +-#undef ABORT_TRANSACTION +-#define ABORT_TRANSACTION +- +-#include "sysdeps/unix/sysv/linux/not-errno.h" +- +-/* Recover ABORT_TRANSACTION's previous value, in order to not affect +- other syscalls. */ +-#undef ABORT_TRANSACTION +-#define ABORT_TRANSACTION ABORT_TRANSACTION_IMPL +diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h b/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h +index f7277d59e1..ec5c5250f8 100644 +--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h ++++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h +@@ -109,7 +109,6 @@ + register long int r11 __asm__ ("r11"); \ + register long int r12 __asm__ ("r12"); \ + LOADARGS_##nr(name, args); \ +- ABORT_TRANSACTION; \ + __asm__ __volatile__ \ + ("sc \n\t" \ + "mfcr %0" \ +diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h b/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h +index 0956cf04a7..1f17f7bd5f 100644 +--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h ++++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h +@@ -131,7 +131,6 @@ + register long int r7 __asm__ ("r7"); \ + register long int r8 __asm__ ("r8"); \ + LOADARGS_##nr (name, ##args); \ +- ABORT_TRANSACTION; \ + __asm__ __volatile__ \ + ("sc\n\t" \ + "mfcr %0\n\t" \ +diff --git a/sysdeps/unix/sysv/linux/powerpc/syscall.S b/sysdeps/unix/sysv/linux/powerpc/syscall.S +index 2da91721be..bbab613aca 100644 +--- a/sysdeps/unix/sysv/linux/powerpc/syscall.S ++++ b/sysdeps/unix/sysv/linux/powerpc/syscall.S +@@ -18,7 +18,6 @@ + #include + + ENTRY (syscall) +- ABORT_TRANSACTION + mr r0,r3 + mr r3,r4 + mr r4,r5 +diff --git a/sysdeps/unix/sysv/linux/preadv2.c b/sysdeps/unix/sysv/linux/preadv2.c +index c8bf0764ef..bb08cbc5fd 100644 +--- a/sysdeps/unix/sysv/linux/preadv2.c ++++ b/sysdeps/unix/sysv/linux/preadv2.c +@@ -32,7 +32,7 @@ preadv2 (int fd, const struct iovec *vector, int count, off_t offset, + # ifdef __NR_preadv2 + ssize_t result = SYSCALL_CANCEL (preadv2, fd, vector, count, + LO_HI_LONG (offset), flags); +- if (result >= 0) ++ if (result >= 0 || errno != ENOSYS) + return result; + # endif + /* Trying to emulate the preadv2 syscall flags is troublesome: +diff --git a/sysdeps/unix/sysv/linux/preadv64v2.c b/sysdeps/unix/sysv/linux/preadv64v2.c +index d7400a0252..b72a047347 100644 +--- a/sysdeps/unix/sysv/linux/preadv64v2.c ++++ b/sysdeps/unix/sysv/linux/preadv64v2.c +@@ -30,7 +30,7 @@ preadv64v2 (int fd, const struct iovec *vector, int count, off64_t offset, + #ifdef __NR_preadv64v2 + ssize_t result = SYSCALL_CANCEL (preadv64v2, fd, vector, count, + LO_HI_LONG (offset), flags); +- if (result >= 0) ++ if (result >= 0 || errno != ENOSYS) + return result; + #endif + /* Trying to emulate the preadv2 syscall flags is troublesome: +diff --git a/sysdeps/unix/sysv/linux/pwritev2.c b/sysdeps/unix/sysv/linux/pwritev2.c +index 29c2264c8f..26333ebd43 100644 +--- a/sysdeps/unix/sysv/linux/pwritev2.c ++++ b/sysdeps/unix/sysv/linux/pwritev2.c +@@ -28,7 +28,7 @@ pwritev2 (int fd, const struct iovec *vector, int count, off_t offset, + # ifdef __NR_pwritev2 + ssize_t result = SYSCALL_CANCEL (pwritev2, fd, vector, count, + LO_HI_LONG (offset), flags); +- if (result >= 0) ++ if (result >= 0 || errno != ENOSYS) + return result; + # endif + /* Trying to emulate the pwritev2 syscall flags is troublesome: +diff --git a/sysdeps/unix/sysv/linux/pwritev64v2.c b/sysdeps/unix/sysv/linux/pwritev64v2.c +index 42da321149..17ea905aa6 100644 +--- a/sysdeps/unix/sysv/linux/pwritev64v2.c ++++ b/sysdeps/unix/sysv/linux/pwritev64v2.c +@@ -30,7 +30,7 @@ pwritev64v2 (int fd, const struct iovec *vector, int count, off64_t offset, + #ifdef __NR_pwritev64v2 + ssize_t result = SYSCALL_CANCEL (pwritev64v2, fd, vector, count, + LO_HI_LONG (offset), flags); +- if (result >= 0) ++ if (result >= 0 || errno != ENOSYS) + return result; + #endif + /* Trying to emulate the pwritev2 syscall flags is troublesome: +diff --git a/sysdeps/unix/sysv/linux/riscv/clone.S b/sysdeps/unix/sysv/linux/riscv/clone.S +index 392af72b55..1c5b12566e 100644 +--- a/sysdeps/unix/sysv/linux/riscv/clone.S ++++ b/sysdeps/unix/sysv/linux/riscv/clone.S +@@ -69,6 +69,11 @@ L (error): + + ENTRY (__thread_start) + L (thread_start): ++ /* Terminate call stack by noting ra is undefined. Use a dummy ++ .cfi_label to force starting the FDE. */ ++ .cfi_label .Ldummy ++ cfi_undefined (ra) ++ + /* Restore the arg for user's function. */ + REG_L a1,0(sp) /* Function pointer. */ + REG_L a0,SZREG(sp) /* Argument pointer. */ +diff --git a/sysdeps/unix/sysv/linux/riscv/flush-icache.c b/sysdeps/unix/sysv/linux/riscv/flush-icache.c +index d612ef4c6c..0b2042620b 100644 +--- a/sysdeps/unix/sysv/linux/riscv/flush-icache.c ++++ b/sysdeps/unix/sysv/linux/riscv/flush-icache.c +@@ -21,7 +21,11 @@ + #include + #include + #include +-#include ++#if __has_include__ () ++# include ++#else ++# include ++#endif + + typedef int (*func_type) (void *, void *, unsigned long int); + +diff --git a/sysdeps/unix/sysv/linux/riscv/kernel-features.h b/sysdeps/unix/sysv/linux/riscv/kernel-features.h +index 37f4d99a92..d21c824624 100644 +--- a/sysdeps/unix/sysv/linux/riscv/kernel-features.h ++++ b/sysdeps/unix/sysv/linux/riscv/kernel-features.h +@@ -21,3 +21,8 @@ + + #undef __ASSUME_CLONE_DEFAULT + #define __ASSUME_CLONE_BACKWARDS 1 ++ ++/* No support for PI mutexes or robust futexes before 4.20. */ ++#if __LINUX_KERNEL_VERSION < 0x041400 ++# undef __ASSUME_SET_ROBUST_LIST ++#endif +diff --git a/sysdeps/unix/sysv/linux/s390/force-elision.h b/sysdeps/unix/sysv/linux/s390/force-elision.h +index d8a1b9972f..71f32367dd 100644 +--- a/sysdeps/unix/sysv/linux/s390/force-elision.h ++++ b/sysdeps/unix/sysv/linux/s390/force-elision.h +@@ -18,9 +18,45 @@ + + /* Automatically enable elision for existing user lock kinds. */ + #define FORCE_ELISION(m, s) \ +- if (__pthread_force_elision \ +- && (m->__data.__kind & PTHREAD_MUTEX_ELISION_FLAGS_NP) == 0) \ ++ if (__pthread_force_elision) \ + { \ +- mutex->__data.__kind |= PTHREAD_MUTEX_ELISION_NP; \ +- s; \ ++ /* See concurrency notes regarding __kind in \ ++ struct __pthread_mutex_s in \ ++ sysdeps/nptl/bits/thread-shared-types.h. \ ++ \ ++ There are the following cases for the kind of a mutex \ ++ (The mask PTHREAD_MUTEX_ELISION_FLAGS_NP covers the flags \ ++ PTHREAD_MUTEX_ELISION_NP and PTHREAD_MUTEX_NO_ELISION_NP where \ ++ only one of both flags can be set): \ ++ - both flags are not set: \ ++ This is the first lock operation for this mutex. Enable \ ++ elision as it is not enabled so far. \ ++ Note: It can happen that multiple threads are calling e.g. \ ++ pthread_mutex_lock at the same time as the first lock \ ++ operation for this mutex. Then elision is enabled for this \ ++ mutex by multiple threads. Storing with relaxed MO is enough \ ++ as all threads will store the same new value for the kind of \ ++ the mutex. But we have to ensure that we always use the \ ++ elision path regardless if this thread has enabled elision or \ ++ another one. \ ++ \ ++ - PTHREAD_MUTEX_ELISION_NP flag is set: \ ++ Elision was already enabled for this mutex by a previous lock \ ++ operation. See case above. Just use the elision path. \ ++ \ ++ - PTHREAD_MUTEX_NO_ELISION_NP flag is set: \ ++ Elision was explicitly disabled by pthread_mutexattr_settype. \ ++ Do not use the elision path. \ ++ Note: The flag PTHREAD_MUTEX_NO_ELISION_NP will never be \ ++ changed after mutex initialization. */ \ ++ int mutex_kind = atomic_load_relaxed (&((m)->__data.__kind)); \ ++ if ((mutex_kind & PTHREAD_MUTEX_ELISION_FLAGS_NP) == 0) \ ++ { \ ++ mutex_kind |= PTHREAD_MUTEX_ELISION_NP; \ ++ atomic_store_relaxed (&((m)->__data.__kind), mutex_kind); \ ++ } \ ++ if ((mutex_kind & PTHREAD_MUTEX_ELISION_NP) != 0) \ ++ { \ ++ s; \ ++ } \ + } +diff --git a/sysdeps/unix/sysv/linux/sh/kernel_sigaction.h b/sysdeps/unix/sysv/linux/sh/kernel_sigaction.h +index 7ebcd08d62..c8dc77a02b 100644 +--- a/sysdeps/unix/sysv/linux/sh/kernel_sigaction.h ++++ b/sysdeps/unix/sysv/linux/sh/kernel_sigaction.h +@@ -1,8 +1,9 @@ + /* SH uses the generic Linux UAPI but defines SA_RESTORER. */ + #define SA_RESTORER 0x04000000 +-#include + + #define SET_SA_RESTORER(kact, act) \ + (kact)->sa_restorer = (act)->sa_restorer + #define RESET_SA_RESTORER(act, kact) \ + (act)->sa_restorer = (kact)->sa_restorer ++ ++#include +diff --git a/sysdeps/unix/sysv/linux/sparc/bits/siginfo-arch.h b/sysdeps/unix/sysv/linux/sparc/bits/siginfo-arch.h +index 9f79715ebe..4dd35237f6 100644 +--- a/sysdeps/unix/sysv/linux/sparc/bits/siginfo-arch.h ++++ b/sysdeps/unix/sysv/linux/sparc/bits/siginfo-arch.h +@@ -2,7 +2,12 @@ + #ifndef _BITS_SIGINFO_ARCH_H + #define _BITS_SIGINFO_ARCH_H 1 + +-#define __SI_BAND_TYPE int ++/* The kernel uses int instead of long int (as in POSIX). In 32-bit ++ mode, we can still use long int, but in 64-bit mode, we need to ++ deviate from POSIX. */ ++#if __WORDSIZE == 64 ++# define __SI_BAND_TYPE int ++#endif + + #define __SI_SIGFAULT_ADDL \ + int _si_trapno; +diff --git a/sysdeps/unix/sysv/linux/sparc/kernel_sigaction.h b/sysdeps/unix/sysv/linux/sparc/kernel_sigaction.h +index bee7e9cd03..eb4a522453 100644 +--- a/sysdeps/unix/sysv/linux/sparc/kernel_sigaction.h ++++ b/sysdeps/unix/sysv/linux/sparc/kernel_sigaction.h +@@ -1,10 +1,5 @@ + /* SPARC 'struct __new_sigaction' is similar to generic Linux UAPI with + a sa_restorer field, even though function is passed as an argument + to rt_sigaction syscall. */ +-#define SA_RESTORER 0x04000000 ++#define HAS_SA_RESTORER 1 + #include +- +-#define SET_SA_RESTORER(kact, act) \ +- (kact)->sa_restorer = NULL +-#define RESET_SA_RESTORER(act, kact) \ +- (act)->sa_restorer = (kact)->sa_restorer +diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/Makefile b/sysdeps/unix/sysv/linux/sparc/sparc64/Makefile +index 715af3df7b..218c246f16 100644 +--- a/sysdeps/unix/sysv/linux/sparc/sparc64/Makefile ++++ b/sysdeps/unix/sysv/linux/sparc/sparc64/Makefile +@@ -7,3 +7,8 @@ LD += -melf64_sparc + ifeq ($(subdir),stdlib) + sysdep_routines += __start_context + endif ++ ++ifeq ($(subdir),conform) ++# For bug 23821 (incorrect type of si_band). ++conformtest-xfail-conds += sparc64-linux ++endif +diff --git a/sysdeps/unix/sysv/linux/spawni.c b/sysdeps/unix/sysv/linux/spawni.c +index cf0213ece5..85239cedbf 100644 +--- a/sysdeps/unix/sysv/linux/spawni.c ++++ b/sysdeps/unix/sysv/linux/spawni.c +@@ -101,7 +101,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) +diff --git a/sysdeps/unix/sysv/linux/syscall-names.list b/sysdeps/unix/sysv/linux/syscall-names.list +index 5306d538e6..f88001c9c3 100644 +--- a/sysdeps/unix/sysv/linux/syscall-names.list ++++ b/sysdeps/unix/sysv/linux/syscall-names.list +@@ -22,8 +22,8 @@ + # names are only used if the installed kernel headers also provide + # them. + +-# The list of system calls is current as of Linux 4.17. +-kernel 4.17 ++# The list of system calls is current as of Linux 4.19. ++kernel 4.19 + + FAST_atomic_update + FAST_cmpxchg +@@ -186,6 +186,7 @@ inotify_rm_watch + io_cancel + io_destroy + io_getevents ++io_pgetevents + io_setup + io_submit + ioctl +@@ -431,6 +432,7 @@ renameat2 + request_key + restart_syscall + rmdir ++rseq + rt_sigaction + rt_sigpending + rt_sigprocmask +diff --git a/sysdeps/unix/sysv/linux/tst-readdir64-compat.c b/sysdeps/unix/sysv/linux/tst-readdir64-compat.c +new file mode 100644 +index 0000000000..cb78bc9be4 +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/tst-readdir64-compat.c +@@ -0,0 +1,115 @@ ++/* Test readdir64 compatibility symbol. ++ 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 ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* Copied from . */ ++struct __old_dirent64 ++ { ++ __ino_t d_ino; ++ __off64_t d_off; ++ unsigned short int d_reclen; ++ unsigned char d_type; ++ char d_name[256]; ++ }; ++ ++typedef struct __old_dirent64 *(*compat_readdir64_type) (DIR *); ++ ++#if TEST_COMPAT (libc, GLIBC_2_1, GLIBC_2_2) ++struct __old_dirent64 *compat_readdir64 (DIR *); ++compat_symbol_reference (libc, compat_readdir64, readdir64, GLIBC_2_1); ++#endif ++ ++static int ++do_test (void) ++{ ++#if TEST_COMPAT (libc, GLIBC_2_1, GLIBC_2_2) ++ ++ /* Directory stream using the non-compat readdir64 symbol. The test ++ checks against this. */ ++ DIR *dir_reference = opendir ("."); ++ TEST_VERIFY_EXIT (dir_reference != NULL); ++ DIR *dir_test = opendir ("."); ++ TEST_VERIFY_EXIT (dir_test != NULL); ++ ++ /* This loop assumes that the enumeration order is consistent for ++ two different handles. Nothing should write to the current ++ directory (in the source tree) while this test runs, so there ++ should not be any difference due to races. */ ++ size_t count = 0; ++ while (true) ++ { ++ errno = 0; ++ struct dirent64 *entry_reference = readdir64 (dir_reference); ++ if (entry_reference == NULL && errno != 0) ++ FAIL_EXIT1 ("readdir64 entry %zu: %m\n", count); ++ struct __old_dirent64 *entry_test = compat_readdir64 (dir_test); ++ if (entry_reference == NULL) ++ { ++ if (errno == EOVERFLOW) ++ { ++ TEST_VERIFY (entry_reference->d_ino ++ != (__ino_t) entry_reference->d_ino); ++ printf ("info: inode number overflow at entry %zu\n", count); ++ break; ++ } ++ if (errno != 0) ++ FAIL_EXIT1 ("compat readdir64 entry %zu: %m\n", count); ++ } ++ ++ /* Check that both streams end at the same time. */ ++ if (entry_reference == NULL) ++ { ++ TEST_VERIFY (entry_test == NULL); ++ break; ++ } ++ else ++ TEST_VERIFY_EXIT (entry_test != NULL); ++ ++ /* d_off is never zero because it is the offset of the next ++ entry (not the current entry). */ ++ TEST_VERIFY (entry_reference->d_off > 0); ++ ++ /* Check that the entries are the same. */ ++ TEST_COMPARE_BLOB (entry_reference->d_name, ++ strlen (entry_reference->d_name), ++ entry_test->d_name, strlen (entry_test->d_name)); ++ TEST_COMPARE (entry_reference->d_ino, entry_test->d_ino); ++ TEST_COMPARE (entry_reference->d_off, entry_test->d_off); ++ TEST_COMPARE (entry_reference->d_type, entry_test->d_type); ++ TEST_COMPARE (entry_reference->d_reclen, entry_test->d_reclen); ++ ++ ++count; ++ } ++ printf ("info: %zu directory entries found\n", count); ++ TEST_VERIFY (count >= 3); /* ".", "..", and some source files. */ ++ ++ TEST_COMPARE (closedir (dir_test), 0); ++ TEST_COMPARE (closedir (dir_reference), 0); ++#endif ++ return 0; ++} ++ ++#include +diff --git a/sysdeps/unix/sysv/linux/x86/force-elision.h b/sysdeps/unix/sysv/linux/x86/force-elision.h +index dd659c908f..61282d6678 100644 +--- a/sysdeps/unix/sysv/linux/x86/force-elision.h ++++ b/sysdeps/unix/sysv/linux/x86/force-elision.h +@@ -18,9 +18,45 @@ + + /* Automatically enable elision for existing user lock kinds. */ + #define FORCE_ELISION(m, s) \ +- if (__pthread_force_elision \ +- && (m->__data.__kind & PTHREAD_MUTEX_ELISION_FLAGS_NP) == 0) \ ++ if (__pthread_force_elision) \ + { \ +- mutex->__data.__kind |= PTHREAD_MUTEX_ELISION_NP; \ +- s; \ ++ /* See concurrency notes regarding __kind in \ ++ struct __pthread_mutex_s in \ ++ sysdeps/nptl/bits/thread-shared-types.h. \ ++ \ ++ There are the following cases for the kind of a mutex \ ++ (The mask PTHREAD_MUTEX_ELISION_FLAGS_NP covers the flags \ ++ PTHREAD_MUTEX_ELISION_NP and PTHREAD_MUTEX_NO_ELISION_NP where \ ++ only one of both flags can be set): \ ++ - both flags are not set: \ ++ This is the first lock operation for this mutex. Enable \ ++ elision as it is not enabled so far. \ ++ Note: It can happen that multiple threads are calling e.g. \ ++ pthread_mutex_lock at the same time as the first lock \ ++ operation for this mutex. Then elision is enabled for this \ ++ mutex by multiple threads. Storing with relaxed MO is enough \ ++ as all threads will store the same new value for the kind of \ ++ the mutex. But we have to ensure that we always use the \ ++ elision path regardless if this thread has enabled elision or \ ++ another one. \ ++ \ ++ - PTHREAD_MUTEX_ELISION_NP flag is set: \ ++ Elision was already enabled for this mutex by a previous lock \ ++ operation. See case above. Just use the elision path. \ ++ \ ++ - PTHREAD_MUTEX_NO_ELISION_NP flag is set: \ ++ Elision was explicitly disabled by pthread_mutexattr_settype. \ ++ Do not use the elision path. \ ++ Note: The flag PTHREAD_MUTEX_NO_ELISION_NP will never be \ ++ changed after mutex initialization. */ \ ++ int mutex_kind = atomic_load_relaxed (&((m)->__data.__kind)); \ ++ if ((mutex_kind & PTHREAD_MUTEX_ELISION_FLAGS_NP) == 0) \ ++ { \ ++ mutex_kind |= PTHREAD_MUTEX_ELISION_NP; \ ++ atomic_store_relaxed (&((m)->__data.__kind), mutex_kind); \ ++ } \ ++ if ((mutex_kind & PTHREAD_MUTEX_ELISION_NP) != 0) \ ++ { \ ++ s; \ ++ } \ + } +diff --git a/sysdeps/unix/sysv/linux/x86_64/sigaction.c b/sysdeps/unix/sysv/linux/x86_64/sigaction.c +index 4e6d9cc32e..9aa2c7f860 100644 +--- a/sysdeps/unix/sysv/linux/x86_64/sigaction.c ++++ b/sysdeps/unix/sysv/linux/x86_64/sigaction.c +@@ -18,7 +18,6 @@ + + #include + #define SA_RESTORER 0x04000000 +-#include + + extern void restore_rt (void) asm ("__restore_rt") attribute_hidden; + +@@ -29,6 +28,8 @@ extern void restore_rt (void) asm ("__restore_rt") attribute_hidden; + #define RESET_SA_RESTORER(act, kact) \ + (act)->sa_restorer = (kact)->sa_restorer + ++#include ++ + #include + + /* NOTE: Please think twice before making any changes to the bits of +diff --git a/sysdeps/x86/cpu-features.c b/sysdeps/x86/cpu-features.c +index ea0b64fdb9..4695ac80d4 100644 +--- a/sysdeps/x86/cpu-features.c ++++ b/sysdeps/x86/cpu-features.c +@@ -316,7 +316,13 @@ init_cpu_features (struct cpu_features *cpu_features) + | bit_arch_Fast_Unaligned_Copy + | bit_arch_Prefer_PMINUB_for_stringop); + break; ++ } + ++ /* Disable TSX on some Haswell processors to avoid TSX on kernels that ++ weren't updated with the latest microcode package (which disables ++ broken feature by default). */ ++ switch (model) ++ { + case 0x3f: + /* Xeon E7 v3 with stepping >= 4 has working TSX. */ + if (stepping >= 4) +diff --git a/sysdeps/x86/dl-prop.h b/sysdeps/x86/dl-prop.h +index 26c3131ac5..9ab890d12b 100644 +--- a/sysdeps/x86/dl-prop.h ++++ b/sysdeps/x86/dl-prop.h +@@ -49,6 +49,10 @@ _dl_process_cet_property_note (struct link_map *l, + const ElfW(Addr) align) + { + #if CET_ENABLED ++ /* Skip if we have seen a NT_GNU_PROPERTY_TYPE_0 note before. */ ++ if (l->l_cet != lc_unknown) ++ return; ++ + /* The NT_GNU_PROPERTY_TYPE_0 note must be aliged to 4 bytes in + 32-bit objects and to 8 bytes in 64-bit objects. Skip notes + with incorrect alignment. */ +@@ -57,6 +61,9 @@ _dl_process_cet_property_note (struct link_map *l, + + const ElfW(Addr) start = (ElfW(Addr)) note; + ++ unsigned int feature_1 = 0; ++ unsigned int last_type = 0; ++ + while ((ElfW(Addr)) (note + 1) - start < size) + { + /* Find the NT_GNU_PROPERTY_TYPE_0 note. */ +@@ -64,10 +71,18 @@ _dl_process_cet_property_note (struct link_map *l, + && note->n_type == NT_GNU_PROPERTY_TYPE_0 + && memcmp (note + 1, "GNU", 4) == 0) + { ++ /* Stop if we see more than one GNU property note which may ++ be generated by the older linker. */ ++ if (l->l_cet != lc_unknown) ++ return; ++ ++ /* Check CET status now. */ ++ l->l_cet = lc_none; ++ + /* Check for invalid property. */ + if (note->n_descsz < 8 + || (note->n_descsz % sizeof (ElfW(Addr))) != 0) +- break; ++ return; + + /* Start and end of property array. */ + unsigned char *ptr = (unsigned char *) (note + 1) + 4; +@@ -78,9 +93,15 @@ _dl_process_cet_property_note (struct link_map *l, + unsigned int type = *(unsigned int *) ptr; + unsigned int datasz = *(unsigned int *) (ptr + 4); + ++ /* Property type must be in ascending order. */ ++ if (type < last_type) ++ return; ++ + ptr += 8; + if ((ptr + datasz) > ptr_end) +- break; ++ return; ++ ++ last_type = type; + + if (type == GNU_PROPERTY_X86_FEATURE_1_AND) + { +@@ -89,14 +110,18 @@ _dl_process_cet_property_note (struct link_map *l, + we stop the search regardless if its size is correct + or not. There is no point to continue if this note + is ill-formed. */ +- if (datasz == 4) +- { +- unsigned int feature_1 = *(unsigned int *) ptr; +- if ((feature_1 & GNU_PROPERTY_X86_FEATURE_1_IBT)) +- l->l_cet |= lc_ibt; +- if ((feature_1 & GNU_PROPERTY_X86_FEATURE_1_SHSTK)) +- l->l_cet |= lc_shstk; +- } ++ if (datasz != 4) ++ return; ++ ++ feature_1 = *(unsigned int *) ptr; ++ ++ /* Keep searching for the next GNU property note ++ generated by the older linker. */ ++ break; ++ } ++ else if (type > GNU_PROPERTY_X86_FEATURE_1_AND) ++ { ++ /* Stop since property type is in ascending order. */ + return; + } + +@@ -112,6 +137,12 @@ _dl_process_cet_property_note (struct link_map *l, + + ELF_NOTE_NEXT_OFFSET (note->n_namesz, note->n_descsz, + align)); + } ++ ++ /* We get here only if there is one or no GNU property note. */ ++ if ((feature_1 & GNU_PROPERTY_X86_FEATURE_1_IBT)) ++ l->l_cet |= lc_ibt; ++ if ((feature_1 & GNU_PROPERTY_X86_FEATURE_1_SHSTK)) ++ l->l_cet |= lc_shstk; + #endif + } + +diff --git a/sysdeps/x86/link_map.h b/sysdeps/x86/link_map.h +index ef1206a9d2..9367ed0889 100644 +--- a/sysdeps/x86/link_map.h ++++ b/sysdeps/x86/link_map.h +@@ -19,8 +19,9 @@ + /* If this object is enabled with CET. */ + enum + { +- lc_none = 0, /* Not enabled with CET. */ +- lc_ibt = 1 << 0, /* Enabled with IBT. */ +- lc_shstk = 1 << 1, /* Enabled with STSHK. */ ++ lc_unknown = 0, /* Unknown CET status. */ ++ lc_none = 1 << 0, /* Not enabled with CET. */ ++ lc_ibt = 1 << 1, /* Enabled with IBT. */ ++ lc_shstk = 1 << 2, /* Enabled with STSHK. */ + lc_ibt_and_shstk = lc_ibt | lc_shstk /* Enabled with both. */ +- } l_cet:2; ++ } l_cet:3; +diff --git a/sysdeps/x86_64/dl-irel.h b/sysdeps/x86_64/dl-irel.h +index 6ecc50fb42..33f100d8b1 100644 +--- a/sysdeps/x86_64/dl-irel.h ++++ b/sysdeps/x86_64/dl-irel.h +@@ -45,7 +45,7 @@ elf_irela (const ElfW(Rela) *reloc) + *reloc_addr = value; + } + else +- __libc_fatal ("unexpected reloc type in static binary"); ++ __libc_fatal ("Unexpected reloc type in static binary.\n"); + } + + #endif /* dl-irel.h */ +diff --git a/sysdeps/x86_64/memchr.S b/sysdeps/x86_64/memchr.S +index feef5d4f24..cb320257a2 100644 +--- a/sysdeps/x86_64/memchr.S ++++ b/sysdeps/x86_64/memchr.S +@@ -34,12 +34,16 @@ ENTRY(MEMCHR) + mov %edi, %ecx + + #ifdef USE_AS_WMEMCHR +- test %rdx, %rdx ++ test %RDX_LP, %RDX_LP + jz L(return_null) +- shl $2, %rdx ++ shl $2, %RDX_LP + #else ++# ifdef __ILP32__ ++ /* Clear the upper 32 bits. */ ++ movl %edx, %edx ++# endif + punpcklbw %xmm1, %xmm1 +- test %rdx, %rdx ++ test %RDX_LP, %RDX_LP + jz L(return_null) + punpcklbw %xmm1, %xmm1 + #endif +diff --git a/sysdeps/x86_64/memcmp.S b/sysdeps/x86_64/memcmp.S +index bcb4a2e88d..45918d375a 100644 +--- a/sysdeps/x86_64/memcmp.S ++++ b/sysdeps/x86_64/memcmp.S +@@ -21,14 +21,18 @@ + + .text + ENTRY (memcmp) +- test %rdx, %rdx ++#ifdef __ILP32__ ++ /* Clear the upper 32 bits. */ ++ movl %edx, %edx ++#endif ++ test %RDX_LP, %RDX_LP + jz L(finz) + cmpq $1, %rdx +- jle L(finr1b) ++ jbe L(finr1b) + subq %rdi, %rsi + movq %rdx, %r10 + cmpq $32, %r10 +- jge L(gt32) ++ jae L(gt32) + /* Handle small chunks and last block of less than 32 bytes. */ + L(small): + testq $1, %r10 +@@ -156,7 +160,7 @@ L(A32): + movq %r11, %r10 + andq $-32, %r10 + cmpq %r10, %rdi +- jge L(mt16) ++ jae L(mt16) + /* Pre-unroll to be ready for unrolled 64B loop. */ + testq $32, %rdi + jz L(A64) +@@ -178,7 +182,7 @@ L(A64): + movq %r11, %r10 + andq $-64, %r10 + cmpq %r10, %rdi +- jge L(mt32) ++ jae L(mt32) + + L(A64main): + movdqu (%rdi,%rsi), %xmm0 +@@ -216,7 +220,7 @@ L(mt32): + movq %r11, %r10 + andq $-32, %r10 + cmpq %r10, %rdi +- jge L(mt16) ++ jae L(mt16) + + L(A32main): + movdqu (%rdi,%rsi), %xmm0 +@@ -254,7 +258,7 @@ L(ATR): + movq %r11, %r10 + andq $-32, %r10 + cmpq %r10, %rdi +- jge L(mt16) ++ jae L(mt16) + testq $16, %rdi + jz L(ATR32) + +@@ -325,7 +329,7 @@ L(ATR64main): + movq %r11, %r10 + andq $-32, %r10 + cmpq %r10, %rdi +- jge L(mt16) ++ jae L(mt16) + + L(ATR32res): + movdqa (%rdi,%rsi), %xmm0 +diff --git a/sysdeps/x86_64/memrchr.S b/sysdeps/x86_64/memrchr.S +index b8e3fa1d87..dc82f8f73d 100644 +--- a/sysdeps/x86_64/memrchr.S ++++ b/sysdeps/x86_64/memrchr.S +@@ -24,13 +24,13 @@ + ENTRY (__memrchr) + movd %esi, %xmm1 + +- sub $16, %rdx ++ sub $16, %RDX_LP + jbe L(length_less16) + + punpcklbw %xmm1, %xmm1 + punpcklbw %xmm1, %xmm1 + +- add %rdx, %rdi ++ add %RDX_LP, %RDI_LP + pshufd $0, %xmm1, %xmm1 + + movdqu (%rdi), %xmm0 +diff --git a/sysdeps/x86_64/multiarch/memchr-avx2.S b/sysdeps/x86_64/multiarch/memchr-avx2.S +index 5f5e772554..c81da19bf0 100644 +--- a/sysdeps/x86_64/multiarch/memchr-avx2.S ++++ b/sysdeps/x86_64/multiarch/memchr-avx2.S +@@ -40,16 +40,20 @@ + ENTRY (MEMCHR) + # ifndef USE_AS_RAWMEMCHR + /* Check for zero length. */ +- testq %rdx, %rdx ++ test %RDX_LP, %RDX_LP + jz L(null) + # endif + movl %edi, %ecx + /* Broadcast CHAR to YMM0. */ + vmovd %esi, %xmm0 + # ifdef USE_AS_WMEMCHR +- shl $2, %rdx ++ shl $2, %RDX_LP + vpbroadcastd %xmm0, %ymm0 + # else ++# ifdef __ILP32__ ++ /* Clear the upper 32 bits. */ ++ movl %edx, %edx ++# endif + vpbroadcastb %xmm0, %ymm0 + # endif + /* Check if we may cross page boundary with one vector load. */ +diff --git a/sysdeps/x86_64/multiarch/memcmp-avx2-movbe.S b/sysdeps/x86_64/multiarch/memcmp-avx2-movbe.S +index 30f764c393..e3a35b899e 100644 +--- a/sysdeps/x86_64/multiarch/memcmp-avx2-movbe.S ++++ b/sysdeps/x86_64/multiarch/memcmp-avx2-movbe.S +@@ -58,9 +58,12 @@ + .section .text.avx,"ax",@progbits + ENTRY (MEMCMP) + # ifdef USE_AS_WMEMCMP +- shl $2, %rdx ++ shl $2, %RDX_LP ++# elif defined __ILP32__ ++ /* Clear the upper 32 bits. */ ++ movl %edx, %edx + # endif +- cmpq $VEC_SIZE, %rdx ++ cmp $VEC_SIZE, %RDX_LP + jb L(less_vec) + + /* From VEC to 2 * VEC. No branch when size == VEC_SIZE. */ +diff --git a/sysdeps/x86_64/multiarch/memcmp-sse4.S b/sysdeps/x86_64/multiarch/memcmp-sse4.S +index 8e164f2cb6..302900f5b8 100644 +--- a/sysdeps/x86_64/multiarch/memcmp-sse4.S ++++ b/sysdeps/x86_64/multiarch/memcmp-sse4.S +@@ -42,13 +42,16 @@ + .section .text.sse4.1,"ax",@progbits + ENTRY (MEMCMP) + # ifdef USE_AS_WMEMCMP +- shl $2, %rdx ++ shl $2, %RDX_LP ++# elif defined __ILP32__ ++ /* Clear the upper 32 bits. */ ++ mov %edx, %edx + # endif + pxor %xmm0, %xmm0 +- cmp $79, %rdx ++ cmp $79, %RDX_LP + ja L(79bytesormore) + # ifndef USE_AS_WMEMCMP +- cmp $1, %rdx ++ cmp $1, %RDX_LP + je L(firstbyte) + # endif + add %rdx, %rsi +diff --git a/sysdeps/x86_64/multiarch/memcmp-ssse3.S b/sysdeps/x86_64/multiarch/memcmp-ssse3.S +index 6f76c64123..69d030fc00 100644 +--- a/sysdeps/x86_64/multiarch/memcmp-ssse3.S ++++ b/sysdeps/x86_64/multiarch/memcmp-ssse3.S +@@ -33,9 +33,12 @@ + atom_text_section + ENTRY (MEMCMP) + # ifdef USE_AS_WMEMCMP +- shl $2, %rdx +- test %rdx, %rdx ++ shl $2, %RDX_LP ++ test %RDX_LP, %RDX_LP + jz L(equal) ++# elif defined __ILP32__ ++ /* Clear the upper 32 bits. */ ++ mov %edx, %edx + # endif + mov %rdx, %rcx + mov %rdi, %rdx +diff --git a/sysdeps/x86_64/multiarch/memcpy-ssse3-back.S b/sysdeps/x86_64/multiarch/memcpy-ssse3-back.S +index 3cd1123326..568eebd3ae 100644 +--- a/sysdeps/x86_64/multiarch/memcpy-ssse3-back.S ++++ b/sysdeps/x86_64/multiarch/memcpy-ssse3-back.S +@@ -45,28 +45,33 @@ + .section .text.ssse3,"ax",@progbits + #if !defined USE_AS_MEMPCPY && !defined USE_AS_MEMMOVE + ENTRY (MEMPCPY_CHK) +- cmpq %rdx, %rcx ++ cmp %RDX_LP, %RCX_LP + jb HIDDEN_JUMPTARGET (__chk_fail) + END (MEMPCPY_CHK) + + ENTRY (MEMPCPY) +- movq %rdi, %rax +- addq %rdx, %rax ++ mov %RDI_LP, %RAX_LP ++ add %RDX_LP, %RAX_LP + jmp L(start) + END (MEMPCPY) + #endif + + #if !defined USE_AS_BCOPY + ENTRY (MEMCPY_CHK) +- cmpq %rdx, %rcx ++ cmp %RDX_LP, %RCX_LP + jb HIDDEN_JUMPTARGET (__chk_fail) + END (MEMCPY_CHK) + #endif + + ENTRY (MEMCPY) +- mov %rdi, %rax ++ mov %RDI_LP, %RAX_LP + #ifdef USE_AS_MEMPCPY +- add %rdx, %rax ++ add %RDX_LP, %RAX_LP ++#endif ++ ++#ifdef __ILP32__ ++ /* Clear the upper 32 bits. */ ++ mov %edx, %edx + #endif + + #ifdef USE_AS_MEMMOVE +diff --git a/sysdeps/x86_64/multiarch/memcpy-ssse3.S b/sysdeps/x86_64/multiarch/memcpy-ssse3.S +index 0240bfa309..0bd5ee999a 100644 +--- a/sysdeps/x86_64/multiarch/memcpy-ssse3.S ++++ b/sysdeps/x86_64/multiarch/memcpy-ssse3.S +@@ -45,28 +45,33 @@ + .section .text.ssse3,"ax",@progbits + #if !defined USE_AS_MEMPCPY && !defined USE_AS_MEMMOVE + ENTRY (MEMPCPY_CHK) +- cmpq %rdx, %rcx ++ cmp %RDX_LP, %RCX_LP + jb HIDDEN_JUMPTARGET (__chk_fail) + END (MEMPCPY_CHK) + + ENTRY (MEMPCPY) +- movq %rdi, %rax +- addq %rdx, %rax ++ mov %RDI_LP, %RAX_LP ++ add %RDX_LP, %RAX_LP + jmp L(start) + END (MEMPCPY) + #endif + + #if !defined USE_AS_BCOPY + ENTRY (MEMCPY_CHK) +- cmpq %rdx, %rcx ++ cmp %RDX_LP, %RCX_LP + jb HIDDEN_JUMPTARGET (__chk_fail) + END (MEMCPY_CHK) + #endif + + ENTRY (MEMCPY) +- mov %rdi, %rax ++ mov %RDI_LP, %RAX_LP + #ifdef USE_AS_MEMPCPY +- add %rdx, %rax ++ add %RDX_LP, %RAX_LP ++#endif ++ ++#ifdef __ILP32__ ++ /* Clear the upper 32 bits. */ ++ mov %edx, %edx + #endif + + #ifdef USE_AS_MEMMOVE +diff --git a/sysdeps/x86_64/multiarch/memmove-avx512-no-vzeroupper.S b/sysdeps/x86_64/multiarch/memmove-avx512-no-vzeroupper.S +index effc3ac2de..6ca2bbc91a 100644 +--- a/sysdeps/x86_64/multiarch/memmove-avx512-no-vzeroupper.S ++++ b/sysdeps/x86_64/multiarch/memmove-avx512-no-vzeroupper.S +@@ -24,27 +24,31 @@ + + .section .text.avx512,"ax",@progbits + ENTRY (__mempcpy_chk_avx512_no_vzeroupper) +- cmpq %rdx, %rcx ++ cmp %RDX_LP, %RCX_LP + jb HIDDEN_JUMPTARGET (__chk_fail) + END (__mempcpy_chk_avx512_no_vzeroupper) + + ENTRY (__mempcpy_avx512_no_vzeroupper) +- movq %rdi, %rax +- addq %rdx, %rax ++ mov %RDI_LP, %RAX_LP ++ add %RDX_LP, %RAX_LP + jmp L(start) + END (__mempcpy_avx512_no_vzeroupper) + + ENTRY (__memmove_chk_avx512_no_vzeroupper) +- cmpq %rdx, %rcx ++ cmp %RDX_LP, %RCX_LP + jb HIDDEN_JUMPTARGET (__chk_fail) + END (__memmove_chk_avx512_no_vzeroupper) + + ENTRY (__memmove_avx512_no_vzeroupper) +- mov %rdi, %rax ++ mov %RDI_LP, %RAX_LP + # ifdef USE_AS_MEMPCPY +- add %rdx, %rax ++ add %RDX_LP, %RAX_LP + # endif + L(start): ++# ifdef __ILP32__ ++ /* Clear the upper 32 bits. */ ++ mov %edx, %edx ++# endif + lea (%rsi, %rdx), %rcx + lea (%rdi, %rdx), %r9 + cmp $512, %rdx +diff --git a/sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S b/sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S +index e2ede45e9f..9bab1147d5 100644 +--- a/sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S ++++ b/sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S +@@ -106,20 +106,20 @@ + .section SECTION(.text),"ax",@progbits + #if defined SHARED && IS_IN (libc) + ENTRY (MEMMOVE_CHK_SYMBOL (__mempcpy_chk, unaligned)) +- cmpq %rdx, %rcx ++ cmp %RDX_LP, %RCX_LP + jb HIDDEN_JUMPTARGET (__chk_fail) + END (MEMMOVE_CHK_SYMBOL (__mempcpy_chk, unaligned)) + #endif + + ENTRY (MEMPCPY_SYMBOL (__mempcpy, unaligned)) +- movq %rdi, %rax +- addq %rdx, %rax ++ mov %RDI_LP, %RAX_LP ++ add %RDX_LP, %RAX_LP + jmp L(start) + END (MEMPCPY_SYMBOL (__mempcpy, unaligned)) + + #if defined SHARED && IS_IN (libc) + ENTRY (MEMMOVE_CHK_SYMBOL (__memmove_chk, unaligned)) +- cmpq %rdx, %rcx ++ cmp %RDX_LP, %RCX_LP + jb HIDDEN_JUMPTARGET (__chk_fail) + END (MEMMOVE_CHK_SYMBOL (__memmove_chk, unaligned)) + #endif +@@ -127,9 +127,13 @@ END (MEMMOVE_CHK_SYMBOL (__memmove_chk, unaligned)) + ENTRY (MEMMOVE_SYMBOL (__memmove, unaligned)) + movq %rdi, %rax + L(start): +- cmpq $VEC_SIZE, %rdx ++# ifdef __ILP32__ ++ /* Clear the upper 32 bits. */ ++ movl %edx, %edx ++# endif ++ cmp $VEC_SIZE, %RDX_LP + jb L(less_vec) +- cmpq $(VEC_SIZE * 2), %rdx ++ cmp $(VEC_SIZE * 2), %RDX_LP + ja L(more_2x_vec) + #if !defined USE_MULTIARCH || !IS_IN (libc) + L(last_2x_vec): +@@ -149,38 +153,38 @@ END (MEMMOVE_SYMBOL (__memmove, unaligned)) + + # if VEC_SIZE == 16 + ENTRY (__mempcpy_chk_erms) +- cmpq %rdx, %rcx ++ cmp %RDX_LP, %RCX_LP + jb HIDDEN_JUMPTARGET (__chk_fail) + END (__mempcpy_chk_erms) + + /* Only used to measure performance of REP MOVSB. */ + ENTRY (__mempcpy_erms) +- movq %rdi, %rax ++ mov %RDI_LP, %RAX_LP + /* Skip zero length. */ +- testq %rdx, %rdx ++ test %RDX_LP, %RDX_LP + jz 2f +- addq %rdx, %rax ++ add %RDX_LP, %RAX_LP + jmp L(start_movsb) + END (__mempcpy_erms) + + ENTRY (__memmove_chk_erms) +- cmpq %rdx, %rcx ++ cmp %RDX_LP, %RCX_LP + jb HIDDEN_JUMPTARGET (__chk_fail) + END (__memmove_chk_erms) + + ENTRY (__memmove_erms) + movq %rdi, %rax + /* Skip zero length. */ +- testq %rdx, %rdx ++ test %RDX_LP, %RDX_LP + jz 2f + L(start_movsb): +- movq %rdx, %rcx +- cmpq %rsi, %rdi ++ mov %RDX_LP, %RCX_LP ++ cmp %RSI_LP, %RDI_LP + jb 1f + /* Source == destination is less common. */ + je 2f +- leaq (%rsi,%rcx), %rdx +- cmpq %rdx, %rdi ++ lea (%rsi,%rcx), %RDX_LP ++ cmp %RDX_LP, %RDI_LP + jb L(movsb_backward) + 1: + rep movsb +@@ -200,20 +204,20 @@ strong_alias (__memmove_chk_erms, __memcpy_chk_erms) + + # ifdef SHARED + ENTRY (MEMMOVE_CHK_SYMBOL (__mempcpy_chk, unaligned_erms)) +- cmpq %rdx, %rcx ++ cmp %RDX_LP, %RCX_LP + jb HIDDEN_JUMPTARGET (__chk_fail) + END (MEMMOVE_CHK_SYMBOL (__mempcpy_chk, unaligned_erms)) + # endif + + ENTRY (MEMMOVE_SYMBOL (__mempcpy, unaligned_erms)) +- movq %rdi, %rax +- addq %rdx, %rax ++ mov %RDI_LP, %RAX_LP ++ add %RDX_LP, %RAX_LP + jmp L(start_erms) + END (MEMMOVE_SYMBOL (__mempcpy, unaligned_erms)) + + # ifdef SHARED + ENTRY (MEMMOVE_CHK_SYMBOL (__memmove_chk, unaligned_erms)) +- cmpq %rdx, %rcx ++ cmp %RDX_LP, %RCX_LP + jb HIDDEN_JUMPTARGET (__chk_fail) + END (MEMMOVE_CHK_SYMBOL (__memmove_chk, unaligned_erms)) + # endif +@@ -221,9 +225,13 @@ END (MEMMOVE_CHK_SYMBOL (__memmove_chk, unaligned_erms)) + ENTRY (MEMMOVE_SYMBOL (__memmove, unaligned_erms)) + movq %rdi, %rax + L(start_erms): +- cmpq $VEC_SIZE, %rdx ++# ifdef __ILP32__ ++ /* Clear the upper 32 bits. */ ++ movl %edx, %edx ++# endif ++ cmp $VEC_SIZE, %RDX_LP + jb L(less_vec) +- cmpq $(VEC_SIZE * 2), %rdx ++ cmp $(VEC_SIZE * 2), %RDX_LP + ja L(movsb_more_2x_vec) + L(last_2x_vec): + /* From VEC and to 2 * VEC. No branch when size == VEC_SIZE. */ +@@ -250,7 +258,7 @@ L(movsb): + # endif + jb L(more_8x_vec_backward) + 1: +- movq %rdx, %rcx ++ mov %RDX_LP, %RCX_LP + rep movsb + L(nop): + ret +diff --git a/sysdeps/x86_64/multiarch/memrchr-avx2.S b/sysdeps/x86_64/multiarch/memrchr-avx2.S +index b41a58bcba..ce488dd9e8 100644 +--- a/sysdeps/x86_64/multiarch/memrchr-avx2.S ++++ b/sysdeps/x86_64/multiarch/memrchr-avx2.S +@@ -32,10 +32,10 @@ ENTRY (__memrchr_avx2) + vmovd %esi, %xmm0 + vpbroadcastb %xmm0, %ymm0 + +- subq $VEC_SIZE, %rdx ++ sub $VEC_SIZE, %RDX_LP + jbe L(last_vec_or_less) + +- addq %rdx, %rdi ++ add %RDX_LP, %RDI_LP + + /* Check the last VEC_SIZE bytes. */ + vpcmpeqb (%rdi), %ymm0, %ymm1 +diff --git a/sysdeps/x86_64/multiarch/memset-avx512-no-vzeroupper.S b/sysdeps/x86_64/multiarch/memset-avx512-no-vzeroupper.S +index 689cc1199c..99e255195a 100644 +--- a/sysdeps/x86_64/multiarch/memset-avx512-no-vzeroupper.S ++++ b/sysdeps/x86_64/multiarch/memset-avx512-no-vzeroupper.S +@@ -29,12 +29,16 @@ + .section .text.avx512,"ax",@progbits + #if defined PIC + ENTRY (MEMSET_CHK) +- cmpq %rdx, %rcx ++ cmp %RDX_LP, %RCX_LP + jb HIDDEN_JUMPTARGET (__chk_fail) + END (MEMSET_CHK) + #endif + + ENTRY (MEMSET) ++# ifdef __ILP32__ ++ /* Clear the upper 32 bits. */ ++ mov %edx, %edx ++# endif + vpxor %xmm0, %xmm0, %xmm0 + vmovd %esi, %xmm1 + lea (%rdi, %rdx), %rsi +diff --git a/sysdeps/x86_64/multiarch/memset-vec-unaligned-erms.S b/sysdeps/x86_64/multiarch/memset-vec-unaligned-erms.S +index dc9cb88b37..a44f1bc3b2 100644 +--- a/sysdeps/x86_64/multiarch/memset-vec-unaligned-erms.S ++++ b/sysdeps/x86_64/multiarch/memset-vec-unaligned-erms.S +@@ -75,8 +75,8 @@ + .section SECTION(.text),"ax",@progbits + #if VEC_SIZE == 16 && IS_IN (libc) + ENTRY (__bzero) +- movq %rdi, %rax /* Set return value. */ +- movq %rsi, %rdx /* Set n. */ ++ mov %RDI_LP, %RAX_LP /* Set return value. */ ++ mov %RSI_LP, %RDX_LP /* Set n. */ + pxor %xmm0, %xmm0 + jmp L(entry_from_bzero) + END (__bzero) +@@ -86,13 +86,13 @@ weak_alias (__bzero, bzero) + #if IS_IN (libc) + # if defined SHARED + ENTRY_CHK (WMEMSET_CHK_SYMBOL (__wmemset_chk, unaligned)) +- cmpq %rdx, %rcx ++ cmp %RDX_LP, %RCX_LP + jb HIDDEN_JUMPTARGET (__chk_fail) + END_CHK (WMEMSET_CHK_SYMBOL (__wmemset_chk, unaligned)) + # endif + + ENTRY (WMEMSET_SYMBOL (__wmemset, unaligned)) +- shlq $2, %rdx ++ shl $2, %RDX_LP + WMEMSET_VDUP_TO_VEC0_AND_SET_RETURN (%esi, %rdi) + jmp L(entry_from_bzero) + END (WMEMSET_SYMBOL (__wmemset, unaligned)) +@@ -100,13 +100,17 @@ END (WMEMSET_SYMBOL (__wmemset, unaligned)) + + #if defined SHARED && IS_IN (libc) + ENTRY_CHK (MEMSET_CHK_SYMBOL (__memset_chk, unaligned)) +- cmpq %rdx, %rcx ++ cmp %RDX_LP, %RCX_LP + jb HIDDEN_JUMPTARGET (__chk_fail) + END_CHK (MEMSET_CHK_SYMBOL (__memset_chk, unaligned)) + #endif + + ENTRY (MEMSET_SYMBOL (__memset, unaligned)) + MEMSET_VDUP_TO_VEC0_AND_SET_RETURN (%esi, %rdi) ++# ifdef __ILP32__ ++ /* Clear the upper 32 bits. */ ++ mov %edx, %edx ++# endif + L(entry_from_bzero): + cmpq $VEC_SIZE, %rdx + jb L(less_vec) +@@ -122,14 +126,14 @@ END (MEMSET_SYMBOL (__memset, unaligned)) + + # if VEC_SIZE == 16 + ENTRY (__memset_chk_erms) +- cmpq %rdx, %rcx ++ cmp %RDX_LP, %RCX_LP + jb HIDDEN_JUMPTARGET (__chk_fail) + END (__memset_chk_erms) + + /* Only used to measure performance of REP STOSB. */ + ENTRY (__memset_erms) + /* Skip zero length. */ +- testq %rdx, %rdx ++ test %RDX_LP, %RDX_LP + jnz L(stosb) + movq %rdi, %rax + ret +@@ -141,11 +145,11 @@ ENTRY (MEMSET_SYMBOL (__memset, erms)) + L(stosb): + /* Issue vzeroupper before rep stosb. */ + VZEROUPPER +- movq %rdx, %rcx ++ mov %RDX_LP, %RCX_LP + movzbl %sil, %eax +- movq %rdi, %rdx ++ mov %RDI_LP, %RDX_LP + rep stosb +- movq %rdx, %rax ++ mov %RDX_LP, %RAX_LP + ret + # if VEC_SIZE == 16 + END (__memset_erms) +@@ -155,16 +159,20 @@ END (MEMSET_SYMBOL (__memset, erms)) + + # if defined SHARED && IS_IN (libc) + ENTRY_CHK (MEMSET_CHK_SYMBOL (__memset_chk, unaligned_erms)) +- cmpq %rdx, %rcx ++ cmp %RDX_LP, %RCX_LP + jb HIDDEN_JUMPTARGET (__chk_fail) + END_CHK (MEMSET_CHK_SYMBOL (__memset_chk, unaligned_erms)) + # endif + + ENTRY (MEMSET_SYMBOL (__memset, unaligned_erms)) + MEMSET_VDUP_TO_VEC0_AND_SET_RETURN (%esi, %rdi) +- cmpq $VEC_SIZE, %rdx ++# ifdef __ILP32__ ++ /* Clear the upper 32 bits. */ ++ mov %edx, %edx ++# endif ++ cmp $VEC_SIZE, %RDX_LP + jb L(less_vec) +- cmpq $(VEC_SIZE * 2), %rdx ++ cmp $(VEC_SIZE * 2), %RDX_LP + ja L(stosb_more_2x_vec) + /* From VEC and to 2 * VEC. No branch when size == VEC_SIZE. */ + VMOVU %VEC(0), -VEC_SIZE(%rdi,%rdx) +diff --git a/sysdeps/x86_64/multiarch/strcmp-avx2.S b/sysdeps/x86_64/multiarch/strcmp-avx2.S +index e8397f3b05..78fc116877 100644 +--- a/sysdeps/x86_64/multiarch/strcmp-avx2.S ++++ b/sysdeps/x86_64/multiarch/strcmp-avx2.S +@@ -79,15 +79,15 @@ + ENTRY (STRCMP) + # ifdef USE_AS_STRNCMP + /* Check for simple cases (0 or 1) in offset. */ +- cmp $1, %rdx ++ cmp $1, %RDX_LP + je L(char0) + jb L(zero) + # ifdef USE_AS_WCSCMP + /* Convert units: from wide to byte char. */ +- shl $2, %rdx ++ shl $2, %RDX_LP + # endif + /* Register %r11 tracks the maximum offset. */ +- movq %rdx, %r11 ++ mov %RDX_LP, %R11_LP + # endif + movl %edi, %eax + xorl %edx, %edx +diff --git a/sysdeps/x86_64/multiarch/strcmp-sse42.S b/sysdeps/x86_64/multiarch/strcmp-sse42.S +index d3c07bd292..a1ebea46fe 100644 +--- a/sysdeps/x86_64/multiarch/strcmp-sse42.S ++++ b/sysdeps/x86_64/multiarch/strcmp-sse42.S +@@ -156,11 +156,11 @@ STRCMP_SSE42: + #endif + + #if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L +- test %rdx, %rdx ++ test %RDX_LP, %RDX_LP + je LABEL(strcmp_exitz) +- cmp $1, %rdx ++ cmp $1, %RDX_LP + je LABEL(Byte0) +- mov %rdx, %r11 ++ mov %RDX_LP, %R11_LP + #endif + mov %esi, %ecx + mov %edi, %eax +diff --git a/sysdeps/x86_64/multiarch/strcpy-sse2-unaligned.S b/sysdeps/x86_64/multiarch/strcpy-sse2-unaligned.S +index 72bf7e8586..50aca22d2e 100644 +--- a/sysdeps/x86_64/multiarch/strcpy-sse2-unaligned.S ++++ b/sysdeps/x86_64/multiarch/strcpy-sse2-unaligned.S +@@ -40,8 +40,8 @@ + .text + ENTRY (STRCPY) + # ifdef USE_AS_STRNCPY +- mov %rdx, %r8 +- test %r8, %r8 ++ mov %RDX_LP, %R8_LP ++ test %R8_LP, %R8_LP + jz L(ExitZero) + # endif + mov %rsi, %rcx +diff --git a/sysdeps/x86_64/multiarch/strcpy-ssse3.S b/sysdeps/x86_64/multiarch/strcpy-ssse3.S +index 9858d0c4d5..0a62814a06 100644 +--- a/sysdeps/x86_64/multiarch/strcpy-ssse3.S ++++ b/sysdeps/x86_64/multiarch/strcpy-ssse3.S +@@ -31,13 +31,13 @@ ENTRY (STRCPY) + + mov %rsi, %rcx + # ifdef USE_AS_STRNCPY +- mov %rdx, %r8 ++ mov %RDX_LP, %R8_LP + # endif + mov %rdi, %rdx + # ifdef USE_AS_STRNCPY +- test %r8, %r8 ++ test %R8_LP, %R8_LP + jz L(Exit0) +- cmp $8, %r8 ++ cmp $8, %R8_LP + jbe L(StrncpyExit8Bytes) + # endif + cmpb $0, (%rcx) +diff --git a/sysdeps/x86_64/multiarch/strlen-avx2.S b/sysdeps/x86_64/multiarch/strlen-avx2.S +index fb2418cddc..645e04461f 100644 +--- a/sysdeps/x86_64/multiarch/strlen-avx2.S ++++ b/sysdeps/x86_64/multiarch/strlen-avx2.S +@@ -42,12 +42,15 @@ + ENTRY (STRLEN) + # ifdef USE_AS_STRNLEN + /* Check for zero length. */ +- testq %rsi, %rsi ++ test %RSI_LP, %RSI_LP + jz L(zero) + # ifdef USE_AS_WCSLEN +- shl $2, %rsi ++ shl $2, %RSI_LP ++# elif defined __ILP32__ ++ /* Clear the upper 32 bits. */ ++ movl %esi, %esi + # endif +- movq %rsi, %r8 ++ mov %RSI_LP, %R8_LP + # endif + movl %edi, %ecx + movq %rdi, %rdx +diff --git a/sysdeps/x86_64/strcmp.S b/sysdeps/x86_64/strcmp.S +index e16945b961..f47c8ad45c 100644 +--- a/sysdeps/x86_64/strcmp.S ++++ b/sysdeps/x86_64/strcmp.S +@@ -135,11 +135,11 @@ ENTRY (STRCMP) + * This implementation uses SSE to compare up to 16 bytes at a time. + */ + #if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L +- test %rdx, %rdx ++ test %RDX_LP, %RDX_LP + je LABEL(strcmp_exitz) +- cmp $1, %rdx ++ cmp $1, %RDX_LP + je LABEL(Byte0) +- mov %rdx, %r11 ++ mov %RDX_LP, %R11_LP + #endif + mov %esi, %ecx + mov %edi, %eax +diff --git a/sysdeps/x86_64/strlen.S b/sysdeps/x86_64/strlen.S +index 01cb5fa846..f845f3d46e 100644 +--- a/sysdeps/x86_64/strlen.S ++++ b/sysdeps/x86_64/strlen.S +@@ -59,21 +59,21 @@ ENTRY(strlen) + + #ifdef AS_STRNLEN + /* Do not read anything when n==0. */ +- test %rsi, %rsi ++ test %RSI_LP, %RSI_LP + jne L(n_nonzero) + xor %rax, %rax + ret + L(n_nonzero): + # ifdef AS_WCSLEN +- shlq $2, %rsi ++ shl $2, %RSI_LP + # endif + + /* Initialize long lived registers. */ + +- add %rdi, %rsi +- mov %rsi, %r10 +- and $-64, %r10 +- mov %rsi, %r11 ++ add %RDI_LP, %RSI_LP ++ mov %RSI_LP, %R10_LP ++ and $-64, %R10_LP ++ mov %RSI_LP, %R11_LP + #endif + + pxor %xmm0, %xmm0 +diff --git a/sysdeps/x86_64/x32/Makefile b/sysdeps/x86_64/x32/Makefile +index f2ebc24fb0..8748956563 100644 +--- a/sysdeps/x86_64/x32/Makefile ++++ b/sysdeps/x86_64/x32/Makefile +@@ -4,3 +4,15 @@ ifeq ($(subdir),math) + # 64-bit llround. Add -fno-builtin-lround to silence the compiler. + CFLAGS-s_llround.c += -fno-builtin-lround + endif ++ ++ifeq ($(subdir),string) ++tests += tst-size_t-memchr tst-size_t-memcmp tst-size_t-memcpy \ ++ tst-size_t-memrchr tst-size_t-memset tst-size_t-strncasecmp \ ++ tst-size_t-strncmp tst-size_t-strncpy tst-size_t-strnlen \ ++ tst-size_t-memcmp-2 ++endif ++ ++ifeq ($(subdir),wcsmbs) ++tests += tst-size_t-wmemchr tst-size_t-wmemcmp tst-size_t-wmemset \ ++ tst-size_t-wcsncmp tst-size_t-wcsnlen ++endif +diff --git a/sysdeps/x86_64/x32/test-size_t.h b/sysdeps/x86_64/x32/test-size_t.h +new file mode 100644 +index 0000000000..78a940863e +--- /dev/null ++++ b/sysdeps/x86_64/x32/test-size_t.h +@@ -0,0 +1,35 @@ ++/* Test string/memory functions with size_t in the lower 32 bits of ++ 64-bit register. ++ Copyright (C) 2019 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 ++ . */ ++ ++#define TEST_MAIN ++#include ++ ++/* On x32, parameter_t may be passed in a 64-bit register with the LEN ++ field in the lower 32 bits. When the LEN field of 64-bit register ++ is passed to string/memory function as the size_t parameter, only ++ the lower 32 bits can be used. */ ++typedef struct ++{ ++ union ++ { ++ size_t len; ++ void (*fn) (void); ++ }; ++ void *p; ++} parameter_t; +diff --git a/sysdeps/x86_64/x32/tst-size_t-memchr.c b/sysdeps/x86_64/x32/tst-size_t-memchr.c +new file mode 100644 +index 0000000000..29a3daf102 +--- /dev/null ++++ b/sysdeps/x86_64/x32/tst-size_t-memchr.c +@@ -0,0 +1,72 @@ ++/* Test memchr with size_t in the lower 32 bits of 64-bit register. ++ Copyright (C) 2019 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 ++ . */ ++ ++#ifndef WIDE ++# define TEST_NAME "memchr" ++#else ++# define TEST_NAME "wmemchr" ++#endif /* WIDE */ ++#include "test-size_t.h" ++ ++#ifndef WIDE ++# define MEMCHR memchr ++# define CHAR char ++# define UCHAR unsigned char ++#else ++# include ++# define MEMCHR wmemchr ++# define CHAR wchar_t ++# define UCHAR wchar_t ++#endif /* WIDE */ ++ ++IMPL (MEMCHR, 1) ++ ++typedef CHAR * (*proto_t) (const CHAR*, int, size_t); ++ ++static CHAR * ++__attribute__ ((noinline, noclone)) ++do_memchr (parameter_t a, parameter_t b) ++{ ++ return CALL (&b, a.p, (uintptr_t) b.p, a.len); ++} ++ ++static int ++test_main (void) ++{ ++ test_init (); ++ ++ parameter_t src = { { page_size / sizeof (CHAR) }, buf2 }; ++ parameter_t c = { { 0 }, (void *) (uintptr_t) 0x12 }; ++ ++ int ret = 0; ++ FOR_EACH_IMPL (impl, 0) ++ { ++ c.fn = impl->fn; ++ CHAR *res = do_memchr (src, c); ++ if (res) ++ { ++ error (0, 0, "Wrong result in function %s: %p != NULL", ++ impl->name, res); ++ ret = 1; ++ } ++ } ++ ++ return ret ? EXIT_FAILURE : EXIT_SUCCESS; ++} ++ ++#include +diff --git a/sysdeps/x86_64/x32/tst-size_t-memcmp-2.c b/sysdeps/x86_64/x32/tst-size_t-memcmp-2.c +new file mode 100644 +index 0000000000..d8ae1a0813 +--- /dev/null ++++ b/sysdeps/x86_64/x32/tst-size_t-memcmp-2.c +@@ -0,0 +1,79 @@ ++/* Test memcmp with size_t in the lower 32 bits of 64-bit register. ++ Copyright (C) 2019 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 ++ . */ ++ ++#define TEST_MAIN ++#ifdef WIDE ++# define TEST_NAME "wmemcmp" ++#else ++# define TEST_NAME "memcmp" ++#endif ++ ++#include "test-size_t.h" ++ ++#ifdef WIDE ++# include ++# include ++ ++# define MEMCMP wmemcmp ++# define CHAR wchar_t ++#else ++# define MEMCMP memcmp ++# define CHAR char ++#endif ++ ++IMPL (MEMCMP, 1) ++ ++typedef int (*proto_t) (const CHAR *, const CHAR *, size_t); ++ ++static int ++__attribute__ ((noinline, noclone)) ++do_memcmp (parameter_t a, parameter_t b) ++{ ++ return CALL (&b, a.p, b.p, a.len); ++} ++ ++static int ++test_main (void) ++{ ++ test_init (); ++ ++ parameter_t dest = { { page_size / sizeof (CHAR) }, buf1 }; ++ parameter_t src = { { 0 }, buf2 }; ++ ++ memcpy (buf1, buf2, page_size); ++ ++ CHAR *p = (CHAR *) buf1; ++ p[page_size / sizeof (CHAR) - 1] = (CHAR) 1; ++ ++ int ret = 0; ++ FOR_EACH_IMPL (impl, 0) ++ { ++ src.fn = impl->fn; ++ int res = do_memcmp (dest, src); ++ if (res >= 0) ++ { ++ error (0, 0, "Wrong result in function %s: %i >= 0", ++ impl->name, res); ++ ret = 1; ++ } ++ } ++ ++ return ret ? EXIT_FAILURE : EXIT_SUCCESS; ++} ++ ++#include +diff --git a/sysdeps/x86_64/x32/tst-size_t-memcmp.c b/sysdeps/x86_64/x32/tst-size_t-memcmp.c +new file mode 100644 +index 0000000000..9bd6fdb45a +--- /dev/null ++++ b/sysdeps/x86_64/x32/tst-size_t-memcmp.c +@@ -0,0 +1,76 @@ ++/* Test memcmp with size_t in the lower 32 bits of 64-bit register. ++ Copyright (C) 2019 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 ++ . */ ++ ++#define TEST_MAIN ++#ifdef WIDE ++# define TEST_NAME "wmemcmp" ++#else ++# define TEST_NAME "memcmp" ++#endif ++ ++#include "test-size_t.h" ++ ++#ifdef WIDE ++# include ++# include ++ ++# define MEMCMP wmemcmp ++# define CHAR wchar_t ++#else ++# define MEMCMP memcmp ++# define CHAR char ++#endif ++ ++IMPL (MEMCMP, 1) ++ ++typedef int (*proto_t) (const CHAR *, const CHAR *, size_t); ++ ++static int ++__attribute__ ((noinline, noclone)) ++do_memcmp (parameter_t a, parameter_t b) ++{ ++ return CALL (&b, a.p, b.p, a.len); ++} ++ ++static int ++test_main (void) ++{ ++ test_init (); ++ ++ parameter_t dest = { { page_size / sizeof (CHAR) }, buf1 }; ++ parameter_t src = { { 0 }, buf2 }; ++ ++ memcpy (buf1, buf2, page_size); ++ ++ int ret = 0; ++ FOR_EACH_IMPL (impl, 0) ++ { ++ src.fn = impl->fn; ++ int res = do_memcmp (dest, src); ++ if (res) ++ { ++ error (0, 0, "Wrong result in function %s: %i != 0", ++ impl->name, res); ++ ret = 1; ++ } ++ } ++ ++ return ret ? EXIT_FAILURE : EXIT_SUCCESS; ++} ++ ++#include +diff --git a/sysdeps/x86_64/x32/tst-size_t-memcpy.c b/sysdeps/x86_64/x32/tst-size_t-memcpy.c +new file mode 100644 +index 0000000000..66b71e1749 +--- /dev/null ++++ b/sysdeps/x86_64/x32/tst-size_t-memcpy.c +@@ -0,0 +1,58 @@ ++/* Test memcpy with size_t in the lower 32 bits of 64-bit register. ++ Copyright (C) 2019 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 ++ . */ ++ ++#define TEST_NAME "memcpy" ++#include "test-size_t.h" ++ ++IMPL (memcpy, 1) ++ ++typedef void *(*proto_t) (void *, const void *, size_t); ++ ++static void * ++__attribute__ ((noinline, noclone)) ++do_memcpy (parameter_t a, parameter_t b) ++{ ++ return CALL (&b, a.p, b.p, a.len); ++} ++ ++static int ++test_main (void) ++{ ++ test_init (); ++ ++ parameter_t dest = { { page_size }, buf1 }; ++ parameter_t src = { { 0 }, buf2 }; ++ ++ int ret = 0; ++ FOR_EACH_IMPL (impl, 0) ++ { ++ src.fn = impl->fn; ++ do_memcpy (dest, src); ++ int res = memcmp (dest.p, src.p, dest.len); ++ if (res) ++ { ++ error (0, 0, "Wrong result in function %s: %i != 0", ++ impl->name, res); ++ ret = 1; ++ } ++ } ++ ++ return ret ? EXIT_FAILURE : EXIT_SUCCESS; ++} ++ ++#include +diff --git a/sysdeps/x86_64/x32/tst-size_t-memrchr.c b/sysdeps/x86_64/x32/tst-size_t-memrchr.c +new file mode 100644 +index 0000000000..c83699c097 +--- /dev/null ++++ b/sysdeps/x86_64/x32/tst-size_t-memrchr.c +@@ -0,0 +1,57 @@ ++/* Test memrchr with size_t in the lower 32 bits of 64-bit register. ++ Copyright (C) 2019 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 ++ . */ ++ ++#define TEST_NAME "memrchr" ++#include "test-size_t.h" ++ ++IMPL (memchr, 1) ++ ++typedef void * (*proto_t) (const void *, int, size_t); ++ ++static void * ++__attribute__ ((noinline, noclone)) ++do_memrchr (parameter_t a, parameter_t b) ++{ ++ return CALL (&b, a.p, (uintptr_t) b.p, a.len); ++} ++ ++static int ++test_main (void) ++{ ++ test_init (); ++ ++ parameter_t src = { { page_size }, buf2 }; ++ parameter_t c = { { 0 }, (void *) (uintptr_t) 0x12 }; ++ ++ int ret = 0; ++ FOR_EACH_IMPL (impl, 0) ++ { ++ c.fn = impl->fn; ++ void * res = do_memrchr (src, c); ++ if (res) ++ { ++ error (0, 0, "Wrong result in function %s: %p != NULL", ++ impl->name, res); ++ ret = 1; ++ } ++ } ++ ++ return ret ? EXIT_FAILURE : EXIT_SUCCESS; ++} ++ ++#include +diff --git a/sysdeps/x86_64/x32/tst-size_t-memset.c b/sysdeps/x86_64/x32/tst-size_t-memset.c +new file mode 100644 +index 0000000000..2c367af6cd +--- /dev/null ++++ b/sysdeps/x86_64/x32/tst-size_t-memset.c +@@ -0,0 +1,73 @@ ++/* Test memset with size_t in the lower 32 bits of 64-bit register. ++ Copyright (C) 2019 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 ++ . */ ++ ++#ifdef WIDE ++# define TEST_NAME "wmemset" ++#else ++# define TEST_NAME "memset" ++#endif /* WIDE */ ++ ++#include "test-size_t.h" ++ ++#ifdef WIDE ++# include ++# define MEMSET wmemset ++# define CHAR wchar_t ++#else ++# define MEMSET memset ++# define CHAR char ++#endif /* WIDE */ ++ ++IMPL (MEMSET, 1) ++ ++typedef CHAR *(*proto_t) (CHAR *, int, size_t); ++ ++static void * ++__attribute__ ((noinline, noclone)) ++do_memset (parameter_t a, parameter_t b) ++{ ++ return CALL (&b, a.p, (uintptr_t) b.p, a.len); ++} ++ ++static int ++test_main (void) ++{ ++ test_init (); ++ ++ CHAR ch = 0x23; ++ parameter_t src = { { page_size / sizeof (CHAR) }, buf2 }; ++ parameter_t c = { { 0 }, (void *) (uintptr_t) ch }; ++ ++ int ret = 0; ++ FOR_EACH_IMPL (impl, 0) ++ { ++ c.fn = impl->fn; ++ CHAR *p = (CHAR *) do_memset (src, c); ++ size_t i; ++ for (i = 0; i < src.len; i++) ++ if (p[i] != ch) ++ { ++ error (0, 0, "Wrong result in function %s", impl->name); ++ ret = 1; ++ } ++ } ++ ++ return ret ? EXIT_FAILURE : EXIT_SUCCESS; ++} ++ ++#include +diff --git a/sysdeps/x86_64/x32/tst-size_t-strncasecmp.c b/sysdeps/x86_64/x32/tst-size_t-strncasecmp.c +new file mode 100644 +index 0000000000..862335937b +--- /dev/null ++++ b/sysdeps/x86_64/x32/tst-size_t-strncasecmp.c +@@ -0,0 +1,59 @@ ++/* Test strncaecmp with size_t in the lower 32 bits of 64-bit register. ++ Copyright (C) 2019 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 ++ . */ ++ ++#define TEST_NAME "strncasecmp" ++#include "test-size_t.h" ++ ++IMPL (strncasecmp, 1) ++ ++typedef int (*proto_t) (const char *, const char *, size_t); ++ ++static int ++__attribute__ ((noinline, noclone)) ++do_strncasecmp (parameter_t a, parameter_t b) ++{ ++ return CALL (&b, a.p, b.p, a.len); ++} ++ ++static int ++test_main (void) ++{ ++ test_init (); ++ ++ parameter_t dest = { { page_size }, buf1 }; ++ parameter_t src = { { 0 }, buf2 }; ++ ++ strncpy ((char *) buf1, (const char *) buf2, page_size); ++ ++ int ret = 0; ++ FOR_EACH_IMPL (impl, 0) ++ { ++ src.fn = impl->fn; ++ int res = do_strncasecmp (dest, src); ++ if (res) ++ { ++ error (0, 0, "Wrong result in function %s: %i != 0", ++ impl->name, res); ++ ret = 1; ++ } ++ } ++ ++ return ret ? EXIT_FAILURE : EXIT_SUCCESS; ++} ++ ++#include +diff --git a/sysdeps/x86_64/x32/tst-size_t-strncmp.c b/sysdeps/x86_64/x32/tst-size_t-strncmp.c +new file mode 100644 +index 0000000000..54e6bd83ef +--- /dev/null ++++ b/sysdeps/x86_64/x32/tst-size_t-strncmp.c +@@ -0,0 +1,78 @@ ++/* Test strncmp with size_t in the lower 32 bits of 64-bit register. ++ Copyright (C) 2019 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 ++ . */ ++ ++#ifdef WIDE ++# define TEST_NAME "wcsncmp" ++#else ++# define TEST_NAME "strncmp" ++#endif ++ ++#include "test-size_t.h" ++ ++#ifdef WIDE ++# include ++ ++# define STRNCMP wcsncmp ++# define STRNCPY wcsncpy ++# define CHAR wchar_t ++#else ++# define STRNCMP strncmp ++# define STRNCPY strncpy ++# define CHAR char ++#endif ++ ++IMPL (STRNCMP, 1) ++ ++typedef int (*proto_t) (const CHAR *, const CHAR *, size_t); ++ ++ ++static int ++__attribute__ ((noinline, noclone)) ++do_strncmp (parameter_t a, parameter_t b) ++{ ++ return CALL (&b, a.p, b.p, a.len); ++} ++ ++static int ++test_main (void) ++{ ++ test_init (); ++ ++ size_t size = page_size / sizeof (CHAR); ++ parameter_t dest = { { size }, buf1 }; ++ parameter_t src = { { 0 }, buf2 }; ++ ++ STRNCPY ((CHAR *) buf1, (const CHAR *) buf2, size); ++ ++ int ret = 0; ++ FOR_EACH_IMPL (impl, 0) ++ { ++ src.fn = impl->fn; ++ int res = do_strncmp (dest, src); ++ if (res) ++ { ++ error (0, 0, "Wrong result in function %s: %i != 0", ++ impl->name, res); ++ ret = 1; ++ } ++ } ++ ++ return ret ? EXIT_FAILURE : EXIT_SUCCESS; ++} ++ ++#include +diff --git a/sysdeps/x86_64/x32/tst-size_t-strncpy.c b/sysdeps/x86_64/x32/tst-size_t-strncpy.c +new file mode 100644 +index 0000000000..4dec71e6b3 +--- /dev/null ++++ b/sysdeps/x86_64/x32/tst-size_t-strncpy.c +@@ -0,0 +1,58 @@ ++/* Test strncpy with size_t in the lower 32 bits of 64-bit register. ++ Copyright (C) 2019 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 ++ . */ ++ ++#define TEST_NAME "strncpy" ++#include "test-size_t.h" ++ ++IMPL (strncpy, 1) ++ ++typedef char *(*proto_t) (char *, const char*, size_t); ++ ++static void * ++__attribute__ ((noinline, noclone)) ++do_strncpy (parameter_t a, parameter_t b) ++{ ++ return CALL (&b, a.p, b.p, a.len); ++} ++ ++static int ++test_main (void) ++{ ++ test_init (); ++ ++ parameter_t dest = { { page_size }, buf1 }; ++ parameter_t src = { { 0 }, buf2 }; ++ ++ int ret = 0; ++ FOR_EACH_IMPL (impl, 0) ++ { ++ src.fn = impl->fn; ++ do_strncpy (dest, src); ++ int res = strncmp (dest.p, src.p, dest.len); ++ if (res) ++ { ++ error (0, 0, "Wrong result in function %s: %i != 0", ++ impl->name, res); ++ ret = 1; ++ } ++ } ++ ++ return ret ? EXIT_FAILURE : EXIT_SUCCESS; ++} ++ ++#include +diff --git a/sysdeps/x86_64/x32/tst-size_t-strnlen.c b/sysdeps/x86_64/x32/tst-size_t-strnlen.c +new file mode 100644 +index 0000000000..690a4a8a31 +--- /dev/null ++++ b/sysdeps/x86_64/x32/tst-size_t-strnlen.c +@@ -0,0 +1,72 @@ ++/* Test strnlen with size_t in the lower 32 bits of 64-bit register. ++ Copyright (C) 2019 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 ++ . */ ++ ++#ifdef WIDE ++# define TEST_NAME "wcsnlen" ++#else ++# define TEST_NAME "strnlen" ++#endif /* WIDE */ ++ ++#include "test-size_t.h" ++ ++#ifdef WIDE ++# include ++# define STRNLEN wcsnlen ++# define CHAR wchar_t ++#else ++# define STRNLEN strnlen ++# define CHAR char ++#endif /* WIDE */ ++ ++IMPL (STRNLEN, 1) ++ ++typedef size_t (*proto_t) (const CHAR *, size_t); ++ ++static size_t ++__attribute__ ((noinline, noclone)) ++do_strnlen (parameter_t a, parameter_t b) ++{ ++ return CALL (&a, a.p, b.len); ++} ++ ++static int ++test_main (void) ++{ ++ test_init (); ++ ++ size_t size = page_size / sizeof (CHAR); ++ parameter_t src = { { 0 }, buf2 }; ++ parameter_t c = { { size }, (void *) (uintptr_t) 'a' }; ++ ++ int ret = 0; ++ FOR_EACH_IMPL (impl, 0) ++ { ++ src.fn = impl->fn; ++ size_t res = do_strnlen (src, c); ++ if (res != size) ++ { ++ error (0, 0, "Wrong result in function %s: 0x%x != 0x%x", ++ impl->name, res, size); ++ ret = 1; ++ } ++ } ++ ++ return ret ? EXIT_FAILURE : EXIT_SUCCESS; ++} ++ ++#include +diff --git a/sysdeps/x86_64/x32/tst-size_t-wcsncmp.c b/sysdeps/x86_64/x32/tst-size_t-wcsncmp.c +new file mode 100644 +index 0000000000..4829647c19 +--- /dev/null ++++ b/sysdeps/x86_64/x32/tst-size_t-wcsncmp.c +@@ -0,0 +1,20 @@ ++/* Test wcsncmp with size_t in the lower 32 bits of 64-bit register. ++ Copyright (C) 2019 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 ++ . */ ++ ++#define WIDE 1 ++#include "tst-size_t-strncmp.c" +diff --git a/sysdeps/x86_64/x32/tst-size_t-wcsnlen.c b/sysdeps/x86_64/x32/tst-size_t-wcsnlen.c +new file mode 100644 +index 0000000000..093b4bbe1b +--- /dev/null ++++ b/sysdeps/x86_64/x32/tst-size_t-wcsnlen.c +@@ -0,0 +1,20 @@ ++/* Test wcsnlen with size_t in the lower 32 bits of 64-bit register. ++ Copyright (C) 2019 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 ++ . */ ++ ++#define WIDE 1 ++#include "tst-size_t-strnlen.c" +diff --git a/sysdeps/x86_64/x32/tst-size_t-wmemchr.c b/sysdeps/x86_64/x32/tst-size_t-wmemchr.c +new file mode 100644 +index 0000000000..877801d646 +--- /dev/null ++++ b/sysdeps/x86_64/x32/tst-size_t-wmemchr.c +@@ -0,0 +1,20 @@ ++/* Test wmemchr with size_t in the lower 32 bits of 64-bit register. ++ Copyright (C) 2019 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 ++ . */ ++ ++#define WIDE 1 ++#include "tst-size_t-memchr.c" +diff --git a/sysdeps/x86_64/x32/tst-size_t-wmemcmp.c b/sysdeps/x86_64/x32/tst-size_t-wmemcmp.c +new file mode 100644 +index 0000000000..e8b5ffd0d5 +--- /dev/null ++++ b/sysdeps/x86_64/x32/tst-size_t-wmemcmp.c +@@ -0,0 +1,20 @@ ++/* Test wmemcmp with size_t in the lower 32 bits of 64-bit register. ++ Copyright (C) 2019 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 ++ . */ ++ ++#define WIDE 1 ++#include "tst-size_t-memcmp.c" +diff --git a/sysdeps/x86_64/x32/tst-size_t-wmemset.c b/sysdeps/x86_64/x32/tst-size_t-wmemset.c +new file mode 100644 +index 0000000000..955eb488c2 +--- /dev/null ++++ b/sysdeps/x86_64/x32/tst-size_t-wmemset.c +@@ -0,0 +1,20 @@ ++/* Test wmemset with size_t in the lower 32 bits of 64-bit register. ++ Copyright (C) 2019 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 ++ . */ ++ ++#define WIDE 1 ++#include "tst-size_t-memset.c" +diff --git a/time/tzfile.c b/time/tzfile.c +index 2a385b92bc..ea6e940303 100644 +--- a/time/tzfile.c ++++ b/time/tzfile.c +@@ -410,7 +410,8 @@ __tzfile_read (const char *file, size_t extra, char **extrap) + + /* First "register" all timezone names. */ + for (i = 0; i < num_types; ++i) +- (void) __tzstring (&zone_names[types[i].idx]); ++ if (__tzstring (&zone_names[types[i].idx]) == NULL) ++ goto ret_free_transitions; + + /* Find the standard and daylight time offsets used by the rule file. + We choose the offsets in the types of each flavor that are diff --git a/glibc-2.25-no-timestamping.patch b/glibc-2.25-no-timestamping.patch deleted file mode 100644 index 3301713..0000000 --- a/glibc-2.25-no-timestamping.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff -ru glibc-2.13/nscd/nscd_stat.c glibc-2.13-no-timestamping/nscd/nscd_stat.c ---- glibc-2.13/nscd/nscd_stat.c 2011-08-24 07:43:18.419464199 +0200 -+++ glibc-2.13-no-timestamping/nscd/nscd_stat.c 2011-08-24 07:43:52.837209224 +0200 -@@ -38,7 +38,7 @@ - - - /* We use this to make sure the receiver is the same. */ --static const char compilation[21] = __DATE__ " " __TIME__; -+static const char compilation[21] = "built on OBS"; - - /* Statistic data for one database. */ - struct dbstat diff --git a/glibc-2.25-bits.patch b/glibc-2.27-bits.patch similarity index 66% rename from glibc-2.25-bits.patch rename to glibc-2.27-bits.patch index de6014f..43b1875 100644 --- a/glibc-2.25-bits.patch +++ b/glibc-2.27-bits.patch @@ -1,75 +1,64 @@ ---- glibc-2.25/bits/wordsize.h.bak 2018-11-08 15:12:14.756848932 +0200 -+++ glibc-2.25/bits/wordsize.h 2018-11-08 15:13:00.505009458 +0200 -@@ -1,27 +1,25 @@ --#error "This file must be written based on the data type sizes of the target" +diff --git a/bits/endian.h b/bits/endian.h +index 45afd4a..f49f6ab 100644 +--- a/bits/endian.h ++++ b/bits/endian.h +@@ -1,13 +1,10 @@ +-/* This file should define __BYTE_ORDER as appropriate for the machine +- in question. See string/endian.h for how to define it. - - /* The following entries are a template for what defines should be in the - wordsize.h header file for a target. */ - - /* Size in bits of the 'long int' and pointer types. */ --#define __WORDSIZE -+#define __WORDSIZE 32 - - /* This should be set to 1 if __WORDSIZE is 32 and size_t is type - 'unsigned long' instead of type 'unsigned int'. This will ensure - that SIZE_MAX is defined as an unsigned long constant instead of an - unsigned int constant. Set to 0 if __WORDSIZE is 32 and size_t is - 'unsigned int' and leave undefined if __WORDSIZE is 64. */ --#define __WORDSIZE32_SIZE_ULONG -+#define __WORDSIZE32_SIZE_ULONG 0 - - /* This should be set to 1 if __WORDSIZE is 32 and ptrdiff_t is type 'long' - instead of type 'int'. This will ensure that PTRDIFF_MIN and PTRDIFF_MAX - are defined as long constants instead of int constants. Set to 0 if - __WORDSIZE is 32 and ptrdiff_t is type 'int' and leave undefined if - __WORDSIZE is 64. */ --#define __WORDSIZE32_PTRDIFF_LONG -+#define __WORDSIZE32_PTRDIFF_LONG 0 - - /* Set to 1 in order to force time types to be 32 bits instead of 64 bits in - struct lastlog and struct utmp{,x} on 64-bit ports. This may be done in - order to make 64-bit ports compatible with 32-bit ports. Set to 0 for - 64-bit ports where the time types are 64-bits or for any 32-bit ports. */ --#define __WORDSIZE_TIME64_COMPAT32 -+#define __WORDSIZE_TIME64_COMPAT32 0 ---- glibc-2.25/bits/errno.h.bak 2018-11-08 14:32:39.009340807 +0200 -+++ glibc-2.25/bits/errno.h 2018-11-08 14:43:21.450954354 +0200 -@@ -1,4 +1,5 @@ --/* Copyright (C) 1991-2017 Free Software Foundation, Inc. -+/* Error constants. Linux specific version. -+ Copyright (C) 1996-2014 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 -@@ -15,20 +16,51 @@ - License along with the GNU C Library; if not, see - . */ +- If only the stub bits/endian.h applies to a particular configuration, +- bytesex.h is generated by running a program on the host machine. +- So if cross-compiling to a machine with a different byte order, +- the bits/endian.h file for that machine must exist. */ +- + #ifndef _ENDIAN_H + # error "Never use directly; include instead." + #endif --/* This file defines the `errno' constants. */ -+#ifdef _ERRNO_H +-#error Machine byte order unknown. ++/* ARM can be either big or little endian. */ ++#ifdef __ARMEB__ ++#define __BYTE_ORDER __BIG_ENDIAN ++#else ++#define __BYTE_ORDER __LITTLE_ENDIAN ++#endif +diff --git a/bits/errno.h b/bits/errno.h +index 36c09f3..4eef942 100644 +--- a/bits/errno.h ++++ b/bits/errno.h +@@ -25,26 +25,52 @@ + # error "Never include directly; use instead." + #endif --#if !defined __Emath_defined && (defined _ERRNO_H || defined __need_Emath) --#undef __need_Emath --#define __Emath_defined 1 +-#error "Generic bits/errno.h included -- port is incomplete." +- +-/* Authors of new ports of the GNU C Library must override this file +- with their own bits/errno.h in an appropriate subdirectory of +- sysdeps/. Its function is to define all of the error constants +- from C2011 and POSIX.1-2008, with values appropriate to the +- operating system, and any additional OS-specific error constants. - --# define EDOM XXX <--- fill in what is actually needed --# define EILSEQ XXX <--- fill in what is actually needed --# define ERANGE XXX <--- fill in what is actually needed --#endif +- C2011 requires all error constants to be object-like macros that +- expand to "integer constant expressions with type int, positive +- values, and suitable for use in #if directives". Moreover, all of +- their names must begin with a capital E, followed immediately by +- either another capital letter, or a digit. It is OK to define +- macros that are not error constants, but only in the implementation +- namespace. - --#ifdef _ERRNO_H --# error "Define here all the missing error messages for the port. These" --# error "must match the numbers of the kernel." --# define Exxxx XXX --... --#endif -+# undef EDOM -+# undef EILSEQ -+# undef ERANGE +- errno.h is sometimes included from assembly language. Therefore, +- when __ASSEMBLER__ is defined, bits/errno.h may only define macros; +- it may not make any other kind of C declaration or definition. +- Also, the error constants should, if at all possible, expand to +- simple decimal or hexadecimal numbers. */ ++#ifdef _ERRNO_H ++ +# include + -+/* Linux has no ENOTSUP error code. */ -+# define ENOTSUP EOPNOTSUPP ++/* Older Linux headers do not define these constants. */ ++# ifndef ENOTSUP ++# define ENOTSUP EOPNOTSUPP ++# endif + +/* Older Linux versions also had no ECANCELED error code. */ +# ifndef ECANCELED @@ -109,25 +98,41 @@ +# define EILSEQ 84 /* Illegal byte sequence. */ +# define ERANGE 34 /* Math result not representable. */ +#endif /* !_ERRNO_H && __need_Emath */ ---- glibc-2.25/bits/endian.h.bak 2018-11-08 15:51:55.110637120 +0200 -+++ glibc-2.25/bits/endian.h 2018-11-08 15:52:20.538742585 +0200 -@@ -1,13 +1,10 @@ --/* This file should define __BYTE_ORDER as appropriate for the machine -- in question. See string/endian.h for how to define it. -- -- If only the stub bits/endian.h applies to a particular configuration, -- bytesex.h is generated by running a program on the host machine. -- So if cross-compiling to a machine with a different byte order, -- the bits/endian.h file for that machine must exist. */ + + #endif /* bits/errno.h. */ +diff --git a/bits/wordsize.h b/bits/wordsize.h +index 14edae3..46ac7fd 100644 +--- a/bits/wordsize.h ++++ b/bits/wordsize.h +@@ -1,27 +1,25 @@ +-#error "This file must be written based on the data type sizes of the target" - - #ifndef _ENDIAN_H - # error "Never use directly; include instead." - #endif + /* The following entries are a template for what defines should be in the + wordsize.h header file for a target. */ --#error Machine byte order unknown. -+/* ARM can be either big or little endian. */ -+#ifdef __ARMEB__ -+#define __BYTE_ORDER __BIG_ENDIAN -+#else -+#define __BYTE_ORDER __LITTLE_ENDIAN -+#endif + /* Size in bits of the 'long int' and pointer types. */ +-#define __WORDSIZE ++#define __WORDSIZE 32 + + /* This should be set to 1 if __WORDSIZE is 32 and size_t is type + 'unsigned long' instead of type 'unsigned int'. This will ensure + that SIZE_MAX is defined as an unsigned long constant instead of an + unsigned int constant. Set to 0 if __WORDSIZE is 32 and size_t is + 'unsigned int' and leave undefined if __WORDSIZE is 64. */ +-#define __WORDSIZE32_SIZE_ULONG ++#define __WORDSIZE32_SIZE_ULONG 0 + + /* This should be set to 1 if __WORDSIZE is 32 and ptrdiff_t is type 'long' + instead of type 'int'. This will ensure that PTRDIFF_MIN and PTRDIFF_MAX + are defined as long constants instead of int constants. Set to 0 if + __WORDSIZE is 32 and ptrdiff_t is type 'int' and leave undefined if + __WORDSIZE is 64. */ +-#define __WORDSIZE32_PTRDIFF_LONG ++#define __WORDSIZE32_PTRDIFF_LONG 0 + + /* Set to 1 in order to force time types to be 32 bits instead of 64 bits in + struct lastlog and struct utmp{,x} on 64-bit ports. This may be done in + order to make 64-bit ports compatible with 32-bit ports. Set to 0 for + 64-bit ports where the time types are 64-bits or for any 32-bit ports. */ +-#define __WORDSIZE_TIME64_COMPAT32 ++#define __WORDSIZE_TIME64_COMPAT32 0 diff --git a/glibc-2.25-ldso-rpath-prefix-option.diff b/glibc-2.27-ldso-rpath-prefix-option.diff similarity index 70% rename from glibc-2.25-ldso-rpath-prefix-option.diff rename to glibc-2.27-ldso-rpath-prefix-option.diff index fb6d22d..1f4dcba 100644 --- a/glibc-2.25-ldso-rpath-prefix-option.diff +++ b/glibc-2.27-ldso-rpath-prefix-option.diff @@ -1,19 +1,20 @@ -Index: eglibc-2.19/elf/dl-load.c -=================================================================== ---- eglibc-2.19.orig/elf/dl-load.c -+++ eglibc-2.19/elf/dl-load.c -@@ -482,7 +482,7 @@ static size_t max_dirnamelen; +diff --git a/elf/dl-load.c b/elf/dl-load.c +index 7554a99..eb34a7a 100644 +--- a/elf/dl-load.c ++++ b/elf/dl-load.c +@@ -385,7 +385,8 @@ static size_t max_dirnamelen; + static struct r_search_path_elem ** fillin_rpath (char *rpath, struct r_search_path_elem **result, const char *sep, - int check_trusted, const char *what, const char *where, -- struct link_map *l) -+ struct link_map *l, const char *rpath_prefix) +- const char *what, const char *where, struct link_map *l) ++ const char *what, const char *where, struct link_map *l, ++ const char *rpath_prefix) { char *cp; size_t nelems = 0; -@@ -520,9 +520,23 @@ fillin_rpath (char *rpath, struct r_sear +@@ -425,9 +426,23 @@ fillin_rpath (char *rpath, struct r_search_path_elem **result, const char *sep, } - + /* See if this directory is already known. */ - for (dirp = GL(dl_all_dirs); dirp != NULL; dirp = dirp->next) - if (dirp->dirnamelen == len && memcmp (cp, dirp->dirname, len) == 0) @@ -35,10 +36,10 @@ Index: eglibc-2.19/elf/dl-load.c + if (dirp->dirnamelen == len && memcmp (cp, dirp->dirname, len) == 0) + break; + } - + if (dirp != NULL) { -@@ -540,22 +554,43 @@ fillin_rpath (char *rpath, struct r_sear +@@ -445,22 +460,43 @@ fillin_rpath (char *rpath, struct r_search_path_elem **result, const char *sep, size_t cnt; enum r_dir_status init_val; size_t where_len = where ? strlen (where) + 1 : 0; @@ -50,7 +51,7 @@ Index: eglibc-2.19/elf/dl-load.c + rpath_prefix_len = strlen (rpath_prefix); + if (*cp != '/') rpath_prefix_len++; /* need to add a '/' */ + } - + /* It's a new directory. Create an entry and add it. */ dirp = (struct r_search_path_elem *) malloc (sizeof (*dirp) + ncapstr * sizeof (enum r_dir_status) @@ -59,7 +60,7 @@ Index: eglibc-2.19/elf/dl-load.c if (dirp == NULL) _dl_signal_error (ENOMEM, NULL, NULL, N_("cannot create cache for search path")); - + dirp->dirname = ((char *) dirp + sizeof (*dirp) + ncapstr * sizeof (enum r_dir_status)); - *((char *) __mempcpy ((char *) dirp->dirname, cp, len)) = '\0'; @@ -79,16 +80,16 @@ Index: eglibc-2.19/elf/dl-load.c + *((char *) __mempcpy (prefixend, cp, len)) = '\0'; + } + dirp->dirnamelen = len + rpath_prefix_len; - + - if (len > max_dirnamelen) - max_dirnamelen = len; + if ((len + rpath_prefix_len) > max_dirnamelen) + max_dirnamelen = len + rpath_prefix_len; - + /* We have to make sure all the relative directories are never ignored. The current directory might change and -@@ -566,7 +601,8 @@ fillin_rpath (char *rpath, struct r_sear - +@@ -471,7 +507,8 @@ fillin_rpath (char *rpath, struct r_search_path_elem **result, const char *sep, + dirp->what = what; if (__glibc_likely (where != NULL)) - dirp->where = memcpy ((char *) dirp + sizeof (*dirp) + len + 1 @@ -97,59 +98,59 @@ Index: eglibc-2.19/elf/dl-load.c + (ncapstr * sizeof (enum r_dir_status)), where, where_len); else -@@ -668,7 +704,7 @@ decompose_rpath (struct r_search_path_st +@@ -570,7 +607,7 @@ decompose_rpath (struct r_search_path_struct *sps, _dl_signal_error (ENOMEM, NULL, NULL, errstring); } - -- fillin_rpath (copy, result, ":", 0, what, where, l); -+ fillin_rpath (copy, result, ":", 0, what, where, l, GLRO(dl_rpath_prefix)); - + +- fillin_rpath (copy, result, ":", what, where, l); ++ fillin_rpath (copy, result, ":", what, where, l, GLRO(dl_rpath_prefix)); + /* Free the copied RPATH string. `fillin_rpath' make own copies if necessary. */ -@@ -871,7 +907,7 @@ _dl_init_paths (const char *llp) - +@@ -755,7 +792,7 @@ _dl_init_paths (const char *llp) + } + (void) fillin_rpath (llp_tmp, env_path_list.dirs, ":;", - __libc_enable_secure, "LD_LIBRARY_PATH", -- NULL, l); -+ NULL, l, NULL/*no prefix*/); - +- "LD_LIBRARY_PATH", NULL, l); ++ "LD_LIBRARY_PATH", NULL, l, NULL/*no prefix*/); + if (env_path_list.dirs[0] == NULL) { -Index: eglibc-2.19/elf/dl-support.c -=================================================================== ---- eglibc-2.19.orig/elf/dl-support.c -+++ eglibc-2.19/elf/dl-support.c -@@ -61,6 +61,9 @@ const char *_dl_profile_output; +diff --git a/elf/dl-support.c b/elf/dl-support.c +index 114f77a..502399f 100644 +--- a/elf/dl-support.c ++++ b/elf/dl-support.c +@@ -58,6 +58,9 @@ const char *_dl_profile_output; ignored. */ const char *_dl_inhibit_rpath; - + +/* prefix to be added to all RUNPATHs and RPATHs */ +const char *_dl_rpath_prefix = NULL; + /* The map for the object we will profile. */ struct link_map *_dl_profile_map; - -Index: eglibc-2.19/elf/rtld.c -=================================================================== ---- eglibc-2.19.orig/elf/rtld.c -+++ eglibc-2.19/elf/rtld.c -@@ -991,6 +991,15 @@ dl_main (const ElfW(Phdr) *phdr, - _dl_argc -= 2; - _dl_argv += 2; - } + +diff --git a/elf/rtld.c b/elf/rtld.c +index 453f56e..c6bdd02 100644 +--- a/elf/rtld.c ++++ b/elf/rtld.c +@@ -965,6 +965,15 @@ dl_main (const ElfW(Phdr) *phdr, + { + GLRO(dl_inhibit_rpath) = _dl_argv[2]; + ++ _dl_skip_args += 2; ++ _dl_argc -= 2; ++ _dl_argv += 2; ++ } + else if (! strcmp (_dl_argv[1], "--rpath-prefix") + && _dl_argc > 2) + { + GLRO(dl_rpath_prefix) = _dl_argv[2]; + -+ _dl_skip_args += 2; -+ _dl_argc -= 2; -+ _dl_argv += 2; -+ } - else if (! strcmp (_dl_argv[1], "--audit") && _dl_argc > 2) - { - process_dl_audit (_dl_argv[2]); -@@ -1025,6 +1034,7 @@ of this helper program; chances are you + _dl_skip_args += 2; + _dl_argc -= 2; + _dl_argv += 2; +@@ -1003,6 +1012,7 @@ of this helper program; chances are you did not intend to run this program.\n\ --inhibit-cache Do not use " LD_SO_CACHE "\n\ --library-path PATH use given PATH instead of content of the environment\n\ variable LD_LIBRARY_PATH\n\ @@ -157,11 +158,11 @@ Index: eglibc-2.19/elf/rtld.c --inhibit-rpath LIST ignore RUNPATH and RPATH information in object names\n\ in LIST\n\ --audit LIST use objects named in LIST as auditors\n"); -Index: eglibc-2.19/sysdeps/generic/ldsodefs.h -=================================================================== ---- eglibc-2.19.orig/sysdeps/generic/ldsodefs.h -+++ eglibc-2.19/sysdeps/generic/ldsodefs.h -@@ -600,6 +600,12 @@ struct rtld_global_ro +diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h +index 0ea2786..a9bff29 100644 +--- a/sysdeps/generic/ldsodefs.h ++++ b/sysdeps/generic/ldsodefs.h +@@ -608,6 +608,12 @@ struct rtld_global_ro /* List of auditing interfaces. */ struct audit_ifaces *_dl_audit; unsigned int _dl_naudit; @@ -173,4 +174,4 @@ Index: eglibc-2.19/sysdeps/generic/ldsodefs.h +#ifdef SHARED }; # define __rtld_global_attribute__ - # ifdef IS_IN_rtld + # if IS_IN (rtld) diff --git a/glibc-2.25.tar.xz b/glibc-2.28.tar.xz similarity index 57% rename from glibc-2.25.tar.xz rename to glibc-2.28.tar.xz index c9c84dd..6ae1e01 100644 Binary files a/glibc-2.25.tar.xz and b/glibc-2.28.tar.xz differ diff --git a/glibc.changes b/glibc.changes index a12494f..cf7fbd8 100644 --- a/glibc.changes +++ b/glibc.changes @@ -1,3 +1,19 @@ +* Thu Apr 25 2019 Niels Breet - 2.28+git1 +- Update to 2.28. Fixes JB#45154 +- Fixes CVE-2016-10739, CVE-2016-6261, CVE-2016-6263, CVE-2017-14062, + CVE-2017-18269, CVE-2018-11236, CVE-2018-11237, CVE-2018-19591, + CVE-2019-6488, CVE-2019-7309, CVE-2019-9169 + +* Thu Mar 28 2019 Marko Saukko - 2.27+git1 +- Update to 2.27. Fixes JB#45152 +- Drop already integrated patch glibc-2.25-posix-spawn-fix.patch +- Drop not needed patch glibc-2.25-no-timestamping.patch +- Fixes CVE-2009-5064, CVE-2017-15670, CVE-2017-15671, CVE-2017-15804, + CVE-2017-17426, CVE-2017-1000408, CVE-2017-1000409, CVE-2017-16997, + CVE-2018-1000001,CVE-2018-6485 + 2.26 Fixes CVE-2017-1000366, CVE-2010-3192, CVE-2010-3192, + CVE-2017-12132 + * Wed Mar 27 2019 Marko Kenttälä - 2.25+git5 - Added debuginfo handling, fixes jb#45224 diff --git a/glibc.spec b/glibc.spec index c9e876e..e2b8f3f 100644 --- a/glibc.spec +++ b/glibc.spec @@ -1,29 +1,30 @@ -%define glibcsrcdir glibc-2.25 +%define glibcsrcdir glibc-2.28 +# Default: Always disable the benchtests. +%bcond_with benchtests Name: glibc Summary: GNU C library shared libraries -Version: 2.25+git5 +Version: 2.28+git1 Release: 0 License: LGPLv2+ and LGPLv2+ with exceptions and GPLv2+ Group: System/Libraries URL: http://www.gnu.org/software/libc/ -Source0: glibc-2.25.tar.xz -Source11: build-locale-archive.c +Source0: glibc-2.28.tar.xz +Source1: build-locale-archive.c Patch1: glibc-arm-alignment-fix.patch Patch2: glibc-2.25-arm-runfast.patch -Patch3: glibc-2.25-no-timestamping.patch Patch4: glibc-2.25-elf-rtld.diff -Patch5: glibc-2.25-ldso-rpath-prefix-option.diff +Patch5: glibc-2.27-ldso-rpath-prefix-option.diff Patch6: glibc-2.25-nsswitchconf-location.diff Patch7: glibc-2.25-nscd-socket-location.diff Patch8: glibc-2.25-ldso-nodefaultdirs-option.diff Patch9: glibc-2.14-locarchive-fedora.patch Patch10: eglibc-2.15-fix-neon-libdl.patch Patch11: eglibc-2.19-shlib-make.patch -Patch12: glibc-2.25-bits.patch -Patch13: ubuntu-2.25.6-git-updates.diff +Patch12: glibc-2.27-bits.patch +Patch13: git-updates.diff Provides: ldconfig # The dynamic linker supports DT_GNU_HASH @@ -45,7 +46,7 @@ BuildRequires: gawk, util-linux, quilt # This gcc >= 3.2 is to ensure that __frame_state_for is exported by glibc # will be compatible with egcs 1.x.y BuildRequires: gcc >= 3.2 -%define enablekernel 2.6.32 +%define enablekernel 3.2 %ifarch %{ix86} %ifarch i486 %define _target_cpu i486 @@ -70,6 +71,9 @@ BuildRequires: binutils >= 2.19.51.0.10 BuildRequires: gcc >= 3.2.1-5 BuildRequires: elfutils >= 0.72 BuildRequires: rpm >= 4.2-0.56 +BuildRequires: bison >= 2.7 +# GNU make 4.0 introduced the -O option. +BuildRequires: make >= 4.0 %define __find_provides %{_builddir}/%{glibcsrcdir}/find_provides.sh %define _filter_GLIBC_PRIVATE 1 @@ -148,6 +152,26 @@ Group: System/Base The glibc-common package includes common binaries for the GNU libc libraries, as well as national language (locale) support. +###################################################################### +# File triggers to do ldconfig calls automatically (see rhbz#1380878) +###################################################################### + +# File triggers for when libraries are added or removed in standard +# paths. +%transfiletriggerin common -P 2000000 -- /lib /usr/lib /lib64 /usr/lib64 +/sbin/ldconfig +%end + +%transfiletriggerpostun common -P 2000000 -- /lib /usr/lib /lib64 /usr/lib64 +/sbin/ldconfig +%end + +# We need to run ldconfig manually because ldconfig cannot handle the +# relative include path in the /etc/ld.so.conf file we gneerate. +%undefine __brp_ldconfig + +###################################################################### + %package -n nscd Summary: A Name Service Caching Daemon (nscd) Group: System/Daemons @@ -169,6 +193,16 @@ which can be helpful during program debugging. If unsure if you need this, don't install this package. +%package debuginfo +Summary: Debug libraries from GNU C library +Group: Development/Libraries +Requires: %{name} = %{version}-%{release} + +%description debuginfo +The glibc-debug package contains debug libraries. + +If unsure if you need this, don't install this package. + %package doc Summary: Documentation for %{name} Group: Documentation @@ -178,7 +212,7 @@ Requires: %{name} = %{version}-%{release} %{summary}. %prep -%setup -q -n %{glibcsrcdir} +rm -rf %{glibcsrcdir} xz -dc %SOURCE0 | tar -x cd %{glibcsrcdir} @@ -186,7 +220,6 @@ cd %{glibcsrcdir} %ifarch %{arm} %patch2 -p1 %endif -%patch3 -p1 %patch4 -p1 %patch5 -p1 %patch6 -p1 @@ -214,107 +247,372 @@ BuildFlags="$BuildFlags -march=core2 -mtune=atom" BuildFlags="$BuildFlags -fasynchronous-unwind-tables" %endif -EnableKernel="--enable-kernel=%{enablekernel}" -echo "$GCC" > Gcc - -builddir=build-%{name}-%{version} -rm -rf build-%{name}-* -mkdir $builddir ; cd $builddir - -echo libdir=/usr/lib > configparms -echo slibdir=/lib >> configparms -echo BUILD_CC=gcc >> configparms - %ifarch mipsel build_CFLAGS="$BuildFlags -O1" %else build_CFLAGS="$BuildFlags -O3" %endif -export MAKEINFO=: +# Special flag to enable annobin annotations for statically linked +# assembler code. Needs to be passed to make; not preserved by +# configure. +%define glibc_make_flags_as ASFLAGS="-g" +%define glibc_make_flags %{glibc_make_flags_as} -../%{glibcsrcdir}/configure CC="$GCC" CXX="$GXX" CFLAGS="$build_CFLAGS" \ - --prefix=%{_prefix} \ - "--enable-add-ons=libidn" --without-cvs $EnableKernel \ - --enable-bind-now --with-tls \ - --with-headers=%{_prefix}/include \ -%ifarch %{multiarcharches} - --enable-multi-arch \ +EnableKernel="--enable-kernel=%{enablekernel}" +# Save the used compiler and options into the file "Gcc" for use later +# by %%install. +echo "$GCC" > Gcc + +############################################################################## +# build() +# Build glibc in `build-%%{target}$1', passing the rest of the arguments +# as CFLAGS to the build (not the same as configure CFLAGS). Several +# global values are used to determine build flags, kernel version, +# system tap support, etc. +############################################################################## +build() +{ + local builddir=build-%{target}${1:+-$1} + ${1+shift} + rm -rf $builddir + mkdir $builddir + pushd $builddir + ../%{glibcsrcdir}/configure CC="$GCC" CXX="$GXX" CFLAGS="$build_CFLAGS" \ + --prefix=%{_prefix} \ + --with-headers=%{_prefix}/include $EnableKernel \ + --enable-bind-now \ + --build=%{target} \ + --enable-stack-protector=strong \ + --disable-profile \ + --enable-obsolete-rpc \ + --disable-profile \ + --enable-obsolete-rpc \ + ${core_with_options} \ + --disable-multi-arch \ +%if %{without werror} + --disable-werror \ +%endif + --disable-profile \ +%if %{with bootstrap} + --without-selinux \ %endif - --disable-profile --enable-obsolete-rpc \ - --enable-stack-protector=strong \ - --build=%{target} + libc_cv_slibdir=/lib || + { cat config.log; false; } -make %{?_smp_mflags} -r CFLAGS="$build_CFLAGS" +# Note: We need /lib instead of /lib64 for aarch64, so we force it here -cd .. + make %{?_smp_mflags} -O -r CFLAGS="$build_CFLAGS" + popd +} -$GCC -Os -static -o build-locale-archive %SOURCE11 \ - ./build-%{name}-%{version}/locale/locarchive.o \ - ./build-%{name}-%{version}/locale/md5.o \ - -DDATADIR=\"%{_datadir}\" -DPREFIX=\"%{_prefix}\" \ - -L./build-%{name}-%{version} -I%{glibcsrcdir} +# Default set of compiler options. +build +############################################################################## +# Install glibc... +############################################################################## %install -rm -rf ${RPM_BUILD_ROOT} -cd build-%{name}-%{version} -make -j1 install_root=${RPM_BUILD_ROOT} install -install -p -m 644 ../%{glibcsrcdir}/nss/nsswitch.conf $RPM_BUILD_ROOT/etc/nsswitch.conf +# The built glibc is installed into a subdirectory of $RPM_BUILD_ROOT. +# For a system glibc that subdirectory is "/" (the root of the filesystem). +# This is called a sysroot (system root) and can be changed if we have a +# distribution that supports multiple installed glibc versions. +%define glibc_sysroot $RPM_BUILD_ROOT + +# Remove existing file lists. +find . -type f -name '*.filelist' -exec rm -rf {} \; + +# Reload compiler and build options that were used during %%build. +GCC=`cat Gcc` + +# Build and install: +make -j1 install_root=%{glibc_sysroot} install -C build-%{target} + +# install_different: +# Install all core libraries into DESTDIR/SUBDIR. Either the file is +# installed as a copy or a symlink to the default install (if it is the +# same). The path SUBDIR_UP is the prefix used to go from +# DESTDIR/SUBDIR to the default installed libraries e.g. +# ln -s SUBDIR_UP/foo.so DESTDIR/SUBDIR/foo.so. +# When you call this function it is expected that you are in the root +# of the build directory, and that the default build directory is: +# "../build-%%{target}" (relatively). +# The primary use of this function is to install alternate runtimes +# into the build directory and avoid duplicating this code for each +# runtime. +install_different() +{ + local lib libbase libbaseso dlib + local destdir="$1" + local subdir="$2" + local subdir_up="$3" + local libdestdir="$destdir/$subdir" + # All three arguments must be non-zero paths. + if ! [ "$destdir" \ + -a "$subdir" \ + -a "$subdir_up" ]; then + echo "One of the arguments to install_different was emtpy." + exit 1 + fi + # Create the destination directory and the multilib directory. + mkdir -p "$destdir" + mkdir -p "$libdestdir" + # Walk all of the libraries we installed... + for lib in libc math/libm nptl/libpthread rt/librt nptl_db/libthread_db + do + libbase=${lib#*/} + # Take care that `libbaseso' has a * that needs expanding so + # take care with quoting. + libbaseso=$(basename %{glibc_sysroot}/%{_lib}/${libbase}-*.so) + # Only install if different from default build library. + if cmp -s ${lib}.so ../build-%{target}/${lib}.so; then + ln -sf "$subdir_up"/$libbaseso $libdestdir/$libbaseso + else + cp -a ${lib}.so $libdestdir/$libbaseso + fi + dlib=$libdestdir/$(basename %{glibc_sysroot}/%{_lib}/${libbase}.so.*) + ln -sf $libbaseso $dlib + done +} + +############################################################################## +# Remove the files we don't want to distribute +############################################################################## + +# Remove the libNoVersion files. +# XXX: This looks like a bug in glibc that accidentally installed these +# wrong files. We probably don't need this today. +rm -f %{glibc_sysroot}/%{_libdir}/libNoVersion* +rm -f %{glibc_sysroot}/%{_lib}/libNoVersion* + +# Remove the old nss modules. +rm -f %{glibc_sysroot}/%{_lib}/libnss1-* +rm -f %{glibc_sysroot}/%{_lib}/libnss-*.so.1 + +# This statically linked binary is no longer necessary in a world where +# the default Fedora install uses an initramfs, and further we have rpm-ostree +# which captures the whole userspace FS tree. +# Further, see https://github.com/projectatomic/rpm-ostree/pull/1173#issuecomment-355014583 +rm -f %{glibc_sysroot}/{usr/,}sbin/sln + +###################################################################### +# Run ldconfig to create all the symbolic links we need +###################################################################### + +# Note: This has to happen before creating /etc/ld.so.conf. + +mkdir -p %{glibc_sysroot}/var/cache/ldconfig +> %{glibc_sysroot}/var/cache/ldconfig/aux-cache + +# ldconfig is statically linked, so we can use the new version. +%{glibc_sysroot}/sbin/ldconfig -N -r %{glibc_sysroot} + +############################################################################## +# Install info files +############################################################################## + +%if %{with docs} +# Move the info files if glibc installed them into the wrong location. +if [ -d %{glibc_sysroot}%{_prefix}/info -a "%{_infodir}" != "%{_prefix}/info" ]; then + mkdir -p %{glibc_sysroot}%{_infodir} + mv -f %{glibc_sysroot}%{_prefix}/info/* %{glibc_sysroot}%{_infodir} + rm -rf %{glibc_sysroot}%{_prefix}/info +fi -mkdir -p $RPM_BUILD_ROOT/etc/default -install -p -m 644 ../%{glibcsrcdir}/nis/nss $RPM_BUILD_ROOT/etc/default/nss +# Compress all of the info files. +gzip -9nvf %{glibc_sysroot}%{_infodir}/libc* -install -m 644 ../%{glibcsrcdir}/nscd/nscd.conf $RPM_BUILD_ROOT/etc +%else +rm -f %{glibc_sysroot}%{_infodir}/dir +rm -f %{glibc_sysroot}%{_infodir}/libc.info* +%endif -# Include ld.so.conf -echo 'include /etc/ld.so.conf.d/*.conf' > $RPM_BUILD_ROOT/etc/ld.so.conf -> $RPM_BUILD_ROOT/etc/ld.so.cache -chmod 644 $RPM_BUILD_ROOT/etc/ld.so.conf -mkdir -p $RPM_BUILD_ROOT/etc/ld.so.conf.d -mkdir -p $RPM_BUILD_ROOT/etc/sysconfig -> $RPM_BUILD_ROOT/etc/sysconfig/nscd - -# Include %{_prefix}/%{_lib}/gconv/gconv-modules.cache -> $RPM_BUILD_ROOT%{_prefix}/%{_lib}/gconv/gconv-modules.cache -chmod 644 $RPM_BUILD_ROOT%{_prefix}/%{_lib}/gconv/gconv-modules.cache - -strip -g $RPM_BUILD_ROOT%{_prefix}/%{_lib}/*.o - -mkdir -p $RPM_BUILD_ROOT%{_prefix}/lib/debug%{_prefix}/%{_lib} -cp -a $RPM_BUILD_ROOT%{_prefix}/%{_lib}/*.a \ - $RPM_BUILD_ROOT%{_prefix}/lib/debug%{_prefix}/%{_lib}/ -rm -f $RPM_BUILD_ROOT%{_prefix}/lib/debug%{_prefix}/%{_lib}/*_p.a -# Now strip debugging info from static libraries -pushd $RPM_BUILD_ROOT%{_prefix}/%{_lib}/ -for i in *.a; do - if [ -f $i ]; then - case "$i" in - *_p.a) ;; - *) strip -g -R .comment $i ;; - esac - fi -done -popd +############################################################################## +# Install configuration files for services +############################################################################## +install -p -m 644 %{glibcsrcdir}/nss/nsswitch.conf %{glibc_sysroot}/etc/nsswitch.conf -mkdir -p $RPM_BUILD_ROOT/%{_prefix}/lib/locale/ +%ifnarch %{auxarches} +# This is for ncsd - in glibc 2.2 +install -m 644 %{glibcsrcdir}/nscd/nscd.conf %{glibc_sysroot}/etc +mkdir -p %{glibc_sysroot}%{_tmpfilesdir} +install -m 644 %{glibcsrcdir}/nscd/nscd.conf %{buildroot}%{_tmpfilesdir} +mkdir -p %{glibc_sysroot}/lib/systemd/system +install -m 644 %{glibcsrcdir}/nscd/nscd.service %{glibc_sysroot}/lib/systemd/system +%endif -%ifarch armv7hl armv7tnhl armv7nhl -ln -s /lib/ld-linux-armhf.so.3 ${RPM_BUILD_ROOT}/lib/ld-linux.so.3 +# Include ld.so.conf +echo 'include ld.so.conf.d/*.conf' > %{glibc_sysroot}/etc/ld.so.conf +echo -n '' > %{glibc_sysroot}/etc/ld.so.cache +chmod 644 %{glibc_sysroot}/etc/ld.so.conf +mkdir -p %{glibc_sysroot}/etc/ld.so.conf.d +%ifnarch %{auxarches} +mkdir -p %{glibc_sysroot}/etc/sysconfig +> %{glibc_sysroot}/etc/sysconfig/nscd %endif -rm -f ${RPM_BUILD_ROOT}/%{_lib}/libnss1-* -rm -f ${RPM_BUILD_ROOT}/%{_lib}/libnss-*.so.1 +# Include %%{_libdir}/gconv/gconv-modules.cache +mkdir -p %{glibc_sysroot}%{_libdir}/gconv +echo -n '' > %{glibc_sysroot}%{_libdir}/gconv/gconv-modules.cache +chmod 644 %{glibc_sysroot}%{_libdir}/gconv/gconv-modules.cache + + +############################################################################## +# Install debug copies of unstripped static libraries +# - This step must be last in order to capture any additional static +# archives we might have added. +############################################################################## + +# If we are building a debug package then copy all of the static archives +# into the debug directory to keep them as unstripped copies. +%if 0%{?_enable_debug_packages} +mkdir -p %{glibc_sysroot}%{_prefix}/lib/debug%{_libdir} +cp -a %{glibc_sysroot}%{_libdir}/*.a \ + %{glibc_sysroot}%{_prefix}/lib/debug%{_libdir}/ || true +rm -f %{glibc_sysroot}%{_prefix}/lib/debug%{_libdir}/*_p.a || true +%endif -# Ugly hack for buggy rpm -ln -f ${RPM_BUILD_ROOT}%{_sbindir}/iconvconfig{,.%{_target_cpu}} +# Remove any zoneinfo files; they are maintained by tzdata. +rm -rf %{glibc_sysroot}%{_prefix}/share/zoneinfo + +# Make sure %%config files have the same timestamp across multilib packages. +# +# XXX: Ideally ld.so.conf should have the timestamp of the spec file, but there +# doesn't seem to be any macro to give us that. So we do the next best thing, +# which is to at least keep the timestamp consistent. The choice of using +# glibc_post_upgrade.c is arbitrary. +touch -r %{SOURCE0} %{glibc_sysroot}/etc/ld.so.conf +touch -r %{glibcsrcdir}/sunrpc/etc.rpc %{glibc_sysroot}/etc/rpc + +pushd build-%{target} +$GCC -Os -g -static -o build-locale-archive %{SOURCE1} \ + ../build-%{target}/locale/locarchive.o \ + ../build-%{target}/locale/md5.o \ + ../build-%{target}/locale/record-status.o \ + -I../%{glibcsrcdir} -DDATADIR=\"%{_datadir}\" -DPREFIX=\"%{_prefix}\" \ + -L../build-%{target} \ + -B../build-%{target}/csu/ -lc -lc_nonshared +install -m 700 build-locale-archive %{glibc_sysroot}%{_prefix}/sbin/build-locale-archive +popd -rm -f $RPM_BUILD_ROOT/etc/gai.conf +# Lastly copy some additional documentation for the packages. +rm -rf %{glibcsrcdir}/documentation +mkdir %{glibcsrcdir}/documentation +cp %{glibcsrcdir}/timezone/README %{glibcsrcdir}/documentation/README.timezone -# In F7+ this is provided by rpcbind rpm -rm -f $RPM_BUILD_ROOT%{_sbindir}/rpcinfo +#%if 0%{?_enable_debug_packages} -# BUILD THE FILE LIST +%if %{with docs} +# Remove the `dir' info-heirarchy file which will be maintained +# by the system as it adds info files to the install. +rm -f %{glibc_sysroot}%{_infodir}/dir +%endif + +%ifnarch %{auxarches} +mkdir -p %{glibc_sysroot}/var/{db,run}/nscd +touch %{glibc_sysroot}/var/{db,run}/nscd/{passwd,group,hosts,services} +touch %{glibc_sysroot}/var/run/nscd/{socket,nscd.pid} +%endif + +# Move libpcprofile.so and libmemusage.so into the proper library directory. +# They can be moved without any real consequences because users would not use +# them directly. +mkdir -p %{glibc_sysroot}%{_libdir} +mv -f %{glibc_sysroot}/%{_lib}/lib{pcprofile,memusage}.so \ + %{glibc_sysroot}%{_libdir} + +# Strip all of the installed object files. +strip -g %{glibc_sysroot}%{_libdir}/*.o + +############################################################################### +# Rebuild libpthread.a using --whole-archive to ensure all of libpthread +# is included in a static link. This prevents any problems when linking +# statically, using parts of libpthread, and other necessary parts not +# being included. Upstream has decided that this is the wrong approach to +# this problem and that the full set of dependencies should be resolved +# such that static linking works and produces the most minimally sized +# static application possible. +############################################################################### +pushd %{glibc_sysroot}%{_prefix}/%{_lib}/ +$GCC -r -nostdlib -o libpthread.o -Wl,--whole-archive ./libpthread.a +rm libpthread.a +ar rcs libpthread.a libpthread.o +rm libpthread.o +popd + +############################################################################## +# Build an empty libpthread_nonshared.a for compatiliby with applications +# that have old linker scripts that reference this file. We ship this only +# in compat-libpthread-nonshared sub-package. +############################################################################## +ar cr %{glibc_sysroot}%{_prefix}/%{_lib}/libpthread_nonshared.a + +############################################################################## +# Beyond this point in the install process we no longer modify the set of +# installed files, with one exception, for auxarches we cleanup the file list +# at the end and remove files which we don't intend to ship. We need the file +# list to effect a proper cleanup, and so it happens last. +############################################################################## + +############################################################################## +# Build the file lists used for describing the package and subpackages. +############################################################################## +# There are several main file lists (and many more for +# the langpack sub-packages (langpack-${lang}.filelist)): +# * master.filelist +# - Master file list from which all other lists are built. +# * glibc.filelist +# - Files for the glibc packages. +# * common.filelist +# - Flies for the common subpackage. +# * utils.filelist +# - Files for the utils subpackage. +# * nscd.filelist +# - Files for the nscd subpackage. +# * devel.filelist +# - Files for the devel subpackage. +# * headers.filelist +# - Files for the headers subpackage. +# * static.filelist +# - Files for the static subpackage. +# * libnsl.filelist +# - Files for the libnsl subpackage +# * nss_db.filelist +# * nss_hesiod.filelist +# - File lists for nss_* NSS module subpackages. +# * nss-devel.filelist +# - File list with the .so symbolic links for NSS packages. +# * compat-libpthread-nonshared.filelist. +# - File list for compat-libpthread-nonshared subpackage. +# * debuginfo.filelist +# - Files for the glibc debuginfo package. +# * debuginfocommon.filelist +# - Files for the glibc common debuginfo package. +# + +# Create the main file lists. This way we can append to any one of them later +# wihtout having to create it. Note these are removed at the start of the +# install phase. +touch master.filelist +touch glibc.filelist +touch common.filelist +touch utils.filelist +touch nscd.filelist +touch devel.filelist +touch headers.filelist +touch static.filelist +touch libnsl.filelist +touch nss_db.filelist +touch nss_hesiod.filelist +touch nss-devel.filelist +touch compat-libpthread-nonshared.filelist +touch debuginfo.filelist +touch debuginfocommon.filelist + +############################################################################### +# Master file list, excluding a few things. +############################################################################### { find $RPM_BUILD_ROOT \( -type f -o -type l \) '!' -path "*/lib/debug/*" \ | sed -e "s|^${RPM_BUILD_ROOT}||" -e '\|/etc/|s|^|%%config |' \ @@ -333,221 +631,493 @@ rm -f $RPM_BUILD_ROOT%{_sbindir}/rpcinfo # primary filelist SHARE_LANG='s|.*/share/locale/\([^/_]\+\).*/LC_MESSAGES/.*\.mo|%lang(\1) &|' LIB_LANG='s|.*/lib/locale/\([^/_]\+\)|%lang(\1) &|' - # rpm does not handle %lang() tagged files hardlinked together accross + # rpm does not handle %%lang() tagged files hardlinked together accross # languages very well, temporarily disable LIB_LANG='' sed -e "$LIB_LANG" -e "$SHARE_LANG" \ - -e '\,/etc/\(localtime\|nsswitch.conf\|ld\.so\.conf\|ld\.so\.cache\|default\),d' \ + -e '\,/etc/\(localtime\|nsswitch.conf\|ld\.so\.conf\|ld\.so\.cache\|default\|rpc\|gai\.conf\),d' \ -e '\,/%{_lib}/lib\(pcprofile\|memusage\)\.so,d' \ -e '\,bin/\(memusage\|mtrace\|xtrace\|pcprofiledump\),d' -} | sort > rpm.filelist - -mkdir -p $RPM_BUILD_ROOT%{_prefix}/%{_lib} -mv -f $RPM_BUILD_ROOT/%{_lib}/lib{pcprofile,memusage}.so $RPM_BUILD_ROOT%{_prefix}/%{_lib} - -grep '%{_prefix}/include/gnu/stubs-[32164]\+\.h' < rpm.filelist >> devel.filelist || : - -grep '%{_prefix}/include' < rpm.filelist | - egrep -v '%{_prefix}/include/(linuxthreads|gnu/stubs-[32164]+\.h)' \ - > headers.filelist - -sed -i -e '\|%{_prefix}/%{_lib}/lib.*_p.a|d' \ - -e '\|%{_prefix}/include|d' \ - -e '\|%{_infodir}|d' rpm.filelist +} | sort > master.filelist + +# The master file list is now used by each subpackage to list their own +# files. We go through each package and subpackage now and create their lists. +# Each subpackage picks the files from the master list that they need. +# The order of the subpackage list generation does not matter. + +# Make the master file list read-only after this point to avoid accidental +# modification. +chmod 0444 master.filelist + +############################################################################### +# glibc +############################################################################### + +# Add all files with the following exceptions: +# - The info files '%%{_infodir}/dir' +# - The partial (lib*_p.a) static libraries, include files. +# - The static files, objects, unversioned DSOs, and nscd. +# - The bin, locale, some sbin, and share. +# - The use of [^gi] is meant to exclude all files except glibc_post_upgrade, +# and iconvconfig, which we want in the main packages. +# - All the libnss files (we add back the ones we want later). +# - All bench test binaries. +# - The aux-cache, since it's handled specially in the files section. +# - The build-locale-archive binary since it's in the common package. +cat master.filelist \ + | grep -v \ + -e '%{_infodir}' \ + -e '%{_libdir}/lib.*_p.a' \ + -e '%{_prefix}/include' \ + -e '%{_libdir}/lib.*\.a' \ + -e '%{_libdir}/.*\.o' \ + -e '%{_libdir}/lib.*\.so' \ + -e 'nscd' \ + -e '%{_prefix}/bin' \ + -e '%{_prefix}/lib/locale' \ + -e '%{_prefix}/sbin/[^gi]' \ + -e '%{_prefix}/share' \ + -e '/var/db/Makefile' \ + -e '/libnss_.*\.so[0-9.]*$' \ + -e '/libnsl' \ + -e 'glibc-benchtests' \ + -e 'aux-cache' \ + -e 'build-locale-archive' \ + > glibc.filelist + +cat master.filelist + +# Add specific files: +# - The nss_files, nss_compat, and nss_db files. +# - The libmemusage.so and libpcprofile.so used by utils. +cat master.filelist | grep -e '/libnss_' |grep -E -e "(\.so\.[0-9.]+|-[0-9.]+\.so)$" \ + >> glibc.filelist + +cat master.filelist | grep -e "libmemusage.so" >> glibc.filelist || true +cat master.filelist | grep -e "libpcprofile.so" >> glibc.filelist || true + +cat glibc.filelist +############################################################################### +# glibc-devel +############################################################################### + +%if %{with docs} +# Put the info files into the devel file list, but exclude the generated dir. +grep '%{_infodir}' master.filelist | grep -v '%{_infodir}/dir' > devel.filelist +%endif -grep '%{_prefix}/%{_lib}/lib.*\.a' < rpm.filelist \ - | grep '/lib\(\(c\|pthread\|nldbl\)_nonshared\|bsd\(\|-compat\)\|g\|ieee\|mcheck\|rpcsvc\)\.a$' \ +# Put some static files into the devel package. +grep '%{_libdir}/lib.*\.a' master.filelist \ + | grep '/lib\(\(c\|pthread\|nldbl\|mvec\)_nonshared\|g\|ieee\|mcheck\)\.a$' \ >> devel.filelist -grep '%{_prefix}/%{_lib}/lib.*\.a' < rpm.filelist \ - | grep -v '/lib\(\(c\|pthread\|nldbl\)_nonshared\|bsd\(\|-compat\)\|g\|ieee\|mcheck\|rpcsvc\)\.a$' \ - > static.filelist -grep '%{_prefix}/%{_lib}/.*\.o' < rpm.filelist >> devel.filelist -grep '%{_prefix}/%{_lib}/lib.*\.so' < rpm.filelist >> devel.filelist - -sed -i -e '\|%{_prefix}/%{_lib}/lib.*\.a|d' \ - -e '\|%{_prefix}/%{_lib}/.*\.o|d' \ - -e '\|%{_prefix}/%{_lib}/lib.*\.so|d' \ - -e '\|%{_prefix}/%{_lib}/linuxthreads|d' \ - -e '\|nscd|d' rpm.filelist -grep '%{_prefix}/bin' < rpm.filelist >> common.filelist -#grep '%{_prefix}/lib/locale' < rpm.filelist | grep -v /locale-archive.tmpl >> common.filelist -#grep '%{_prefix}/libexec/pt_chown' < rpm.filelist >> common.filelist -grep '%{_prefix}/sbin/[^gi]' < rpm.filelist >> common.filelist -grep '%{_prefix}/share' < rpm.filelist | \ - grep -v '%{_prefix}/share/zoneinfo' >> common.filelist +# Put all of the object files and *.so (not the versioned ones) into the +# devel package. +grep '%{_libdir}/.*\.o' < master.filelist >> devel.filelist +grep '%{_libdir}/lib.*\.so' < master.filelist >> devel.filelist +# The exceptions are: +# - libmemusage.so and libpcprofile.so in glibc used by utils. +# - libnss_*.so which are in nss-devel. +sed -i -e '\,libmemusage.so,d' \ + -e '\,libpcprofile.so,d' \ + -e '\,/libnss_[a-z]*\.so$,d' \ + devel.filelist + +############################################################################### +# glibc-headers +############################################################################### + +# The glibc-headers package includes only common files which are identical +# across all multilib packages. We must keep gnu/stubs.h and gnu/lib-names.h +# in the glibc-headers package, but the -32, -64, -64-v1, and -64-v2 versions +# go into the development packages. +grep '%{_prefix}/include/gnu/stubs-.*\.h$' < master.filelist >> devel.filelist || : +grep '%{_prefix}/include/gnu/lib-names-.*\.h$' < master.filelist >> devel.filelist || : +# Put the include files into headers file list. +grep '%{_prefix}/include' < master.filelist \ + | grep -v -e '%{_prefix}/include/gnu/stubs-.*\.h$' \ + | grep -v -e '%{_prefix}/include/gnu/lib-names-.*\.h$' \ + > headers.filelist + +############################################################################### +# glibc-static +############################################################################### + +# Put the rest of the static files into the static package. +grep '%{_libdir}/lib.*\.a' < master.filelist \ + | grep -v '/lib\(\(c\|pthread\|nldbl\|mvec\)_nonshared\|g\|ieee\|mcheck\)\.a$' \ + > static.filelist -sed -i -e '\|%{_prefix}/bin|d' \ - -e '\|%{_prefix}/lib/locale|d' \ - -e '\|%{_prefix}/sbin/[^gi]|d' \ - -e '\|%{_prefix}/share|d' rpm.filelist +############################################################################### +# glibc-common +############################################################################### + +# All of the bin and certain sbin files go into the common package except +# glibc_post_upgrade.* and iconvconfig which need to go in glibc. Likewise +# nscd is excluded because it goes in nscd. +grep '%{_prefix}/bin' master.filelist >> common.filelist +grep '%{_prefix}/sbin/[^gi]' master.filelist \ + | grep -v 'nscd' >> common.filelist +# All of the files under share go into the common package since they should be +# multilib-independent. +# Exceptions: +# - The actual share directory, not owned by us. +# - The info files which go in devel, and the info directory. +grep '%{_prefix}/share' master.filelist \ + | grep -v \ + -e '%{_prefix}/share/info/libc.info.*' \ + -e '%%dir %{prefix}/share/info' \ + -e '%%dir %{prefix}/share' \ + >> common.filelist + +# Add the binary to build locales to the common subpackage. +echo '%{_prefix}/sbin/build-locale-archive' >> common.filelist -> nosegneg.filelist +############################################################################### +# nscd +############################################################################### -echo '%{_prefix}/sbin/build-locale-archive' >> common.filelist +# The nscd binary must go into the nscd subpackage. echo '%{_prefix}/sbin/nscd' > nscd.filelist +############################################################################### +# glibc-utils +############################################################################### + +# Add the utils scripts and programs to the utils subpackage. cat > utils.filelist < nss_$module.filelist +done + +############################################################################### +# nss-devel +############################################################################### + +# Symlinks go into the nss-devel package (instead of the main devel +# package). +grep '/libnss_[a-z]*\.so$' master.filelist > nss-devel.filelist + +############################################################################### +# libnsl +############################################################################### + +# Prepare the libnsl-related file lists. +grep '/libnsl-[0-9.]*.so$' master.filelist > libnsl.filelist +test $(wc -l < libnsl.filelist) -eq 1 + +############################################################################### +# compat-libpthread-nonshared +############################################################################### +echo "%{_libdir}/libpthread_nonshared.a" >> compat-libpthread-nonshared.filelist + +############################################################################### +# glibc-debuginfocommon, and glibc-debuginfo +############################################################################### + +find_debuginfo_args='--strict-build-id -g' +%ifarch %{debuginfocommonarches} +find_debuginfo_args="$find_debuginfo_args \ + -l common.filelist \ + -l utils.filelist \ + -l nscd.filelist \ + -p '.*/(sbin|libexec)/.*' \ + -o debuginfocommon.filelist \ + -l nss_db.filelist -l nss_hesiod.filelist \ + -l libnsl.filelist -l glibc.filelist \ +%if %{with benchtests} + -l benchtests.filelist +%endif + " +%endif + +/usr/lib/rpm/find-debuginfo.sh $find_debuginfo_args -o debuginfo.filelist + +# List all of the *.a archives in the debug directory. +list_debug_archives() +{ + local dir=%{_prefix}/lib/debug%{_libdir} + find %{glibc_sysroot}$dir -name "*.a" -printf "$dir/%%P\n" +} + +%ifarch %{debuginfocommonarches} + +# Remove the source files from the common package debuginfo. +sed -i '\#^%{glibc_sysroot}%{_prefix}/src/debug/#d' debuginfocommon.filelist + +# Create a list of all of the source files we copied to the debug directory. +find %{glibc_sysroot}%{_prefix}/src/debug \ + \( -type d -printf '%%%%dir ' \) , \ + -printf '%{_prefix}/src/debug/%%P\n' > debuginfocommon.sources + +%ifarch %{biarcharches} + +# Add the source files to the core debuginfo package. +cat debuginfocommon.sources >> debuginfo.filelist + +%else + +%ifarch %{ix86} +%define basearch i686 +%endif +%ifarch sparc sparcv9 +%define basearch sparc +%endif + +# The auxarches get only these few source files. +auxarches_debugsources=\ +'/(generic|linux|%{basearch}|nptl(_db)?)/|/%{glibcsrcdir}/build|/dl-osinfo\.h' + +# Place the source files into the core debuginfo pakcage. +grep "$auxarches_debugsources" debuginfocommon.sources >> debuginfo.filelist + +# Remove the source files from the common debuginfo package. +grep -v "$auxarches_debugsources" \ + debuginfocommon.sources >> debuginfocommon.filelist + +%endif # %%{biarcharches} + +# Add the list of *.a archives in the debug directory to +# the common debuginfo package. +list_debug_archives >> debuginfocommon.filelist + +%endif # %%{debuginfocommonarches} + +# Remove some common directories from the common package debuginfo so that we +# don't end up owning them. +exclude_common_dirs() +{ + exclude_dirs="%{_prefix}/src/debug" + exclude_dirs="$exclude_dirs $(echo %{_prefix}/lib/debug{,/%{_lib},/bin,/sbin})" + exclude_dirs="$exclude_dirs $(echo %{_prefix}/lib/debug%{_prefix}{,/%{_lib},/libexec,/bin,/sbin})" + + for d in $(echo $exclude_dirs | sed 's/ /\n/g'); do + sed -i "\|^%%dir $d/\?$|d" $1 + done +} + +%ifarch %{debuginfocommonarches} +exclude_common_dirs debuginfocommon.filelist +%endif +exclude_common_dirs debuginfo.filelist + +# %endif # 0%%{?_enable_debug_packages} + + +cat master.filelist | grep '/libnss_[a-z]*\.so$' master.filelist >> devel.filelist + +# remove nss db Makefile +rm %{glibc_sysroot}/var/db/Makefile +# remove libnsl +rm %{glibc_sysroot}/lib/libnsl* + +############################################################################## +# Delete files that we do not intended to ship with the auxarch. +# This is the only place where we touch the installed files after generating +# the file lists. +############################################################################## +%ifarch %{auxarches} +echo Cutting down the list of unpackaged files +sed -e '/%%dir/d;/%%config/d;/%%verify/d;s/%%lang([^)]*) //;s#^/*##' \ + common.filelist devel.filelist static.filelist headers.filelist \ + utils.filelist nscd.filelist \ +%ifarch %{debuginfocommonarches} + debuginfocommon.filelist \ +%endif + | (cd %{glibc_sysroot}; xargs --no-run-if-empty rm -f 2> /dev/null || :) +%endif # %%{auxarches} + +############################################################################## +# Run the glibc testsuite +############################################################################## +%check +%if %{with testsuite} + +# Run the glibc tests. If any tests fail to build we exit %%check with +# an error, otherwise we print the test failure list and the failed +# test output and continue. Write to standard error to avoid +# synchronization issues with make and shell tracing output if +# standard output and standard error are different pipes. +run_tests () { + # This hides a test suite build failure, which should be fatal. We + # check "Summary of test results:" below to verify that all tests + # were built and run. + make %{?_smp_mflags} -O check |& tee rpmbuild.check.log >&2 + test -n tests.sum + if ! grep -q '^Summary of test results:$' rpmbuild.check.log ; then + echo "FAIL: test suite build of target: $(basename "$(pwd)")" >& 2 + exit 1 + fi + set +x + grep -v ^PASS: tests.sum > rpmbuild.tests.sum.not-passing || true + if test -n rpmbuild.tests.sum.not-passing ; then + echo ===================FAILED TESTS===================== >&2 + echo "Target: $(basename "$(pwd)")" >& 2 + cat rpmbuild.tests.sum.not-passing >&2 + while read failed_code failed_test ; do + for suffix in out test-result ; do + if test -e "$failed_test.$suffix"; then + echo >&2 + echo "=====$failed_code $failed_test.$suffix=====" >&2 + cat -- "$failed_test.$suffix" >&2 + echo >&2 + fi + done + done &2 + cat misc/tst-syscall-list.out >&2 + set -x +} # Increase timeouts export TIMEOUTFACTOR=16 parent=$$ echo ====================TESTING========================= -cd build-%{nptl_target_cpu}-linuxnptl -( make %{?_smp_mflags} -k check PARALLELMFLAGS=-s 2>&1 - sleep 10s - teepid="`ps -eo ppid,pid,command | awk '($1 == '${parent}' && $3 ~ /^tee/) { print $2 }'`" - [ -n "$teepid" ] && kill $teepid -) | tee check.log || : -cd .. -echo ====================TESTING DETAILS================= -for i in `sed -n 's|^.*\*\*\* \[\([^]]*\.out\)\].*$|\1|p' build-*-linux*/check.log`; do - echo =====$i===== - cat $i || : - echo ============ -done + +# Default libraries. +pushd build-%{target} +run_tests +popd + + echo ====================TESTING END===================== PLTCMD='/^Relocation section .*\(\.rela\?\.plt\|\.rela\.IA_64\.pltoff\)/,/^$/p' echo ====================PLT RELOCS LD.SO================ -readelf -Wr $RPM_BUILD_ROOT/%{_lib}/ld-*.so | sed -n -e "$PLTCMD" +readelf -Wr %{glibc_sysroot}/%{_lib}/ld-*.so | sed -n -e "$PLTCMD" echo ====================PLT RELOCS LIBC.SO============== -readelf -Wr $RPM_BUILD_ROOT/%{_lib}/libc-*.so | sed -n -e "$PLTCMD" +readelf -Wr %{glibc_sysroot}/%{_lib}/libc-*.so | sed -n -e "$PLTCMD" echo ====================PLT RELOCS END================== -%endif +# Finally, check if valgrind runs with the new glibc. +# We want to fail building if valgrind is not able to run with this glibc so +# that we can then coordinate with valgrind to get it fixed before we update +# glibc. +pushd build-%{target} -pushd $RPM_BUILD_ROOT/usr/%{_lib}/ -gcc -r -nostdlib -o libpthread.o -Wl,--whole-archive ./libpthread.a -rm libpthread.a -ar rcs libpthread.a libpthread.o -rm libpthread.o +# Show the auxiliary vector as seen by the new library +# (even if we do not perform the valgrind test). +LD_SHOW_AUXV=1 elf/ld.so --library-path .:elf:nptl:dlfcn /bin/true + +%if %{with valgrind} +elf/ld.so --library-path .:elf:nptl:dlfcn \ + /usr/bin/valgrind --error-exitcode=1 \ + elf/ld.so --library-path .:elf:nptl:dlfcn /usr/bin/true +%endif popd +%endif # %%{run_glibc_tests} -%ifarch %{auxarches} +%pre -p +-- Check that the running kernel is new enough +required = '%{enablekernel}' +rel = posix.uname("%r") +if rpm.vercmp(rel, required) < 0 then + error("FATAL: kernel too old", 0) +end -echo Cutting down the list of unpackaged files ->> debuginfocommon.filelist -sed -e '/%%dir/d;/%%config/d;/%%verify/d;s/%%lang([^)]*) //;s#^/*##' \ - common.filelist devel.filelist static.filelist headers.filelist \ - utils.filelist nscd.filelist debuginfocommon.filelist | -(cd $RPM_BUILD_ROOT; xargs --no-run-if-empty rm -f 2> /dev/null || :) +%if %{with docs} +%post devel +/sbin/install-info %{_infodir}/libc.info.gz %{_infodir}/dir > /dev/null 2>&1 || : +%endif -%else +%pre headers +# this used to be a link and it is causing nightmares now +if [ -L %{_prefix}/include/scsi ] ; then + rm -f %{_prefix}/include/scsi +fi -mkdir -p $RPM_BUILD_ROOT/var/{db,run}/nscd -touch $RPM_BUILD_ROOT/var/{db,run}/nscd/{passwd,group,hosts,services} -touch $RPM_BUILD_ROOT/var/run/nscd/{socket,nscd.pid} +%if %{with docs} +%preun devel +if [ "$1" = 0 ]; then + /sbin/install-info --delete %{_infodir}/libc.info.gz %{_infodir}/dir > /dev/null 2>&1 || : +fi %endif -install -m 700 ../build-locale-archive $RPM_BUILD_ROOT/usr/sbin/build-locale-archive - -mkdir -p $RPM_BUILD_ROOT/var/cache/ldconfig -> $RPM_BUILD_ROOT/var/cache/ldconfig/aux-cache +%pre -n nscd +getent group nscd >/dev/null || /usr/sbin/groupadd -g 28 -r nscd +getent passwd nscd >/dev/null || + /usr/sbin/useradd -M -o -r -d / -s /sbin/nologin \ + -c "NSCD Daemon" -u 28 -g nscd nscd %post -p /sbin/ldconfig %postun -p /sbin/ldconfig -%pre headers -# this used to be a link and it is causing nightmares now -if [ -L %{_prefix}/include/scsi ] ; then - rm -f %{_prefix}/include/scsi -fi +%post -n glibc-devel -p /sbin/ldconfig -%post utils -p /sbin/ldconfig +%postun -n glibc-devel -p /sbin/ldconfig -%postun utils -p /sbin/ldconfig +%post -n nscd +%systemd_post nscd.service -%pre -n nscd -/usr/sbin/useradd -M -o -r -d / -s /sbin/nologin \ - -c "NSCD Daemon" -u 28 nscd > /dev/null 2>&1 || : +%preun -n nscd +%systemd_preun nscd.service %postun -n nscd -if [ $1 = 0 ] ; then +if test $1 = 0; then /usr/sbin/userdel nscd > /dev/null 2>&1 || : fi -if [ "$1" -ge "1" ]; then - service nscd condrestart > /dev/null 2>&1 || : -fi - +%systemd_postun_with_restart nscd.service -%files -f build-%{name}-%{version}/rpm.filelist -%defattr(-,root,root) -%verify(not md5 size mtime) %config(noreplace) /etc/localtime +%files -f glibc.filelist +%dir %{_prefix}/%{_lib}/audit +%ifarch s390x +/lib/ld64.so.1 +%endif %verify(not md5 size mtime) %config(noreplace) /etc/nsswitch.conf %verify(not md5 size mtime) %config(noreplace) /etc/ld.so.conf +%verify(not md5 size mtime) %config(noreplace) /etc/rpc %dir /etc/ld.so.conf.d %dir %{_prefix}/libexec/getconf -%dir %{_prefix}/%{_lib}/gconv +%dir %{_libdir}/gconv %dir %attr(0700,root,root) /var/cache/ldconfig %attr(0600,root,root) %verify(not md5 size mtime) %ghost %config(missingok,noreplace) /var/cache/ldconfig/aux-cache %attr(0644,root,root) %verify(not md5 size mtime) %ghost %config(missingok,noreplace) /etc/ld.so.cache -%license COPYING COPYING.LIB LICENSES - +%doc %{glibcsrcdir}/README %{glibcsrcdir}/NEWS %{glibcsrcdir}/INSTALL %{glibcsrcdir}/elf/rtld-debugger-interface.txt +# If rpm doesn't support %%license, then use %%doc instead. +%{!?_licensedir:%global license %%doc} +%license %{glibcsrcdir}/COPYING %{glibcsrcdir}/COPYING.LIB %{glibcsrcdir}/LICENSES %ifnarch %{auxarches} -%files -f build-%{name}-%{version}/common.filelist common -%defattr(-,root,root) -%dir %{_prefix}/lib/locale -%dir %attr(755,root,root) /etc/default -%verify(not md5 size mtime) %config(noreplace) /etc/default/nss +%files -f common.filelist common +%doc %{glibcsrcdir}/documentation/README.timezone -%files -f build-%{name}-%{version}/devel.filelist devel -%defattr(-,root,root) +%files -f devel.filelist devel -%files -f build-%{name}-%{version}/static.filelist static -%defattr(-,root,root) +%files -f static.filelist static -%files -f build-%{name}-%{version}/headers.filelist headers -%defattr(-,root,root) +%files -f headers.filelist headers -%files -f build-%{name}-%{version}/utils.filelist utils -%defattr(-,root,root) +%files -f utils.filelist utils -%files -f build-%{name}-%{version}/nscd.filelist -n nscd -%defattr(-,root,root) +%files -f nscd.filelist -n nscd %config(noreplace) /etc/nscd.conf %dir %attr(0755,root,root) /var/run/nscd %dir %attr(0755,root,root) /var/db/nscd +/lib/systemd/system/nscd.service +#/lib/systemd/system/nscd.socket %attr(0644,root,root) %verify(not md5 size mtime) %ghost %config(missingok,noreplace) /var/run/nscd/nscd.pid %attr(0666,root,root) %verify(not md5 size mtime) %ghost %config(missingok,noreplace) /var/run/nscd/socket %attr(0600,root,root) %verify(not md5 size mtime) %ghost %config(missingok,noreplace) /var/run/nscd/passwd @@ -561,6 +1131,11 @@ fi %ghost %config(missingok,noreplace) /etc/sysconfig/nscd %endif -%files doc -%defattr(-,root,root) -%{_docdir}/%{name}-%{version} +%if 0%{?_enable_debug_packages} +%files debuginfo -f debuginfo.filelist +%ifarch %{debuginfocommonarches} +%ifnarch %{auxarches} +#%%files debuginfo-common -f debuginfocommon.filelist +%endif +%endif +%endif diff --git a/ubuntu-2.25.6-git-updates.diff b/ubuntu-2.25.6-git-updates.diff deleted file mode 100644 index eaba5e3..0000000 --- a/ubuntu-2.25.6-git-updates.diff +++ /dev/null @@ -1,14297 +0,0 @@ -GIT update of git://sourceware.org/git/glibc.git/release/2.25/master from glibc-2.25 - -diff --git a/ChangeLog b/ChangeLog -index f140ee67de..a3db9c09f2 100644 ---- a/ChangeLog -+++ b/ChangeLog -@@ -1,3 +1,750 @@ -+2017-12-30 Aurelien Jarno -+ Dmitry V. Levin -+ -+ [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 -+ -+ [BZ #22627] -+ * elf/dl-load.c (_dl_init_paths): Remove _dl_dst_substitute preparatory -+ code and invocation. -+ -+2017-12-14 Florian Weimer -+ -+ [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 -+ -+ [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 -+ -+ Add array_length and array_end macros. -+ * include/array_length.h: New file. -+ -+2017-12-12 James Clarke -+ -+ * sysdeps/unix/sysv/linux/ia64/ipc_priv.h: New file defining -+ __IPC_64 to 0 to avoid IPC_64 being set. -+ -+2017-11-02 Florian Weimer -+ -+ [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 -+ -+ [BZ #22332] -+ * posix/glob.c (__glob): Fix buffer overflow during GLOB_TILDE -+ unescaping. -+ -+2017-10-21 Florian Weimer -+ -+ * 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 -+ -+ [BZ #22320] -+ CVE-2017-15670 -+ * posix/glob.c (__glob): Fix one-byte overflow. -+ -+2017-09-08 Adhemerval Zanella -+ -+ [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 -+ -+ [BZ #18822] -+ * sysdeps/unix/sysv/linux/i386/glob64.c (__old_glob64): Add -+ libc_hidden_proto and libc_hidden_def. -+ -+2017-03-14 Adhemerval Zanella -+ -+ [BZ #21232] -+ * sysdeps/unix/sysv/linux/mips/mips64/n64/posix_fadvise64.c: Add -+ posix_fadvise64 weak_alias for static build. -+ -+2017-10-23 Adhemerval Zanella -+ -+ * sysdeps/unix/sysv/linux/spawni.c (__spawnix): Use 0 instead of -+ WNOHANG in waitpid call. -+ -+2017-10-20 Adhemerval Zanella -+ -+ [BZ #22273] -+ * sysdeps/unix/sysv/linux/spawni.c (__spawnix): Handle the case where -+ the auxiliary process is terminated by a signal before calling _exit -+ or execve. -+ -+2017-08-09 Andreas Schwab -+ -+ * nptl/Makefile (tests) [$(build-shared) = yes]: Add -+ tst-compat-forwarder. -+ (modules-names): Add tst-compat-forwarder-mod. -+ ($(objpfx)tst-compat-forwarder): Depend on -+ $(objpfx)tst-compat-forwarder-mod.so. -+ * nptl/tst-compat-forwarder.c: New file. -+ * nptl/tst-compat-forwarder-mod.c: New file. -+ -+2017-08-09 Andreas Schwab -+ -+ * sysdeps/unix/sysv/linux/s390/pt-longjmp.c: Update reference to -+ renamed alias. -+ -+2017-08-08 Andreas Schwab -+ -+ [BZ #21041] -+ * nptl/pt-longjmp.c (longjmp, siglongjmp): Don't use IFUNC resolver. -+ * nptl/pt-system.c (system): Likewise. -+ -+2017-10-13 James Clarke -+ -+ * sysdeps/powerpc/powerpc32/dl-machine.h (elf_machine_rela): -+ Assign sym_map to be map for local symbols, as TLS relocations -+ use sym_map to determine whether the symbol is defined and to -+ extract the TLS information. -+ * sysdeps/sparc/sparc32/dl-machine.h (elf_machine_rela): Likewise. -+ * sysdeps/sparc/sparc64/dl-machine.h (elf_machine_rela): Likewise. -+ -+2017-10-19 Joseph Myers -+ -+ [BZ #22322] -+ * sysdeps/mips/bits/long-double.h: Move to .... -+ * sysdeps/mips/ieee754/bits/long-double.h: ... here. -+ -+2017-10-22 H.J. Lu -+ -+ [BZ #21265] -+ * sysdeps/x86/cpu-features-offsets.sym (XSAVE_STATE_SIZE_OFFSET): -+ New. -+ * sysdeps/x86/cpu-features.c: Include . -+ (get_common_indeces): Set xsave_state_size and -+ bit_arch_XSAVEC_Usable if needed. -+ (init_cpu_features): Remove bit_arch_Use_dl_runtime_resolve_slow -+ and bit_arch_Use_dl_runtime_resolve_opt. -+ * sysdeps/x86/cpu-features.h (bit_arch_Use_dl_runtime_resolve_opt): -+ Removed. -+ (bit_arch_Use_dl_runtime_resolve_slow): Likewise. -+ (bit_arch_Prefer_No_AVX512): Updated. -+ (bit_arch_MathVec_Prefer_No_AVX512): Likewise. -+ (bit_arch_XSAVEC_Usable): New. -+ (STATE_SAVE_OFFSET): Likewise. -+ (STATE_SAVE_MASK): Likewise. -+ [__ASSEMBLER__]: Include . -+ (cpu_features): Add xsave_state_size. -+ (index_arch_Use_dl_runtime_resolve_opt): Removed. -+ (index_arch_Use_dl_runtime_resolve_slow): Likewise. -+ (index_arch_XSAVEC_Usable): New. -+ * sysdeps/x86_64/dl-machine.h (elf_machine_runtime_setup): -+ Replace _dl_runtime_resolve_sse, _dl_runtime_resolve_avx, -+ _dl_runtime_resolve_avx_slow, _dl_runtime_resolve_avx_opt, -+ _dl_runtime_resolve_avx512 and _dl_runtime_resolve_avx512_opt -+ with _dl_runtime_resolve_fxsave, _dl_runtime_resolve_xsave and -+ _dl_runtime_resolve_xsavec. -+ * sysdeps/x86_64/dl-trampoline.S (DL_RUNTIME_UNALIGNED_VEC_SIZE): -+ Removed. -+ (DL_RUNTIME_RESOLVE_REALIGN_STACK): Check STATE_SAVE_ALIGNMENT -+ instead of VEC_SIZE. -+ (REGISTER_SAVE_BND0): Removed. -+ (REGISTER_SAVE_BND1): Likewise. -+ (REGISTER_SAVE_BND3): Likewise. -+ (REGISTER_SAVE_RAX): Always defined to 0. -+ (VMOV): Removed. -+ (_dl_runtime_resolve_avx): Likewise. -+ (_dl_runtime_resolve_avx_slow): Likewise. -+ (_dl_runtime_resolve_avx_opt): Likewise. -+ (_dl_runtime_resolve_avx512): Likewise. -+ (_dl_runtime_resolve_avx512_opt): Likewise. -+ (_dl_runtime_resolve_sse): Likewise. -+ (_dl_runtime_resolve_sse_vex): Likewise. -+ (USE_FXSAVE): New. -+ (_dl_runtime_resolve_fxsave): Likewise. -+ (USE_XSAVE): Likewise. -+ (_dl_runtime_resolve_xsave): Likewise. -+ (USE_XSAVEC): Likewise. -+ (_dl_runtime_resolve_xsavec): Likewise. -+ * sysdeps/x86_64/dl-trampoline.h (_dl_runtime_resolve_avx512): -+ Removed. -+ (_dl_runtime_resolve_avx512_opt): Likewise. -+ (_dl_runtime_resolve_avx): Likewise. -+ (_dl_runtime_resolve_avx_opt): Likewise. -+ (_dl_runtime_resolve_sse): Likewise. -+ (_dl_runtime_resolve_sse_vex): Likewise. -+ (_dl_runtime_resolve_fxsave): New. -+ (_dl_runtime_resolve_xsave): Likewise. -+ (_dl_runtime_resolve_xsavec): Likewise. -+ -+2017-10-19 H.J. Lu -+ -+ * sysdeps/x86_64/Makefile (tests): Add tst-sse, tst-avx and -+ tst-avx512. -+ (test-extras): Add tst-avx-aux and tst-avx512-aux. -+ (extra-test-objs): Add tst-avx-aux.o and tst-avx512-aux.o. -+ (modules-names): Add tst-ssemod, tst-avxmod and tst-avx512mod. -+ ($(objpfx)tst-sse): New rule. -+ ($(objpfx)tst-avx): Likewise. -+ ($(objpfx)tst-avx512): Likewise. -+ (CFLAGS-tst-avx-aux.c): New. -+ (CFLAGS-tst-avxmod.c): Likewise. -+ (CFLAGS-tst-avx512-aux.c): Likewise. -+ (CFLAGS-tst-avx512mod.c): Likewise. -+ * sysdeps/x86_64/tst-avx-aux.c: New file. -+ * sysdeps/x86_64/tst-avx.c: Likewise. -+ * sysdeps/x86_64/tst-avx512-aux.c: Likewise. -+ * sysdeps/x86_64/tst-avx512.c: Likewise. -+ * sysdeps/x86_64/tst-avx512mod.c: Likewise. -+ * sysdeps/x86_64/tst-avxmod.c: Likewise. -+ * sysdeps/x86_64/tst-sse.c: Likewise. -+ * sysdeps/x86_64/tst-ssemod.c: Likewise. -+ -+2017-07-19 DJ Delorie -+ -+ [BZ #21654] -+ * grp/grp-merge.c (libc_hidden_def): Fix cast-after-dereference. -+ -+2017-07-14 DJ Delorie -+ -+ [BZ #21654] -+ * grp/grp_merge.c (__copy_grp): Align char** to minimum pointer -+ alignment not char alignment. -+ (__merge_grp): Likewise. -+ -+2017-08-22 Joseph Myers -+ -+ [BZ #21987] -+ * sysdeps/unix/sysv/linux/sparc/bits/long-double.h: Remove file -+ and copy to ... -+ * sysdeps/unix/sysv/linux/sparc/sparc32/bits/long-double.h: -+ ... here. -+ * sysdeps/unix/sysv/linux/sparc/sparc64/bits/long-double.h: -+ ... and here. -+ -+2017-09-11 H.J. Lu -+ Florian Weimer -+ -+ * configure.ac (find_cxx_header): Suppress compiler error message. -+ * configure: Regenerated. -+ -+ [BZ #21573] -+ * Makerules [$(c++-bits-std_abs-h) != ""] (before-compile): Add -+ $(common-objpfx)bits/std_abs.h. -+ [$(c++-bits-std_abs-h) != ""] ($(common-objpfx)bits/std_abs.h): -+ New target. -+ * config.make.in (c++-bits-std_abs-h): New. -+ * configure.ac (find_cxx_header): Use "\,$1," with sed. -+ (CXX_BITS_STD_ABS_H): New. -+ (AC_SUBST(CXX_BITS_STD_ABS_H)): Likewise. -+ * configure: Regenerated. -+ -+2017-09-11 H.J. Lu -+ -+ [BZ #21982] -+ * string/stratcliff.c (do_test): Declare size, nchars, inner, -+ middle and outer with size_t instead of int. Repleace %d and -+ %Zd with %zu in printf. Update "MAX (0, nchars - 128)" and -+ "MAX (outer, nchars - 64)" to support unsigned outer and -+ nchars. Also exit loop when outer == 0. -+ -+2017-09-07 H.J. Lu -+ -+ * resolv/tst-resolv-qtypes.c (domain): Changed to -+ "const char domain[] =". -+ -+2017-08-31 H.J. Lu -+ -+ [BZ #22051] -+ * Makerules (build-module-helper-objlist): Filter out -+ $(elf-objpfx)sofini.os. -+ (build-shlib-objlist): Append $(elf-objpfx)sofini.os if it is -+ needed. -+ -+2017-07-29 Torvald Riegel -+ Carlos O'Donell -+ -+ [BZ 21778] -+ * nptl/pthread_mutex_timedlock.c (__pthread_mutex_timedlock): Update -+ oldval if the CAS fails. -+ * nptl/pthread_mutex_lock.c (__pthread_mutex_lock_full): Likewise. -+ * nptl/tst-mutex7.c: Add comments explaining template test. -+ (ROBUST, DELAY_NSEC, ROUNDS, N): New. -+ (tf, do_test): Use them. -+ * nptl/tst-mutex7robust.c: New file. -+ * nptl/Makefile (tests): Add new test. -+ -+2017-07-28 Torvald Riegel -+ Carlos O'Donell -+ -+ [BZ #21298] -+ * nptl/Makefile (tests): Add tst-rwlock20. -+ * nptl/pthread_rwlock_common.c (__pthread_rwlock_rdlock_full): Fix -+ explicit hand-over. -+ (__pthread_rwlock_wrlock_full): Likewise. -+ * nptl/tst-rwlock20.c: New file. -+ -+2017-08-21 Florian Weimer -+ -+ [BZ #21972] -+ * assert/assert.h (assert): Use static_cast (bool) for C++. -+ Use the ternary operator in the warning branch for GNU C. -+ * assert/Makefile (tests): Add tst-assert-c++, tst-assert-g++. -+ (CFLAGS-tst-assert-c++.o): Compile in C++11 mode. -+ (CFLAGS-tst-assert-g++.o): Compile in GnU C++11 mode. -+ (LDLIBS-tst-assert-c++, LDLIBS-tst-assert-g++): Link with libstdc++. -+ * assert/tst-assert-c++.cc, assert/tst-assert-g++.cc: New files. -+ -+2017-04-13 Florian Weimer -+ -+ [BZ #21361] -+ Limit EDNS buffer size to 1200 bytes. -+ * include/resolv.h (__res_nopt): Remove declaration. -+ * resolv/Makefile (tests): tst-resolv-edns. -+ (tst-resolv-edns): Link with -lresolv, -lpthread. -+ * resolv/res_mkquery.c (__res_ntop): Limit EDNS buffer size to the -+ interval [512, 1200]. -+ * resolv/res_query.c (__libc_res_nquery): Use 1200 buffer size if -+ we can resize the buffer. -+ * resolv/resolv-internal.h (RESOLV_EDNS_BUFFER_SIZE): Define. -+ (__res_nopt): Declare. -+ * resolv/tst-resolv-edns.c: New file. -+ * resolv/resolv_test.h (struct resolv_edns_info): Define. -+ (struct resolv_response_context): Add edns member. -+ * resolv/resolv_test.c (struct query_info): Add edns member. -+ (parse_query): Extract EDNS information from the query. -+ (server_thread_udp_process_one): Propagate EDNS data. -+ (server_thread_tcp_client): Likewise. -+ -+2017-08-12 John David Anglin -+ -+ [BZ 19170] -+ * sysdeps/hppa/dl-trampoline.S (_dl_runtime_resolve): Return to caller -+ if _dl_fixup fails. -+ -+2017-08-12 John David Anglin -+ Adhemerval Zanella -+ -+ [BZ #21512] -+ * sysdeps/unix/sysv/linux/aarch64/clone.S (__clone): Call exit -+ syscall instead of jump to _exit. -+ * sysdeps/unix/sysv/linux/hppa/localplt.data: Remove _exit entry. -+ -+2017-08-12 Adhemerval Zanella -+ -+ * sysdeps/unix/sysv/linux/hppa/ipc_priv.h: New file. -+ -+2017-08-12 John David Anglin -+ -+ * sysdeps/unix/sysv/linux/hppa/clone.S (__clone): Add .cfi annotation. -+ * sysdeps/unix/sysv/linux/hppa/getcontext.S (__getcontext): Likewise. -+ * sysdeps/unix/sysv/linux/hppa/pt-vfork.S (__vfork): Likewise. -+ * sysdeps/unix/sysv/linux/hppa/setcontext.S (__setcontext): Likewise. -+ -+ * sysdeps/unix/sysv/linux/hppa/getcontext.S (__getcontext): Fix stack -+ offset for r19 load. -+ -+ * sysdeps/unix/sysv/linux/hppa/setcontext.S (__setcontext): Return 0. -+ -+ * sysdeps/unix/sysv/linux/hppa/sysdep-cancel.h (PSEUDO): Fix CFA offset. -+ Use .cfi_def_cfa_offset instead of .cfi_offset. Don't record stack -+ pointer offset. Correct PIC register offset. Don't mention frame -+ related instructions in epilogue. -+ (PUSHARGS_1): Correct offset. -+ (PUSHARGS_2): Likewise. -+ (PUSHARGS_3): Likewise. -+ (PUSHARGS_4): Likewise. -+ (PUSHARGS_5): Likewise. -+ (PUSHARGS_6): Likewise. -+ (POPARGS_1): Don't mention register restore. -+ (POPARGS_2): Likewise. -+ (POPARGS_3): Likewise. -+ (POPARGS_4): Likewise. -+ (POPARGS_5): Likewise. -+ (POPARGS_6): Likewise. -+ * sysdeps/unix/sysv/linux/hppa/sysdep.h (SAVE_PIC): Don't mention -+ copy of PIC register. -+ (LOAD_PIC): Likewise don't mention restore. -+ (DO_CALL): Fix CFA offset. Use .cfi_def_cfa_offset instead of -+ .cfi_offset. Don't record stack pointer offset. Correct PIC register -+ offset. Don't mention frame related instructions in epilogue. -+ -+ [BZ 20098] -+ * sysdeps/hppa/dl-fptr.c (_dl_read_access_allowed): New. -+ (_dl_lookup_address): Return address if it is not consistent with -+ being a linker defined function pointer. Likewise, return address -+ if address and function descriptor addresses are not accessible. -+ -+ [BZ locale/19838] -+ * sysdeps/unix/sysv/linux/hppa/bits/shm.h (SHMLBA): Set to page size. -+ -+ * nptl/allocatestack.c (allocate_stack): Align old and new guard -+ addresses to page boundaries when the stack grows up. -+ -+ * sysdeps/hppa/math-tests.h: New. -+ -+ [BZ #21016] -+ * sysdeps/hppa/nptl/bits/pthreadtypes.h: Update pthread_cond_t typedef. -+ * sysdeps/unix/sysv/linux/hppa/pthread.h: Include -+ bits/types/struct_timespec.h. -+ (PTHREAD_MUTEX_INITIALIZER): Revise define. -+ (PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP): Likewise. -+ (PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP): Likewise. -+ (PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP): Likewise. -+ (PTHREAD_RWLOCK_INITIALIZER): Likewise. -+ (PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP): Likewise. -+ (PTHREAD_COND_INITIALIZER): Likewise. -+ Remove old definitions. -+ * sysdeps/unix/sysv/linux/hppa/internaltypes.h: Delete. -+ * sysdeps/unix/sysv/linux/hppa/pthread_cond_broadcast.c: Delete. -+ * sysdeps/unix/sysv/linux/hppa/pthread_cond_destroy.c: Delete. -+ * sysdeps/unix/sysv/linux/hppa/pthread_cond_init.c: Delete. -+ * sysdeps/unix/sysv/linux/hppa/pthread_cond_signal.c: Delete. -+ * sysdeps/unix/sysv/linux/hppa/pthread_cond_wait.c: Delete. -+ -+2017-08-11 Florian Weimer -+ -+ [BZ #21242] -+ * assert/assert.h [__GNUC__ && !__STRICT_ANSI__] (assert): -+ Suppress pedantic warning resulting from statement expression. -+ (__ASSERT_FUNCTION): Add missing __extension__. -+ -+2017-08-08 Helge Deller -+ -+ [BZ #21049] -+ * sysdeps/hppa/__longjmp.c (__longjmp): Move call to CHECK_SP up -+ to avoid clobbering r26. -+ -+2017-08-06 H.J. Lu -+ -+ [BZ #21871] -+ * sysdeps/x86/cpu-features.c (init_cpu_features): Set -+ bit_arch_Use_dl_runtime_resolve_opt only with AVX512F. -+ -+2017-08-04 Aurelien Jarno -+ -+ * sysdeps/i386/i686/fpu/multiarch/libm-test-ulps: Regenerated. -+ -+2017-08-03 Aurelien Jarno -+ -+ * stdlib/getentropy.c (getentropy): Change return type to int. -+ -+2017-04-28 Tulio Magno Quites Machado Filho -+ -+ [BZ #21280] -+ * sysdeps/powerpc/power7/fpu/s_logbl.c (__logbl): Ignore the -+ signal of subnormals and adjust the exponent of power of 2 down -+ when low part has opposite sign. -+ -+2017-07-26 H.J. Lu -+ -+ [BZ #21666] -+ * misc/regexp.c (loc1): Add __attribute__ ((nocommon)); -+ (loc2): Likewise. -+ (locs): Likewise. -+ -+2017-07-12 Szabolcs Nagy -+ -+ * sysdeps/aarch64/dl-machine.h (RTLD_START_1): Change _dl_argv to the -+ hidden __GI__dl_argv symbol. -+ -+2017-07-06 Florian Weimer -+ H.J. Lu -+ -+ [BZ #21609] -+ * sysdeps/x86_64/Makefile (sysdep-dl-routines): Add tls_get_addr. -+ (gen-as-const-headers): Add rtld-offsets.sym. -+ * sysdeps/x86_64/dl-tls.c: New file. -+ * sysdeps/x86_64/rtld-offsets.sym: Likwise. -+ * sysdeps/x86_64/tls_get_addr.S: Likewise. -+ * sysdeps/x86_64/dl-tls.h: Add multiple inclusion guards. -+ * sysdeps/x86_64/tlsdesc.sym (TI_MODULE_OFFSET): New. -+ (TI_OFFSET_OFFSET): Likwise. -+ -+2017-06-14 Florian Weimer -+ -+ * sysdeps/i386/i686/multiarch/strcspn-c.c: Add IS_IN (libc) guard. -+ * sysdeps/i386/i686/multiarch/varshift.c: Likewise. -+ -+2017-03-07 Siddhesh Poyarekar -+ -+ [BZ #21209] -+ * elf/rtld.c (process_envvars): Ignore LD_HWCAP_MASK for -+ AT_SECURE processes. -+ * sysdeps/generic/unsecvars.h: Add LD_HWCAP_MASK. -+ * elf/tst-env-setuid.c (test_parent): Test LD_HWCAP_MASK. -+ (test_child): Likewise. -+ * elf/Makefile (tst-env-setuid-ENV): Add LD_HWCAP_MASK. -+ -+2017-06-19 Florian Weimer -+ -+ * elf/rtld.c (audit_list_string): New variable. -+ (audit_list): Update comment. -+ (struct audit_list_iter): Define. -+ (audit_list_iter_init, audit_list_iter_next): New function. -+ (dl_main): Use struct audit_list_iter to process audit modules. -+ (process_dl_audit): Call dso_name_valid_for_suid. -+ (process_envvars): Set audit_list_string instead of calling -+ process_dl_audit. -+ -+2017-06-19 Florian Weimer -+ -+ * elf/rtld.c (SECURE_NAME_LIMIT, SECURE_PATH_LIMIT): Define. -+ (dso_name_valid_for_suid): New function. -+ (handle_ld_preload): Likewise. -+ (dl_main): Call it. Remove alloca. -+ -+2017-06-19 Florian Weimer -+ -+ [BZ #21624] -+ CVE-2017-1000366 -+ * elf/rtld.c (process_envvars): Ignore LD_LIBRARY_PATH for -+ __libc_enable_secure. -+ -+2017-05-12 Florian Weimer -+ -+ [BZ #21386] -+ * sysdeps/nptl/fork.c (__libc_fork): Remove assertions on the -+ parent PID. The assertion in the child is incorrect with PID -+ namespaces. -+ -+2017-03-15 Joseph Myers -+ -+ * sysdeps/x86/fpu/test-math-vector-sincos.h (INIT_VEC_PTRS_LOOP): -+ Use a union when storing pointers. -+ (VECTOR_WRAPPER_fFF_2): Do not take address of integer vector and -+ cast result when passing to INIT_VEC_PTRS_LOOP. -+ (VECTOR_WRAPPER_fFF_3): Likewise. -+ (VECTOR_WRAPPER_fFF_4): Likewise. -+ -+2017-05-01 Adhemerval Zanella -+ -+ [BZ# 21182] -+ * string/test-memchr.c (do_test): Add BZ#21182 checks for address -+ near end of a page. -+ * sysdeps/i386/i686/multiarch/memchr-sse2.S (__memchr): Fix -+ overflow calculation. -+ -+2017-04-28 H.J. Lu -+ -+ [BZ #21396] -+ * sysdeps/x86/cpu-features.c (init_cpu_features): Set -+ Prefer_No_AVX512 if AVX512ER isn't available. -+ * sysdeps/x86/cpu-features.h (bit_arch_Prefer_No_AVX512): New. -+ (index_arch_Prefer_No_AVX512): Likewise. -+ * sysdeps/x86_64/multiarch/memcpy.S (__new_memcpy): Don't use -+ AVX512 version if Prefer_No_AVX512 is set. -+ * sysdeps/x86_64/multiarch/memcpy_chk.S (__memcpy_chk): -+ Likewise. -+ * sysdeps/x86_64/multiarch/memmove.S (__libc_memmove): Likewise. -+ * sysdeps/x86_64/multiarch/memmove_chk.S (__memmove_chk): -+ Likewise. -+ * sysdeps/x86_64/multiarch/mempcpy.S (__mempcpy): Likewise. -+ * sysdeps/x86_64/multiarch/mempcpy_chk.S (__mempcpy_chk): -+ Likewise. -+ * sysdeps/x86_64/multiarch/memset.S (memset): Likewise. -+ * sysdeps/x86_64/multiarch/memset_chk.S (__memset_chk): -+ Likewise. -+ -+2017-04-28 H.J. Lu -+ -+ * sysdeps/x86/cpu-features.c (init_cpu_features): Set -+ Prefer_No_VZEROUPPER if AVX512ER is available. -+ * sysdeps/x86/cpu-features.h -+ (bit_cpu_AVX512PF): New. -+ (bit_cpu_AVX512ER): Likewise. -+ (bit_cpu_AVX512CD): Likewise. -+ (bit_cpu_AVX512BW): Likewise. -+ (bit_cpu_AVX512VL): Likewise. -+ (index_cpu_AVX512PF): Likewise. -+ (index_cpu_AVX512ER): Likewise. -+ (index_cpu_AVX512CD): Likewise. -+ (index_cpu_AVX512BW): Likewise. -+ (index_cpu_AVX512VL): Likewise. -+ (reg_AVX512PF): Likewise. -+ (reg_AVX512ER): Likewise. -+ (reg_AVX512CD): Likewise. -+ (reg_AVX512BW): Likewise. -+ (reg_AVX512VL): Likewise. -+ -+2017-04-11 Adhemerval Zanella -+ -+ * posix/globtest.sh: Add cleanup routine on trap 0. -+ -+2017-04-07 H.J. Lu -+ -+ [BZ #21258] -+ * sysdeps/x86_64/dl-trampoline.S (_dl_runtime_resolve_opt): -+ Define only if _dl_runtime_resolve is defined to -+ _dl_runtime_resolve_sse_vex. -+ * sysdeps/x86_64/dl-trampoline.h (_dl_runtime_resolve_opt): -+ Fallthrough to _dl_runtime_resolve_sse_vex. -+ -+2017-04-03 Mike Frysinger -+ -+ [BZ #21253] -+ * sysdeps/unix/sysv/linux/spawni.c (__spawnix): Increase argv_size -+ slack space by 32KiB. -+ -+2017-04-03 Wladimir van der Laan -+ -+ [BZ# 21338] -+ * malloc/malloc.c: Call do_set_arena_max for M_ARENA_MAX -+ instead of incorrect do_set_arena_test -+ -+2017-03-31 Slava Barinov -+ -+ [BZ #21289] -+ * io/fts.h (fts_set): Replace __REDIRECT with __REDIRECT_NTH. -+ -+2017-03-20 Mike Frysinger -+ -+ [BZ #21275] -+ * sysdeps/unix/sysv/linux/spawni.c [__ia64__] (CLONE): Rename -+ __stack to __stackbase. -+ (STACK): Invert _STACK_GROWS_DOWN and _STACK_GROWS_UP order of -+ checks so we can include defined(__ia64__) first. -+ -+2017-03-15 Mike Frysinger -+ -+ * sysdeps/x86_64/mempcpy_chk.S (__mempcpy_chk): Check for SHARED -+ instead of PIC. -+ -+2017-03-15 John David Anglin -+ -+ * sysdeps/hppa/dl-machine.h (DL_STACK_END): Define. -+ (RTLD_START): Don't record stack end address in _dl_start_user. -+ -+2017-03-02 Florian Weimer -+ -+ [BZ #21015] -+ * manual/install.texi (Configuring and compiling): Document -+ --enable-bind-now. -+ * Makeconfig [bind-now] (LDFLAGS-lib.so): Set. -+ (build-shlib-helper): Use $(LDFLAGS-lib.so). -+ (format.lds): Likewise. -+ [bind-now] (LDFLAGS-c.so): Remove. -+ * sysdeps/x86_64/localplt.data (libm.so): matherr relocation can -+ be R_X86_64_GLOB_DAT. -+ * sysdeps/unix/sysv/linux/i386/localplt.data (libm.so): matherr -+ relocation can be R_386_GLOB_DAT. -+ * sysdeps/unix/sysv/linux/alpha/localplt.data (libm.so): matherr -+ relocaiton can be R_ALPHA_GLOB_DAT. -+ * iconvdata/Makefile [bind-now] (LDFLAGS.so): Add -Wl,-z,now. -+ -+2017-02-28 Florian Weimer -+ -+ [BZ #20257] -+ * inet/Makefile (routines): Add deadline. -+ (tests-static): Add tst-deadline. -+ * inet/net-internal.h (struct deadline_current_time) -+ (__deadline_current_time, struct deadline, __deadline_is_infinite) -+ (__deadline_elapsed, __deadline_first, __deadline_from_timeval) -+ (__deadline_to_ms, __is_timeval_valid_timeout): Declare. -+ * inet/deadline.c: New file. -+ * inet/tst-deadline.c: Likewise. -+ * sunrpc/Makefile (tests): Add tst-udp-nonblocking, -+ tst-udp-timeout, tst-udp-garbage. -+ (tst-udp-nonblocking, tst-udp-timeout): Link against libc.so -+ explicitly. -+ (tst-udp-garbage): Likewise. Also link against thread library. -+ * sunrpc/clnt_udp.c (struct cu_data): Mention in comment that the -+ struct layout is part of the ABI. -+ (clntudp_call): Rework timeout handling. -+ * sunrpc/tst-udp-garbage.c: New file. -+ * sunrpc/tst-udp-nonblocking.c: Likewise. -+ * sunrpc/tst-udp-timeout.c: Likewise. -+ -+2017-02-27 Florian Weimer -+ -+ [BZ #21115] -+ * sunrpc/clnt_udp.c (clntudp_call): Free ancillary data later. -+ * sunrpc/Makefile (tests): Add tst-udp-error. -+ (tst-udp-error): Link against libc.so explicitly. -+ * sunrpc/tst-udp-error: New file. -+ -+2017-02-08 Siddhesh Poyarekar -+ -+ [BZ #21109] -+ * elf/dl-tunable-types.h (tunable_callback_t): Accept -+ tunable_val_t as argument. -+ * elf/dl-tunables.c (__tunable_set_val): Add comment. -+ * malloc/arena.c (set_mallopt_check): Take tunable_val_t as -+ argument. -+ (DL_TUNABLE_CALLBACK_FNDECL): Likewise. -+ - 2017-02-05 Siddhesh Poyarekar - - * version.h (RELEASE): Set to "stable" -diff --git a/INSTALL b/INSTALL -index 3b3fd121b2..e77cb2d4e2 100644 ---- a/INSTALL -+++ b/INSTALL -@@ -146,6 +146,12 @@ will be used, and CFLAGS sets optimization options for the compiler. - of routines called directly from assembler are excluded from this - protection. - -+'--enable-bind-now' -+ Disable lazy binding for installed shared objects. This provides -+ additional security hardening because it enables full RELRO and a -+ read-only global offset table (GOT), at the cost of slightly -+ increased program load times. -+ - '--enable-pt_chown' - The file 'pt_chown' is a helper binary for 'grantpt' (*note - Pseudo-Terminals: Allocation.) that is installed setuid root to fix -diff --git a/Makeconfig b/Makeconfig -index 97a15b569e..1c815113b9 100644 ---- a/Makeconfig -+++ b/Makeconfig -@@ -386,6 +386,13 @@ LDFLAGS.so += $(hashstyle-LDFLAGS) - LDFLAGS-rtld += $(hashstyle-LDFLAGS) - endif - -+# If lazy relocations are disabled, add the -z now flag. Use -+# LDFLAGS-lib.so instead of LDFLAGS.so, to avoid adding the flag to -+# test modules. -+ifeq ($(bind-now),yes) -+LDFLAGS-lib.so += -Wl,-z,now -+endif -+ - # Command to run after every final link (executable or shared object). - # This is invoked with $(call after-link,...), so it should operate on - # the file $1. This can be set to do some sort of post-processing on -diff --git a/Makerules b/Makerules -index e9194e54cf..43343f03ee 100644 ---- a/Makerules -+++ b/Makerules -@@ -127,6 +127,14 @@ $(common-objpfx)cstdlib: $(c++-cstdlib-header) - $(common-objpfx)cmath: $(c++-cmath-header) - $(INSTALL_DATA) $< $@T - $(move-if-change) $@T $@ -+ifneq (,$(c++-bits-std_abs-h)) -+# Also make a copy of from GCC 7 to prevent it from -+# including /usr/include/stdlib.h. -+before-compile := $(common-objpfx)bits/std_abs.h $(before-compile) -+$(common-objpfx)bits/std_abs.h: $(c++-bits-std_abs-h) -+ $(INSTALL_DATA) $< $@T -+ $(move-if-change) $@T $@ -+endif - endif - - before-compile := $(common-objpfx)libc-abis.h $(before-compile) -@@ -588,7 +596,7 @@ $(LINK.o) -shared -static-libgcc -Wl,-O1 $(sysdep-LDFLAGS) \ - $(extra-B-$(@F:lib%.so=%).so) -B$(csu-objpfx) \ - $(extra-B-$(@F:lib%.so=%).so) $(load-map-file) \ - -Wl,-soname=lib$(libprefix)$(@F:lib%.so=%).so$($(@F)-version) \ -- $(LDFLAGS.so) $(LDFLAGS-$(@F:lib%.so=%).so) \ -+ $(LDFLAGS.so) $(LDFLAGS-lib.so) $(LDFLAGS-$(@F:lib%.so=%).so) \ - -L$(subst :, -L,$(rpath-link)) -Wl,-rpath-link=$(rpath-link) - endef - -@@ -669,14 +677,17 @@ $(build-module-helper) -o $@ $(shlib-lds-flags) \ - $(call after-link,$@) - endef - -+# sofini.os must be placed last since it terminates .eh_frame section. - build-module-helper-objlist = \ - $(patsubst %_pic.a,$(whole-archive) %_pic.a $(no-whole-archive),\ - $(filter-out %.lds $(map-file) $(+preinit) $(+postinit) \ -+ $(elf-objpfx)sofini.os \ - $(link-libc-deps),$^)) - - build-module-objlist = $(build-module-helper-objlist) $(LDLIBS-$(@F:%.so=%).so) - build-shlib-objlist = $(build-module-helper-objlist) \ -- $(LDLIBS-$(@F:lib%.so=%).so) -+ $(LDLIBS-$(@F:lib%.so=%).so) \ -+ $(filter $(elf-objpfx)sofini.os,$^) - - # Don't try to use -lc when making libc.so itself. - # Also omits crti.o and crtn.o, which we do not want -@@ -686,10 +697,6 @@ LDFLAGS-c.so = -nostdlib -nostartfiles - LDLIBS-c.so += $(libc.so-gnulib) - # Give libc.so an entry point and make it directly runnable itself. - LDFLAGS-c.so += -e __libc_main --# If lazy relocation is disabled add the -z now flag. --ifeq ($(bind-now),yes) --LDFLAGS-c.so += -Wl,-z,now --endif - # Pre-link the objects of libc_pic.a so that we can locally resolve - # COMMON symbols before we link against ld.so. This is because ld.so - # contains some of libc_pic.a already, which will prevent the COMMONs -@@ -1104,7 +1111,8 @@ $(common-objpfx)format.lds: $(..)scripts/output-format.sed \ - ifneq (unknown,$(output-format)) - echo > $@.new 'OUTPUT_FORMAT($(output-format))' - else -- $(LINK.o) -shared $(sysdep-LDFLAGS) $(rtld-LDFLAGS) $(LDFLAGS.so) \ -+ $(LINK.o) -shared $(sysdep-LDFLAGS) $(rtld-LDFLAGS) \ -+ $(LDFLAGS.so) $(LDFLAGS-lib.so) \ - -x c /dev/null -o $@.so -Wl,--verbose -v 2>&1 \ - | sed -n -f $< > $@.new - test -s $@.new -diff --git a/NEWS b/NEWS -index ec15dde761..7c44ba2a8a 100644 ---- a/NEWS -+++ b/NEWS -@@ -5,6 +5,60 @@ See the end for copying conditions. - Please send GNU C library bug reports via - using `glibc' in the "product" field. - -+Version 2.25.1 -+ -+Security related changes: -+ -+* The DNS stub resolver limits the advertised UDP buffer size to 1200 bytes, -+ to avoid fragmentation-based spoofing attacks. -+ -+ 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. -+ -+The following bugs are resolved with this release: -+ -+ [20257] sunrpc: clntudp_call does not enforce timeout when receiving data -+ [21015] Document and fix --enable-bind-now -+ [21109] Tunables broken on big-endian -+ [21115] sunrpc: Use-after-free in error path in clntudp_call -+ [21209] Ignore and remove LD_HWCAP_MASK for AT_SECURE programs -+ [21242] assert: Suppress pedantic warning caused by statement expression -+ [21265] x86-64: Use fxsave/xsave/xsavec in _dl_runtime_resolve -+ [21289] Fix symbol redirect for fts_set -+ [21298] rwlock can deadlock on frequent reader/writer phase switching -+ [21386] Assertion in fork for distinct parent PID is incorrect -+ [21624] Unsafe alloca allows local attackers to alias stack and heap (CVE-2017-1000366) -+ [21654] nss: Fix invalid cast in group merging -+ [21778] Robust mutex may deadlock -+ [21972] assert macro requires operator== (int) for its argument type -+ [22322] libc: [mips64] wrong bits/long-double.h installed -+ [22627] $ORIGIN in $LD_LIBRARY_PATH is substituted twice -+ - Version 2.25 - - * The feature test macro __STDC_WANT_LIB_EXT2__, from ISO/IEC TR -diff --git a/assert/Makefile b/assert/Makefile -index 1c3be9b01f..9ec1be81a9 100644 ---- a/assert/Makefile -+++ b/assert/Makefile -@@ -25,6 +25,15 @@ include ../Makeconfig - headers := assert.h - - routines := assert assert-perr __assert --tests := test-assert test-assert-perr -+tests := test-assert test-assert-perr tst-assert-c++ tst-assert-g++ - - include ../Rules -+ -+ifeq ($(have-cxx-thread_local),yes) -+CFLAGS-tst-assert-c++.o = -std=c++11 -+LDLIBS-tst-assert-c++ = -lstdc++ -+CFLAGS-tst-assert-g++.o = -std=gnu++11 -+LDLIBS-tst-assert-g++ = -lstdc++ -+else -+tests-unsupported += tst-assert-c++ tst-assert-g++ -+endif -diff --git a/assert/assert.h b/assert/assert.h -index 22f019537c..640c95c063 100644 ---- a/assert/assert.h -+++ b/assert/assert.h -@@ -85,19 +85,29 @@ __END_DECLS - /* When possible, define assert so that it does not add extra - parentheses around EXPR. Otherwise, those added parentheses would - suppress warnings we'd expect to be detected by gcc's -Wparentheses. */ --# if !defined __GNUC__ || defined __STRICT_ANSI__ -+# if defined __cplusplus -+# define assert(expr) \ -+ (static_cast (expr) \ -+ ? void (0) \ -+ : __assert_fail (#expr, __FILE__, __LINE__, __ASSERT_FUNCTION)) -+# elif !defined __GNUC__ || defined __STRICT_ANSI__ - # define assert(expr) \ - ((expr) \ - ? __ASSERT_VOID_CAST (0) \ - : __assert_fail (#expr, __FILE__, __LINE__, __ASSERT_FUNCTION)) - # else -+/* The first occurrence of EXPR is not evaluated due to the sizeof, -+ but will trigger any pedantic warnings masked by the __extension__ -+ for the second occurrence. The ternary operator is required to -+ support function pointers and bit fields in this context, and to -+ suppress the evaluation of variable length arrays. */ - # define assert(expr) \ -- ({ \ -+ ((void) sizeof ((expr) ? 1 : 0), __extension__ ({ \ - if (expr) \ - ; /* empty */ \ - else \ - __assert_fail (#expr, __FILE__, __LINE__, __ASSERT_FUNCTION); \ -- }) -+ })) - # endif - - # ifdef __USE_GNU -@@ -113,7 +123,7 @@ __END_DECLS - C9x has a similar variable called __func__, but prefer the GCC one since - it demangles C++ function names. */ - # if defined __cplusplus ? __GNUC_PREREQ (2, 6) : __GNUC_PREREQ (2, 4) --# define __ASSERT_FUNCTION __PRETTY_FUNCTION__ -+# define __ASSERT_FUNCTION __extension__ __PRETTY_FUNCTION__ - # else - # if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L - # define __ASSERT_FUNCTION __func__ -diff --git a/assert/tst-assert-c++.cc b/assert/tst-assert-c++.cc -new file mode 100644 -index 0000000000..12a5e690cb ---- /dev/null -+++ b/assert/tst-assert-c++.cc -@@ -0,0 +1,78 @@ -+/* Tests for interactions between C++ and assert. -+ 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 -+ . */ -+ -+#include -+ -+/* The C++ standard requires that if the assert argument is a constant -+ subexpression, then the assert itself is one, too. */ -+constexpr int -+check_constexpr () -+{ -+ return (assert (true), 1); -+} -+ -+/* Objects of this class can be contextually converted to bool, but -+ cannot be compared to int. */ -+struct no_int -+{ -+ no_int () = default; -+ no_int (const no_int &) = delete; -+ -+ explicit operator bool () const -+ { -+ return true; -+ } -+ -+ bool operator! () const; /* No definition. */ -+ template bool operator== (T) const; /* No definition. */ -+ template bool operator!= (T) const; /* No definition. */ -+}; -+ -+/* This class tests that operator== is not used by assert. */ -+struct bool_and_int -+{ -+ bool_and_int () = default; -+ bool_and_int (const no_int &) = delete; -+ -+ explicit operator bool () const -+ { -+ return true; -+ } -+ -+ bool operator! () const; /* No definition. */ -+ template bool operator== (T) const; /* No definition. */ -+ template bool operator!= (T) const; /* No definition. */ -+}; -+ -+static int -+do_test () -+{ -+ { -+ no_int value; -+ assert (value); -+ } -+ -+ { -+ bool_and_int value; -+ assert (value); -+ } -+ -+ return 0; -+} -+ -+#include -diff --git a/assert/tst-assert-g++.cc b/assert/tst-assert-g++.cc -new file mode 100644 -index 0000000000..8c06402825 ---- /dev/null -+++ b/assert/tst-assert-g++.cc -@@ -0,0 +1,19 @@ -+/* Tests for interactions between C++ and assert. GNU C++11 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 -+ . */ -+ -+#include -diff --git a/config.make.in b/config.make.in -index 5836b32a72..709527da4f 100644 ---- a/config.make.in -+++ b/config.make.in -@@ -47,6 +47,7 @@ sysincludes = @SYSINCLUDES@ - c++-sysincludes = @CXX_SYSINCLUDES@ - c++-cstdlib-header = @CXX_CSTDLIB_HEADER@ - c++-cmath-header = @CXX_CMATH_HEADER@ -+c++-bits-std_abs-h = @CXX_BITS_STD_ABS_H@ - all-warnings = @all_warnings@ - enable-werror = @enable_werror@ - -diff --git a/configure b/configure -index eecd0ace74..ee637a7caf 100755 ---- a/configure -+++ b/configure -@@ -634,6 +634,7 @@ BISON - INSTALL_INFO - PERL - BASH_SHELL -+CXX_BITS_STD_ABS_H - CXX_CMATH_HEADER - CXX_CSTDLIB_HEADER - CXX_SYSINCLUDES -@@ -5318,14 +5319,17 @@ fi - # copy of those headers in Makerules. - if test -n "$CXX"; then - find_cxx_header () { -- echo "#include <$1>" | $CXX -M -MP -x c++ - | sed -n "/$1:/{s/:\$//;p}" -+ echo "#include <$1>" | $CXX -M -MP -x c++ - 2>/dev/null \ -+ | sed -n "\,$1:,{s/:\$//;p}" - } - CXX_CSTDLIB_HEADER="$(find_cxx_header cstdlib)" - CXX_CMATH_HEADER="$(find_cxx_header cmath)" -+ CXX_BITS_STD_ABS_H="$(find_cxx_header bits/std_abs.h)" - fi - - - -+ - # Test if LD_LIBRARY_PATH contains the notation for the current directory - # since this would lead to problems installing/building glibc. - # LD_LIBRARY_PATH contains the current directory if one of the following -diff --git a/configure.ac b/configure.ac -index 4a77411b71..d288ff43cd 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -1176,13 +1176,16 @@ AC_SUBST(CXX_SYSINCLUDES) - # copy of those headers in Makerules. - if test -n "$CXX"; then - find_cxx_header () { -- echo "#include <$1>" | $CXX -M -MP -x c++ - | sed -n "/$1:/{s/:\$//;p}" -+ echo "#include <$1>" | $CXX -M -MP -x c++ - 2>/dev/null \ -+ | sed -n "\,$1:,{s/:\$//;p}" - } - CXX_CSTDLIB_HEADER="$(find_cxx_header cstdlib)" - CXX_CMATH_HEADER="$(find_cxx_header cmath)" -+ CXX_BITS_STD_ABS_H="$(find_cxx_header bits/std_abs.h)" - fi - AC_SUBST(CXX_CSTDLIB_HEADER) - AC_SUBST(CXX_CMATH_HEADER) -+AC_SUBST(CXX_BITS_STD_ABS_H) - - # Test if LD_LIBRARY_PATH contains the notation for the current directory - # since this would lead to problems installing/building glibc. -diff --git a/elf/Makefile b/elf/Makefile -index 61abeb59ee..cc4aeb25b6 100644 ---- a/elf/Makefile -+++ b/elf/Makefile -@@ -1398,6 +1398,7 @@ $(objpfx)tst-nodelete-dlclose: $(objpfx)tst-nodelete-dlclose-dso.so - $(objpfx)tst-nodelete-dlclose.out: $(objpfx)tst-nodelete-dlclose-dso.so \ - $(objpfx)tst-nodelete-dlclose-plugin.so - --tst-env-setuid-ENV = MALLOC_CHECK_=2 MALLOC_MMAP_THRESHOLD_=4096 -+tst-env-setuid-ENV = MALLOC_CHECK_=2 MALLOC_MMAP_THRESHOLD_=4096 \ -+ LD_HWCAP_MASK=0xffffffff - tst-env-setuid-tunables-ENV = \ - GLIBC_TUNABLES=glibc.malloc.check=2:glibc.malloc.mmap_threshold=4096 -diff --git a/elf/dl-load.c b/elf/dl-load.c -index a5318f9c8d..58e7220050 100644 ---- a/elf/dl-load.c -+++ b/elf/dl-load.c -@@ -37,6 +37,7 @@ - #include - #include - #include -+#include - - #include - #include -@@ -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/dl-tunable-types.h b/elf/dl-tunable-types.h -index a986f0b593..37a4e8021f 100644 ---- a/elf/dl-tunable-types.h -+++ b/elf/dl-tunable-types.h -@@ -21,8 +21,6 @@ - # define _TUNABLE_TYPES_H_ - #include - --typedef void (*tunable_callback_t) (void *); -- - typedef enum - { - TUNABLE_TYPE_INT_32, -@@ -43,6 +41,8 @@ typedef union - const char *strval; - } tunable_val_t; - -+typedef void (*tunable_callback_t) (tunable_val_t *); -+ - /* Security level for tunables. This decides what to do with individual - tunables for AT_SECURE binaries. */ - typedef enum -diff --git a/elf/dl-tunables.c b/elf/dl-tunables.c -index a8d53d6a31..e42aa67003 100644 ---- a/elf/dl-tunables.c -+++ b/elf/dl-tunables.c -@@ -455,6 +455,8 @@ __tunable_set_val (tunable_id_t id, void *valp, tunable_callback_t callback) - if (cur->strval == NULL) - return; - -+ /* Caller does not need the value, just call the callback with our tunable -+ value. */ - if (valp == NULL) - goto cb; - -diff --git a/elf/rtld.c b/elf/rtld.c -index a036ece956..9362a21e73 100644 ---- a/elf/rtld.c -+++ b/elf/rtld.c -@@ -99,14 +99,121 @@ uintptr_t __pointer_chk_guard_local - strong_alias (__pointer_chk_guard_local, __pointer_chk_guard) - #endif - -+/* Length limits for names and paths, to protect the dynamic linker, -+ particularly when __libc_enable_secure is active. */ -+#ifdef NAME_MAX -+# define SECURE_NAME_LIMIT NAME_MAX -+#else -+# define SECURE_NAME_LIMIT 255 -+#endif -+#ifdef PATH_MAX -+# define SECURE_PATH_LIMIT PATH_MAX -+#else -+# define SECURE_PATH_LIMIT 1024 -+#endif -+ -+/* Check that AT_SECURE=0, or that the passed name does not contain -+ directories and is not overly long. Reject empty names -+ unconditionally. */ -+static bool -+dso_name_valid_for_suid (const char *p) -+{ -+ if (__glibc_unlikely (__libc_enable_secure)) -+ { -+ /* Ignore pathnames with directories for AT_SECURE=1 -+ programs, and also skip overlong names. */ -+ size_t len = strlen (p); -+ if (len >= SECURE_NAME_LIMIT || memchr (p, '/', len) != NULL) -+ return false; -+ } -+ return *p != '\0'; -+} - --/* List of auditing DSOs. */ -+/* LD_AUDIT variable contents. Must be processed before the -+ audit_list below. */ -+const char *audit_list_string; -+ -+/* Cyclic list of auditing DSOs. audit_list->next is the first -+ element. */ - static struct audit_list - { - const char *name; - struct audit_list *next; - } *audit_list; - -+/* Iterator for audit_list_string followed by audit_list. */ -+struct audit_list_iter -+{ -+ /* Tail of audit_list_string still needing processing, or NULL. */ -+ const char *audit_list_tail; -+ -+ /* The list element returned in the previous iteration. NULL before -+ the first element. */ -+ struct audit_list *previous; -+ -+ /* Scratch buffer for returning a name which is part of -+ audit_list_string. */ -+ char fname[SECURE_NAME_LIMIT]; -+}; -+ -+/* Initialize an audit list iterator. */ -+static void -+audit_list_iter_init (struct audit_list_iter *iter) -+{ -+ iter->audit_list_tail = audit_list_string; -+ iter->previous = NULL; -+} -+ -+/* Iterate through both audit_list_string and audit_list. */ -+static const char * -+audit_list_iter_next (struct audit_list_iter *iter) -+{ -+ if (iter->audit_list_tail != NULL) -+ { -+ /* First iterate over audit_list_string. */ -+ while (*iter->audit_list_tail != '\0') -+ { -+ /* Split audit list at colon. */ -+ size_t len = strcspn (iter->audit_list_tail, ":"); -+ if (len > 0 && len < sizeof (iter->fname)) -+ { -+ memcpy (iter->fname, iter->audit_list_tail, len); -+ iter->fname[len] = '\0'; -+ } -+ else -+ /* Do not return this name to the caller. */ -+ iter->fname[0] = '\0'; -+ -+ /* Skip over the substring and the following delimiter. */ -+ iter->audit_list_tail += len; -+ if (*iter->audit_list_tail == ':') -+ ++iter->audit_list_tail; -+ -+ /* If the name is valid, return it. */ -+ if (dso_name_valid_for_suid (iter->fname)) -+ return iter->fname; -+ /* Otherwise, wrap around and try the next name. */ -+ } -+ /* Fall through to the procesing of audit_list. */ -+ } -+ -+ if (iter->previous == NULL) -+ { -+ if (audit_list == NULL) -+ /* No pre-parsed audit list. */ -+ return NULL; -+ /* Start of audit list. The first list element is at -+ audit_list->next (cyclic list). */ -+ iter->previous = audit_list->next; -+ return iter->previous->name; -+ } -+ if (iter->previous == audit_list) -+ /* Cyclic list wrap-around. */ -+ return NULL; -+ iter->previous = iter->previous->next; -+ return iter->previous->name; -+} -+ - #ifndef HAVE_INLINED_SYSCALLS - /* Set nonzero during loading and initialization of executable and - libraries, cleared before the executable's entry point runs. This -@@ -716,6 +823,42 @@ static const char *preloadlist attribute_relro; - /* Nonzero if information about versions has to be printed. */ - static int version_info attribute_relro; - -+/* The LD_PRELOAD environment variable gives list of libraries -+ separated by white space or colons that are loaded before the -+ executable's dependencies and prepended to the global scope list. -+ (If the binary is running setuid all elements containing a '/' are -+ ignored since it is insecure.) Return the number of preloads -+ performed. */ -+unsigned int -+handle_ld_preload (const char *preloadlist, struct link_map *main_map) -+{ -+ unsigned int npreloads = 0; -+ const char *p = preloadlist; -+ char fname[SECURE_PATH_LIMIT]; -+ -+ while (*p != '\0') -+ { -+ /* Split preload list at space/colon. */ -+ size_t len = strcspn (p, " :"); -+ if (len > 0 && len < sizeof (fname)) -+ { -+ memcpy (fname, p, len); -+ fname[len] = '\0'; -+ } -+ else -+ fname[0] = '\0'; -+ -+ /* Skip over the substring and the following delimiter. */ -+ p += len; -+ if (*p != '\0') -+ ++p; -+ -+ if (dso_name_valid_for_suid (fname)) -+ npreloads += do_preload (fname, main_map, "LD_PRELOAD"); -+ } -+ return npreloads; -+} -+ - static void - dl_main (const ElfW(Phdr) *phdr, - ElfW(Word) phnum, -@@ -1238,11 +1381,13 @@ of this helper program; chances are you did not intend to run this program.\n\ - GL(dl_rtld_map).l_tls_modid = _dl_next_tls_modid (); - - /* If we have auditing DSOs to load, do it now. */ -- if (__glibc_unlikely (audit_list != NULL)) -+ bool need_security_init = true; -+ if (__glibc_unlikely (audit_list != NULL) -+ || __glibc_unlikely (audit_list_string != NULL)) - { -- /* Iterate over all entries in the list. The order is important. */ - struct audit_ifaces *last_audit = NULL; -- struct audit_list *al = audit_list->next; -+ struct audit_list_iter al_iter; -+ audit_list_iter_init (&al_iter); - - /* Since we start using the auditing DSOs right away we need to - initialize the data structures now. */ -@@ -1253,9 +1398,14 @@ of this helper program; chances are you did not intend to run this program.\n\ - use different values (especially the pointer guard) and will - fail later on. */ - security_init (); -+ need_security_init = false; - -- do -+ while (true) - { -+ const char *name = audit_list_iter_next (&al_iter); -+ if (name == NULL) -+ break; -+ - int tls_idx = GL(dl_tls_max_dtv_idx); - - /* Now it is time to determine the layout of the static TLS -@@ -1264,7 +1414,7 @@ of this helper program; chances are you did not intend to run this program.\n\ - no DF_STATIC_TLS bit is set. The reason is that we know - glibc will use the static model. */ - struct dlmopen_args dlmargs; -- dlmargs.fname = al->name; -+ dlmargs.fname = name; - dlmargs.map = NULL; - - const char *objname; -@@ -1277,7 +1427,7 @@ of this helper program; chances are you did not intend to run this program.\n\ - not_loaded: - _dl_error_printf ("\ - ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n", -- al->name, err_str); -+ name, err_str); - if (malloced) - free ((char *) err_str); - } -@@ -1381,10 +1531,7 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n", - goto not_loaded; - } - } -- -- al = al->next; - } -- while (al != audit_list->next); - - /* If we have any auditing modules, announce that we already - have two objects loaded. */ -@@ -1462,23 +1609,8 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n", - - if (__glibc_unlikely (preloadlist != NULL)) - { -- /* The LD_PRELOAD environment variable gives list of libraries -- separated by white space or colons that are loaded before the -- executable's dependencies and prepended to the global scope -- list. If the binary is running setuid all elements -- containing a '/' are ignored since it is insecure. */ -- char *list = strdupa (preloadlist); -- char *p; -- - HP_TIMING_NOW (start); -- -- /* Prevent optimizing strsep. Speed is not important here. */ -- while ((p = (strsep) (&list, " :")) != NULL) -- if (p[0] != '\0' -- && (__builtin_expect (! __libc_enable_secure, 1) -- || strchr (p, '/') == NULL)) -- npreloads += do_preload (p, main_map, "LD_PRELOAD"); -- -+ npreloads += handle_ld_preload (preloadlist, main_map); - HP_TIMING_NOW (stop); - HP_TIMING_DIFF (diff, start, stop); - HP_TIMING_ACCUM_NT (load_time, diff); -@@ -1663,7 +1795,7 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n", - if (tcbp == NULL) - tcbp = init_tls (); - -- if (__glibc_likely (audit_list == NULL)) -+ if (__glibc_likely (need_security_init)) - /* Initialize security features. But only if we have not done it - earlier. */ - security_init (); -@@ -2294,9 +2426,7 @@ process_dl_audit (char *str) - char *p; - - while ((p = (strsep) (&str, ":")) != NULL) -- if (p[0] != '\0' -- && (__builtin_expect (! __libc_enable_secure, 1) -- || strchr (p, '/') == NULL)) -+ if (dso_name_valid_for_suid (p)) - { - /* This is using the local malloc, not the system malloc. The - memory can never be freed. */ -@@ -2360,7 +2490,7 @@ process_envvars (enum mode *modep) - break; - } - if (memcmp (envline, "AUDIT", 5) == 0) -- process_dl_audit (&envline[6]); -+ audit_list_string = &envline[6]; - break; - - case 7: -@@ -2404,7 +2534,8 @@ process_envvars (enum mode *modep) - - case 10: - /* Mask for the important hardware capabilities. */ -- if (memcmp (envline, "HWCAP_MASK", 10) == 0) -+ if (!__libc_enable_secure -+ && memcmp (envline, "HWCAP_MASK", 10) == 0) - GLRO(dl_hwcap_mask) = __strtoul_internal (&envline[11], NULL, - 0, 0); - break; -@@ -2418,7 +2549,8 @@ process_envvars (enum mode *modep) - - case 12: - /* The library search path. */ -- if (memcmp (envline, "LIBRARY_PATH", 12) == 0) -+ if (!__libc_enable_secure -+ && memcmp (envline, "LIBRARY_PATH", 12) == 0) - { - library_path = &envline[13]; - break; -diff --git a/elf/tst-env-setuid.c b/elf/tst-env-setuid.c -index 6ec3fa5874..eec408eb5d 100644 ---- a/elf/tst-env-setuid.c -+++ b/elf/tst-env-setuid.c -@@ -213,6 +213,12 @@ test_child (void) - return 1; - } - -+ if (getenv ("LD_HWCAP_MASK") != NULL) -+ { -+ printf ("LD_HWCAP_MASK still set\n"); -+ return 1; -+ } -+ - return 0; - } - #endif -@@ -233,6 +239,12 @@ test_parent (void) - return 1; - } - -+ if (getenv ("LD_HWCAP_MASK") == NULL) -+ { -+ printf ("LD_HWCAP_MASK lost\n"); -+ return 1; -+ } -+ - return 0; - } - #endif -diff --git a/grp/grp-merge.c b/grp/grp-merge.c -index 77c494d159..035e7a604b 100644 ---- a/grp/grp-merge.c -+++ b/grp/grp-merge.c -@@ -85,6 +85,14 @@ __copy_grp (const struct group srcgrp, const size_t buflen, - } - members[i] = NULL; - -+ /* Align for pointers. We can't simply align C because we need to -+ align destbuf[c]. */ -+ if ((((uintptr_t)destbuf + c) & (__alignof__(char **) - 1)) != 0) -+ { -+ uintptr_t mis_align = ((uintptr_t)destbuf + c) & (__alignof__(char **) - 1); -+ c += __alignof__(char **) - mis_align; -+ } -+ - /* Copy the pointers from the members array into the buffer and assign them - to the gr_mem member of destgrp. */ - destgrp->gr_mem = (char **) &destbuf[c]; -@@ -129,7 +137,7 @@ __merge_grp (struct group *savedgrp, char *savedbuf, char *savedend, - - /* Get the count of group members from the last sizeof (size_t) bytes in the - mergegrp buffer. */ -- savedmemcount = (size_t) *(savedend - sizeof (size_t)); -+ savedmemcount = *(size_t *) (savedend - sizeof (size_t)); - - /* Get the count of new members to add. */ - for (memcount = 0; mergegrp->gr_mem[memcount]; memcount++) -@@ -168,6 +176,14 @@ __merge_grp (struct group *savedgrp, char *savedbuf, char *savedend, - /* Add the NULL-terminator. */ - members[savedmemcount + memcount] = NULL; - -+ /* Align for pointers. We can't simply align C because we need to -+ align savedbuf[c]. */ -+ if ((((uintptr_t)savedbuf + c) & (__alignof__(char **) - 1)) != 0) -+ { -+ uintptr_t mis_align = ((uintptr_t)savedbuf + c) & (__alignof__(char **) - 1); -+ c += __alignof__(char **) - mis_align; -+ } -+ - /* Copy the member array back into the buffer after the member list and free - the member array. */ - savedgrp->gr_mem = (char **) &savedbuf[c]; -diff --git a/iconvdata/Makefile b/iconvdata/Makefile -index 04157b25c5..e4845871f5 100644 ---- a/iconvdata/Makefile -+++ b/iconvdata/Makefile -@@ -63,6 +63,11 @@ modules := ISO8859-1 ISO8859-2 ISO8859-3 ISO8859-4 ISO8859-5 \ - MAC-CENTRALEUROPE KOI8-RU ISO8859-9E \ - CP770 CP771 CP772 CP773 CP774 - -+# If lazy binding is disabled, use BIND_NOW for the gconv modules. -+ifeq ($(bind-now),yes) -+LDFLAGS.so += -Wl,-z,now -+endif -+ - modules.so := $(addsuffix .so, $(modules)) - - ifeq (yes,$(build-shared)) -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 -+ . */ -+ -+#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/include/resolv.h b/include/resolv.h -index 95dcd3ca37..e8f477cd86 100644 ---- a/include/resolv.h -+++ b/include/resolv.h -@@ -37,8 +37,6 @@ extern void res_pquery (const res_state __statp, const unsigned char *__msg, - extern int res_ourserver_p (const res_state __statp, - const struct sockaddr_in6 *__inp); - extern void __res_iclose (res_state statp, bool free_addr); --extern int __res_nopt(res_state statp, int n0, unsigned char *buf, int buflen, -- int anslen); - libc_hidden_proto (__res_ninit) - libc_hidden_proto (__res_maybe_init) - libc_hidden_proto (__res_nclose) -@@ -91,7 +89,6 @@ libresolv_hidden_proto (__res_nameinquery) - libresolv_hidden_proto (__res_queriesmatch) - libresolv_hidden_proto (__res_nsend) - libresolv_hidden_proto (__b64_ntop) --libresolv_hidden_proto (__res_nopt) - libresolv_hidden_proto (__dn_count_labels) - libresolv_hidden_proto (__p_secstodate) - -diff --git a/inet/Makefile b/inet/Makefile -index 010792af8f..6a7d3e0664 100644 ---- a/inet/Makefile -+++ b/inet/Makefile -@@ -45,14 +45,18 @@ routines := htonl htons \ - in6_addr getnameinfo if_index ifaddrs inet6_option \ - getipv4sourcefilter setipv4sourcefilter \ - getsourcefilter setsourcefilter inet6_opt inet6_rth \ -- inet6_scopeid_pton -+ inet6_scopeid_pton deadline - - aux := check_pf check_native ifreq - - tests := htontest test_ifindex tst-ntoa tst-ether_aton tst-network \ - tst-gethnm test-ifaddrs bug-if1 test-inet6_opt tst-ether_line \ - tst-getni1 tst-getni2 tst-inet6_rth tst-checks tst-checks-posix \ -- tst-sockaddr tst-inet6_scopeid_pton test-hnto-types -+ tst-sockaddr tst-inet6_scopeid_pton test-hnto-types tst-deadline -+ -+# tst-deadline must be linked statically so that we can access -+# internal functions. -+tests-static += tst-deadline - - include ../Rules - -diff --git a/inet/deadline.c b/inet/deadline.c -new file mode 100644 -index 0000000000..c1fa415a39 ---- /dev/null -+++ b/inet/deadline.c -@@ -0,0 +1,122 @@ -+/* Computing deadlines for timeouts. -+ 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 -+ . */ -+ -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+struct deadline_current_time internal_function -+__deadline_current_time (void) -+{ -+ struct deadline_current_time result; -+ if (__clock_gettime (CLOCK_MONOTONIC, &result.current) != 0) -+ { -+ struct timeval current_tv; -+ if (__gettimeofday (¤t_tv, NULL) == 0) -+ __libc_fatal ("Fatal error: gettimeofday system call failed\n"); -+ result.current.tv_sec = current_tv.tv_sec; -+ result.current.tv_nsec = current_tv.tv_usec * 1000; -+ } -+ assert (result.current.tv_sec >= 0); -+ return result; -+} -+ -+/* A special deadline value for which __deadline_is_infinite is -+ true. */ -+static inline struct deadline -+infinite_deadline (void) -+{ -+ return (struct deadline) { { -1, -1 } }; -+} -+ -+struct deadline internal_function -+__deadline_from_timeval (struct deadline_current_time current, -+ struct timeval tv) -+{ -+ assert (__is_timeval_valid_timeout (tv)); -+ -+ /* Compute second-based deadline. Perform the addition in -+ uintmax_t, which is unsigned, to simply overflow detection. */ -+ uintmax_t sec = current.current.tv_sec; -+ sec += tv.tv_sec; -+ if (sec < (uintmax_t) tv.tv_sec) -+ return infinite_deadline (); -+ -+ /* Compute nanosecond deadline. */ -+ int nsec = current.current.tv_nsec + tv.tv_usec * 1000; -+ if (nsec >= 1000 * 1000 * 1000) -+ { -+ /* Carry nanosecond overflow to seconds. */ -+ nsec -= 1000 * 1000 * 1000; -+ if (sec + 1 < sec) -+ return infinite_deadline (); -+ ++sec; -+ } -+ /* This uses a GCC extension, otherwise these casts for detecting -+ overflow would not be defined. */ -+ if ((time_t) sec < 0 || sec != (uintmax_t) (time_t) sec) -+ return infinite_deadline (); -+ -+ return (struct deadline) { { sec, nsec } }; -+} -+ -+int internal_function -+__deadline_to_ms (struct deadline_current_time current, -+ struct deadline deadline) -+{ -+ if (__deadline_is_infinite (deadline)) -+ return INT_MAX; -+ -+ if (current.current.tv_sec > deadline.absolute.tv_sec -+ || (current.current.tv_sec == deadline.absolute.tv_sec -+ && current.current.tv_nsec >= deadline.absolute.tv_nsec)) -+ return 0; -+ time_t sec = deadline.absolute.tv_sec - current.current.tv_sec; -+ if (sec >= INT_MAX) -+ /* This value will overflow below. */ -+ return INT_MAX; -+ int nsec = deadline.absolute.tv_nsec - current.current.tv_nsec; -+ if (nsec < 0) -+ { -+ /* Borrow from the seconds field. */ -+ assert (sec > 0); -+ --sec; -+ nsec += 1000 * 1000 * 1000; -+ } -+ -+ /* Prepare for rounding up to milliseconds. */ -+ nsec += 999999; -+ if (nsec > 1000 * 1000 * 1000) -+ { -+ assert (sec < INT_MAX); -+ ++sec; -+ nsec -= 1000 * 1000 * 1000; -+ } -+ -+ unsigned int msec = nsec / (1000 * 1000); -+ if (sec > INT_MAX / 1000) -+ return INT_MAX; -+ msec += sec * 1000; -+ if (msec > INT_MAX) -+ return INT_MAX; -+ return msec; -+} -diff --git a/inet/net-internal.h b/inet/net-internal.h -index 087597ed99..2b2632c7ba 100644 ---- a/inet/net-internal.h -+++ b/inet/net-internal.h -@@ -20,11 +20,100 @@ - #define _NET_INTERNAL_H 1 - - #include -+#include - #include -+#include - - int __inet6_scopeid_pton (const struct in6_addr *address, - const char *scope, uint32_t *result) - internal_function attribute_hidden; - libc_hidden_proto (__inet6_scopeid_pton) - -+ -+/* Deadline handling for enforcing timeouts. -+ -+ Code should call __deadline_current_time to obtain the current time -+ and cache it locally. The cache needs updating after every -+ long-running or potentially blocking operation. Deadlines relative -+ to the current time can be computed using __deadline_from_timeval. -+ The deadlines may have to be recomputed in response to certain -+ events (such as an incoming packet), but they are absolute (not -+ relative to the current time). A timeout suitable for use with the -+ poll function can be computed from such a deadline using -+ __deadline_to_ms. -+ -+ The fields in the structs defined belowed should only be used -+ within the implementation. */ -+ -+/* Cache of the current time. Used to compute deadlines from relative -+ timeouts and vice versa. */ -+struct deadline_current_time -+{ -+ struct timespec current; -+}; -+ -+/* Return the current time. Terminates the process if the current -+ time is not available. */ -+struct deadline_current_time __deadline_current_time (void) -+ internal_function attribute_hidden; -+ -+/* Computed absolute deadline. */ -+struct deadline -+{ -+ struct timespec absolute; -+}; -+ -+ -+/* For internal use only. */ -+static inline bool -+__deadline_is_infinite (struct deadline deadline) -+{ -+ return deadline.absolute.tv_nsec < 0; -+} -+ -+/* Return true if the current time is at the deadline or past it. */ -+static inline bool -+__deadline_elapsed (struct deadline_current_time current, -+ struct deadline deadline) -+{ -+ return !__deadline_is_infinite (deadline) -+ && (current.current.tv_sec > deadline.absolute.tv_sec -+ || (current.current.tv_sec == deadline.absolute.tv_sec -+ && current.current.tv_nsec >= deadline.absolute.tv_nsec)); -+} -+ -+/* Return the deadline which occurs first. */ -+static inline struct deadline -+__deadline_first (struct deadline left, struct deadline right) -+{ -+ if (__deadline_is_infinite (right) -+ || left.absolute.tv_sec < right.absolute.tv_sec -+ || (left.absolute.tv_sec == right.absolute.tv_sec -+ && left.absolute.tv_nsec < right.absolute.tv_nsec)) -+ return left; -+ else -+ return right; -+} -+ -+/* Add TV to the current time and return it. Returns a special -+ infinite absolute deadline on overflow. */ -+struct deadline __deadline_from_timeval (struct deadline_current_time, -+ struct timeval tv) -+ internal_function attribute_hidden; -+ -+/* Compute the number of milliseconds until the specified deadline, -+ from the current time in the argument. The result is mainly for -+ use with poll. If the deadline has already passed, return 0. If -+ the result would overflow an int, return INT_MAX. */ -+int __deadline_to_ms (struct deadline_current_time, struct deadline) -+ internal_function attribute_hidden; -+ -+/* Return true if TV.tv_sec is non-negative and TV.tv_usec is in the -+ interval [0, 999999]. */ -+static inline bool -+__is_timeval_valid_timeout (struct timeval tv) -+{ -+ return tv.tv_sec >= 0 && tv.tv_usec >= 0 && tv.tv_usec < 1000 * 1000; -+} -+ - #endif /* _NET_INTERNAL_H */ -diff --git a/inet/tst-deadline.c b/inet/tst-deadline.c -new file mode 100644 -index 0000000000..ed04345c35 ---- /dev/null -+++ b/inet/tst-deadline.c -@@ -0,0 +1,188 @@ -+/* Tests for computing deadlines for timeouts. -+ 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 -+ . */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+/* Find the maximum value which can be represented in a time_t. */ -+static time_t -+time_t_max (void) -+{ -+ _Static_assert (0 > (time_t) -1, "time_t is signed"); -+ uintmax_t current = 1; -+ while (true) -+ { -+ uintmax_t next = current * 2; -+ /* This cannot happen because time_t is signed. */ -+ TEST_VERIFY_EXIT (next > current); -+ ++next; -+ if ((time_t) next < 0 || next != (uintmax_t) (time_t) next) -+ /* Value cannot be represented in time_t. Return the previous -+ value. */ -+ return current; -+ current = next; -+ } -+} -+ -+static int -+do_test (void) -+{ -+ { -+ struct deadline_current_time current_time = __deadline_current_time (); -+ TEST_VERIFY (current_time.current.tv_sec >= 0); -+ current_time = __deadline_current_time (); -+ /* Due to CLOCK_MONOTONIC, either seconds or nanoseconds are -+ greater than zero. This is also true for the gettimeofday -+ fallback. */ -+ TEST_VERIFY (current_time.current.tv_sec >= 0); -+ TEST_VERIFY (current_time.current.tv_sec > 0 -+ || current_time.current.tv_nsec > 0); -+ } -+ -+ /* Check basic computations of deadlines. */ -+ struct deadline_current_time current_time = { { 1, 123456789 } }; -+ struct deadline deadline = __deadline_from_timeval -+ (current_time, (struct timeval) { 0, 1 }); -+ TEST_VERIFY (deadline.absolute.tv_sec == 1); -+ TEST_VERIFY (deadline.absolute.tv_nsec == 123457789); -+ TEST_VERIFY (__deadline_to_ms (current_time, deadline) == 1); -+ -+ deadline = __deadline_from_timeval -+ (current_time, ((struct timeval) { 0, 2 })); -+ TEST_VERIFY (deadline.absolute.tv_sec == 1); -+ TEST_VERIFY (deadline.absolute.tv_nsec == 123458789); -+ TEST_VERIFY (__deadline_to_ms (current_time, deadline) == 1); -+ -+ deadline = __deadline_from_timeval -+ (current_time, ((struct timeval) { 1, 0 })); -+ TEST_VERIFY (deadline.absolute.tv_sec == 2); -+ TEST_VERIFY (deadline.absolute.tv_nsec == 123456789); -+ TEST_VERIFY (__deadline_to_ms (current_time, deadline) == 1000); -+ -+ /* Check if timeouts are correctly rounded up to the next -+ millisecond. */ -+ for (int i = 0; i < 999999; ++i) -+ { -+ ++current_time.current.tv_nsec; -+ TEST_VERIFY (__deadline_to_ms (current_time, deadline) == 1000); -+ } -+ -+ /* A full millisecond has elapsed, so the time to the deadline is -+ now less than 1000. */ -+ ++current_time.current.tv_nsec; -+ TEST_VERIFY (__deadline_to_ms (current_time, deadline) == 999); -+ -+ /* Check __deadline_to_ms carry-over. */ -+ current_time = (struct deadline_current_time) { { 9, 123456789 } }; -+ deadline = (struct deadline) { { 10, 122456789 } }; -+ TEST_VERIFY (__deadline_to_ms (current_time, deadline) == 999); -+ deadline = (struct deadline) { { 10, 122456790 } }; -+ TEST_VERIFY (__deadline_to_ms (current_time, deadline) == 1000); -+ deadline = (struct deadline) { { 10, 123456788 } }; -+ TEST_VERIFY (__deadline_to_ms (current_time, deadline) == 1000); -+ deadline = (struct deadline) { { 10, 123456789 } }; -+ TEST_VERIFY (__deadline_to_ms (current_time, deadline) == 1000); -+ -+ /* Check __deadline_to_ms overflow. */ -+ deadline = (struct deadline) { { INT_MAX - 1, 1 } }; -+ TEST_VERIFY (__deadline_to_ms (current_time, deadline) == INT_MAX); -+ -+ /* Check __deadline_to_ms for elapsed deadlines. */ -+ current_time = (struct deadline_current_time) { { 9, 123456789 } }; -+ deadline.absolute = current_time.current; -+ TEST_VERIFY (__deadline_to_ms (current_time, deadline) == 0); -+ current_time = (struct deadline_current_time) { { 9, 123456790 } }; -+ TEST_VERIFY (__deadline_to_ms (current_time, deadline) == 0); -+ current_time = (struct deadline_current_time) { { 10, 0 } }; -+ TEST_VERIFY (__deadline_to_ms (current_time, deadline) == 0); -+ current_time = (struct deadline_current_time) { { 10, 123456788 } }; -+ TEST_VERIFY (__deadline_to_ms (current_time, deadline) == 0); -+ current_time = (struct deadline_current_time) { { 10, 123456789 } }; -+ TEST_VERIFY (__deadline_to_ms (current_time, deadline) == 0); -+ -+ /* Check carry-over in __deadline_from_timeval. */ -+ current_time = (struct deadline_current_time) { { 9, 998000001 } }; -+ for (int i = 0; i < 2000; ++i) -+ { -+ deadline = __deadline_from_timeval -+ (current_time, (struct timeval) { 1, i }); -+ TEST_VERIFY (deadline.absolute.tv_sec == 10); -+ TEST_VERIFY (deadline.absolute.tv_nsec == 998000001 + i * 1000); -+ } -+ for (int i = 2000; i < 3000; ++i) -+ { -+ deadline = __deadline_from_timeval -+ (current_time, (struct timeval) { 2, i }); -+ TEST_VERIFY (deadline.absolute.tv_sec == 12); -+ TEST_VERIFY (deadline.absolute.tv_nsec == 1 + (i - 2000) * 1000); -+ } -+ -+ /* Check infinite deadlines. */ -+ deadline = __deadline_from_timeval -+ ((struct deadline_current_time) { { 0, 1000 * 1000 * 1000 - 1000 } }, -+ (struct timeval) { time_t_max (), 1 }); -+ TEST_VERIFY (__deadline_is_infinite (deadline)); -+ deadline = __deadline_from_timeval -+ ((struct deadline_current_time) { { 0, 1000 * 1000 * 1000 - 1001 } }, -+ (struct timeval) { time_t_max (), 1 }); -+ TEST_VERIFY (!__deadline_is_infinite (deadline)); -+ deadline = __deadline_from_timeval -+ ((struct deadline_current_time) -+ { { time_t_max (), 1000 * 1000 * 1000 - 1000 } }, -+ (struct timeval) { 0, 1 }); -+ TEST_VERIFY (__deadline_is_infinite (deadline)); -+ deadline = __deadline_from_timeval -+ ((struct deadline_current_time) -+ { { time_t_max () / 2 + 1, 0 } }, -+ (struct timeval) { time_t_max () / 2 + 1, 0 }); -+ TEST_VERIFY (__deadline_is_infinite (deadline)); -+ -+ /* Check __deadline_first behavior. */ -+ deadline = __deadline_first -+ ((struct deadline) { { 1, 2 } }, -+ (struct deadline) { { 1, 3 } }); -+ TEST_VERIFY (deadline.absolute.tv_sec == 1); -+ TEST_VERIFY (deadline.absolute.tv_nsec == 2); -+ deadline = __deadline_first -+ ((struct deadline) { { 1, 3 } }, -+ (struct deadline) { { 1, 2 } }); -+ TEST_VERIFY (deadline.absolute.tv_sec == 1); -+ TEST_VERIFY (deadline.absolute.tv_nsec == 2); -+ deadline = __deadline_first -+ ((struct deadline) { { 1, 2 } }, -+ (struct deadline) { { 2, 1 } }); -+ TEST_VERIFY (deadline.absolute.tv_sec == 1); -+ TEST_VERIFY (deadline.absolute.tv_nsec == 2); -+ deadline = __deadline_first -+ ((struct deadline) { { 1, 2 } }, -+ (struct deadline) { { 2, 4 } }); -+ TEST_VERIFY (deadline.absolute.tv_sec == 1); -+ TEST_VERIFY (deadline.absolute.tv_nsec == 2); -+ deadline = __deadline_first -+ ((struct deadline) { { 2, 4 } }, -+ (struct deadline) { { 1, 2 } }); -+ TEST_VERIFY (deadline.absolute.tv_sec == 1); -+ TEST_VERIFY (deadline.absolute.tv_nsec == 2); -+ -+ return 0; -+} -+ -+#include -diff --git a/io/fts.h b/io/fts.h -index b9cff534e9..ab15567001 100644 ---- a/io/fts.h -+++ b/io/fts.h -@@ -193,7 +193,7 @@ FTS *__REDIRECT (fts_open, (char * const *, int, - int (*)(const FTSENT **, const FTSENT **)), - fts64_open); - FTSENT *__REDIRECT (fts_read, (FTS *), fts64_read); --int __REDIRECT (fts_set, (FTS *, FTSENT *, int), fts64_set) __THROW; -+int __REDIRECT_NTH (fts_set, (FTS *, FTSENT *, int), fts64_set); - # else - # define fts_children fts64_children - # define fts_close fts64_close -diff --git a/localedata/ChangeLog b/localedata/ChangeLog -index 0cdb097ab6..127c1cfb35 100644 ---- a/localedata/ChangeLog -+++ b/localedata/ChangeLog -@@ -1,3 +1,11 @@ -+2017-06-11 Santhosh Thottingal -+ -+ [BZ #19922] -+ * locales/iso14651_t1_common: Add collation rules for U+07DA to U+07DF. -+ -+ [BZ #19919] -+ * locales/iso14651_t1_common: Correct collation of U+0D36 and U+0D37. -+ - 2017-01-01 Joseph Myers - - * All files with FSF copyright notices: Update copyright dates -diff --git a/localedata/locales/iso14651_t1_common b/localedata/locales/iso14651_t1_common -index eef75ba65e..0e64f26a12 100644 ---- a/localedata/locales/iso14651_t1_common -+++ b/localedata/locales/iso14651_t1_common -@@ -1042,9 +1042,9 @@ collating-element from "" - collating-element from "" - collating-element from "" - collating-element from "" --collating-element from "" - collating-element from "" - collating-element from "" -+collating-element from "" - collating-element from "" - collating-element from "" - collating-element from "" -@@ -1103,8 +1103,8 @@ collating-symbol - collating-symbol - collating-symbol - collating-symbol --collating-symbol - collating-symbol -+collating-symbol - collating-symbol - collating-symbol - collating-symbol -@@ -1126,6 +1126,12 @@ collating-symbol - collating-symbol - collating-symbol - collating-symbol -+collating-symbol -+collating-symbol -+collating-symbol -+collating-symbol -+collating-symbol -+collating-symbol - # - # - # -@@ -4552,6 +4558,12 @@ collating-symbol - - - -+ -+ -+ -+ -+ -+ - # - # - # -@@ -7252,6 +7264,7 @@ order_start ;forward;forward;forward;forward,position - ;;;IGNORE - ;;;IGNORE - "";;;IGNORE -+ "";;;IGNORE - "";;;IGNORE - "";;;IGNORE - "";;;IGNORE -@@ -7280,6 +7293,7 @@ order_start ;forward;forward;forward;forward,position - "";;;IGNORE - "";;;IGNORE - "";;;IGNORE # ണ്‍ = ണ + ് + zwj -+ "";;;IGNORE - "";;;IGNORE # ണ = ണ + ് + അ - "";;;IGNORE - "";;;IGNORE -@@ -7290,6 +7304,7 @@ order_start ;forward;forward;forward;forward,position - "";;;IGNORE - "";;;IGNORE - "";;;IGNORE # ന്‍= ന + ് + zwj -+ "";;;IGNORE - "";;;IGNORE #ന = ന + ് + അ - "";;;IGNORE - "";;;IGNORE -@@ -7305,20 +7320,23 @@ order_start ;forward;forward;forward;forward,position - "";;;IGNORE - "";;;IGNORE - "";;;IGNORE # ര = ര + ് + zwj -+ "";;;IGNORE - "";;;IGNORE # ര = ര + ് + അ - ;;;IGNORE # ല്‍ = ല + ് + zwj -+ "";;;IGNORE - "";;;IGNORE # ല = ല + ് + അ - "";;;IGNORE - "";;;IGNORE - "";;;IGNORE -- "";;;IGNORE -+ "";;;IGNORE - "";;;IGNORE -- "";;;IGNORE -+ "";;;IGNORE - "";;;IGNORE - "";;;IGNORE - "";;;IGNORE - "";;;IGNORE - "";;;IGNORE # ള്‍ = ള + ് + zwj -+ "";;;IGNORE - "";;;IGNORE # ള = ള + ് + അ - "";;;IGNORE - "";;;IGNORE -diff --git a/malloc/arena.c b/malloc/arena.c -index b91d7d6b16..d49e4a21c8 100644 ---- a/malloc/arena.c -+++ b/malloc/arena.c -@@ -212,9 +212,9 @@ __malloc_fork_unlock_child (void) - #if HAVE_TUNABLES - static inline int do_set_mallopt_check (int32_t value); - void --DL_TUNABLE_CALLBACK (set_mallopt_check) (void *valp) -+DL_TUNABLE_CALLBACK (set_mallopt_check) (tunable_val_t *valp) - { -- int32_t value = *(int32_t *) valp; -+ int32_t value = (int32_t) valp->numval; - do_set_mallopt_check (value); - if (check_action != 0) - __malloc_check_init (); -@@ -223,9 +223,9 @@ DL_TUNABLE_CALLBACK (set_mallopt_check) (void *valp) - # define DL_TUNABLE_CALLBACK_FNDECL(__name, __type) \ - static inline int do_ ## __name (__type value); \ - void \ --DL_TUNABLE_CALLBACK (__name) (void *valp) \ -+DL_TUNABLE_CALLBACK (__name) (tunable_val_t *valp) \ - { \ -- __type value = *(__type *) valp; \ -+ __type value = (__type) (valp)->numval; \ - do_ ## __name (value); \ - } - -diff --git a/malloc/malloc.c b/malloc/malloc.c -index 4885793905..4e076638b0 100644 ---- a/malloc/malloc.c -+++ b/malloc/malloc.c -@@ -4902,7 +4902,7 @@ __libc_mallopt (int param_number, int value) - - case M_ARENA_MAX: - if (value > 0) -- do_set_arena_test (value); -+ do_set_arena_max (value); - break; - } - __libc_lock_unlock (av->mutex); -diff --git a/misc/regexp.c b/misc/regexp.c -index 19d76c0c37..eaea7c3b89 100644 ---- a/misc/regexp.c -+++ b/misc/regexp.c -@@ -29,14 +29,15 @@ - - #if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_23) - --/* Define the variables used for the interface. */ --char *loc1; --char *loc2; -+/* Define the variables used for the interface. Avoid .symver on common -+ symbol, which just creates a new common symbol, not an alias. */ -+char *loc1 __attribute__ ((nocommon)); -+char *loc2 __attribute__ ((nocommon)); - compat_symbol (libc, loc1, loc1, GLIBC_2_0); - compat_symbol (libc, loc2, loc2, GLIBC_2_0); - - /* Although we do not support the use we define this variable as well. */ --char *locs; -+char *locs __attribute__ ((nocommon)); - compat_symbol (libc, locs, locs, GLIBC_2_0); - - -diff --git a/nptl/Makefile b/nptl/Makefile -index 6d48c0cfc8..8def69ae22 100644 ---- a/nptl/Makefile -+++ b/nptl/Makefile -@@ -224,6 +224,7 @@ tests = tst-typesizes \ - tst-attr1 tst-attr2 tst-attr3 tst-default-attr \ - tst-mutex1 tst-mutex2 tst-mutex3 tst-mutex4 tst-mutex5 tst-mutex6 \ - tst-mutex7 tst-mutex8 tst-mutex9 tst-mutex5a tst-mutex7a \ -+ tst-mutex7robust \ - tst-mutexpi1 tst-mutexpi2 tst-mutexpi3 tst-mutexpi4 tst-mutexpi5 \ - tst-mutexpi5a tst-mutexpi6 tst-mutexpi7 tst-mutexpi7a tst-mutexpi8 \ - tst-mutexpi9 \ -@@ -241,7 +242,7 @@ tests = tst-typesizes \ - tst-rwlock4 tst-rwlock5 tst-rwlock6 tst-rwlock7 tst-rwlock8 \ - tst-rwlock9 tst-rwlock10 tst-rwlock11 tst-rwlock12 tst-rwlock13 \ - tst-rwlock14 tst-rwlock15 tst-rwlock16 tst-rwlock17 tst-rwlock18 \ -- tst-rwlock19 \ -+ tst-rwlock19 tst-rwlock20 \ - tst-once1 tst-once2 tst-once3 tst-once4 tst-once5 \ - tst-key1 tst-key2 tst-key3 tst-key4 \ - tst-sem1 tst-sem2 tst-sem3 tst-sem4 tst-sem5 tst-sem6 tst-sem7 \ -@@ -355,7 +356,7 @@ tests += tst-cancelx2 tst-cancelx3 tst-cancelx4 tst-cancelx5 \ - tst-oncex3 tst-oncex4 - ifeq ($(build-shared),yes) - tests += tst-atfork2 tst-tls3 tst-tls3-malloc tst-tls4 tst-tls5 tst-_res1 \ -- tst-fini1 tst-stackguard1 -+ tst-fini1 tst-stackguard1 tst-compat-forwarder - tests-nolibpthread += tst-fini1 - ifeq ($(have-z-execstack),yes) - tests += tst-execstack -@@ -366,7 +367,7 @@ modules-names = tst-atfork2mod tst-tls3mod tst-tls4moda tst-tls4modb \ - tst-tls5mod tst-tls5moda tst-tls5modb tst-tls5modc \ - tst-tls5modd tst-tls5mode tst-tls5modf tst-stack4mod \ - tst-_res1mod1 tst-_res1mod2 tst-execstack-mod tst-fini1mod \ -- tst-join7mod -+ tst-join7mod tst-compat-forwarder-mod - extra-test-objs += $(addsuffix .os,$(strip $(modules-names))) \ - tst-cleanup4aux.o tst-cleanupx4aux.o - test-extras += $(modules-names) tst-cleanup4aux tst-cleanupx4aux -@@ -704,6 +705,8 @@ $(objpfx)tst-oddstacklimit.out: $(objpfx)tst-oddstacklimit $(objpfx)tst-basic1 - $(evaluate-test) - endif - -+$(objpfx)tst-compat-forwarder: $(objpfx)tst-compat-forwarder-mod.so -+ - # The tests here better do not run in parallel - ifneq ($(filter %tests,$(MAKECMDGOALS)),) - .NOTPARALLEL: -diff --git a/nptl/allocatestack.c b/nptl/allocatestack.c -index 8a228ab254..368fe3c36b 100644 ---- a/nptl/allocatestack.c -+++ b/nptl/allocatestack.c -@@ -683,8 +683,14 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp, - prot) != 0) - goto mprot_error; - #elif _STACK_GROWS_UP -- if (mprotect ((char *) pd - pd->guardsize, -- pd->guardsize - guardsize, prot) != 0) -+ char *new_guard = (char *)(((uintptr_t) pd - guardsize) -+ & ~pagesize_m1); -+ char *old_guard = (char *)(((uintptr_t) pd - pd->guardsize) -+ & ~pagesize_m1); -+ /* The guard size difference might be > 0, but once rounded -+ to the nearest page the size difference might be zero. */ -+ if (new_guard > old_guard -+ && mprotect (old_guard, new_guard - old_guard, prot) != 0) - goto mprot_error; - #endif - -diff --git a/nptl/pt-longjmp.c b/nptl/pt-longjmp.c -index 2ef757e687..8f3c6b3a09 100644 ---- a/nptl/pt-longjmp.c -+++ b/nptl/pt-longjmp.c -@@ -25,21 +25,14 @@ - symbol in libpthread, but the historical ABI requires it. For static - linking, there is no need to provide anything here--the libc version - will be linked in. For shared library ABI compatibility, there must be -- longjmp and siglongjmp symbols in libpthread.so; so we define them using -- IFUNC to redirect to the libc function. */ -+ longjmp and siglongjmp symbols in libpthread.so. - --#if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_22) -- --# if HAVE_IFUNC -- --# undef INIT_ARCH --# define INIT_ARCH() --# define DEFINE_LONGJMP(name) libc_ifunc (name, &__libc_longjmp) -- --extern __typeof(longjmp) longjmp_ifunc; --extern __typeof(siglongjmp) siglongjmp_ifunc; -+ With an IFUNC resolver, it would be possible to avoid the indirection, -+ but the IFUNC resolver might run before the __libc_longjmp symbol has -+ been relocated, in which case the IFUNC resolver would not be able to -+ provide the correct address. */ - --# else /* !HAVE_IFUNC */ -+#if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_22) - - static void __attribute__ ((noreturn, used)) - longjmp_compat (jmp_buf env, int val) -@@ -47,14 +40,10 @@ longjmp_compat (jmp_buf env, int val) - __libc_longjmp (env, val); - } - --# define DEFINE_LONGJMP(name) strong_alias (longjmp_compat, name) -- --# endif /* HAVE_IFUNC */ -- --DEFINE_LONGJMP (longjmp_ifunc) --compat_symbol (libpthread, longjmp_ifunc, longjmp, GLIBC_2_0); -+strong_alias (longjmp_compat, longjmp_alias) -+compat_symbol (libpthread, longjmp_alias, longjmp, GLIBC_2_0); - --strong_alias (longjmp_ifunc, siglongjmp_ifunc) --compat_symbol (libpthread, siglongjmp_ifunc, siglongjmp, GLIBC_2_0); -+strong_alias (longjmp_alias, siglongjmp_alias) -+compat_symbol (libpthread, siglongjmp_alias, siglongjmp, GLIBC_2_0); - - #endif -diff --git a/nptl/pt-system.c b/nptl/pt-system.c -index f8ca6ba0d9..b30ddf2b39 100644 ---- a/nptl/pt-system.c -+++ b/nptl/pt-system.c -@@ -25,29 +25,21 @@ - libpthread, but the historical ABI requires it. For static linking, - there is no need to provide anything here--the libc version will be - linked in. For shared library ABI compatibility, there must be a -- 'system' symbol in libpthread.so; so we define it using IFUNC to -- redirect to the libc function. */ -+ 'system' symbol in libpthread.so. - --#if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_22) -- --# if HAVE_IFUNC -- --extern __typeof(system) system_ifunc; --# undef INIT_ARCH --# define INIT_ARCH() --libc_ifunc (system_ifunc, &__libc_system) -+ With an IFUNC resolver, it would be possible to avoid the indirection, -+ but the IFUNC resolver might run before the __libc_system symbol has -+ been relocated, in which case the IFUNC resolver would not be able to -+ provide the correct address. */ - --# else /* !HAVE_IFUNC */ -+#if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_22) - - static int __attribute__ ((used)) - system_compat (const char *line) - { - return __libc_system (line); - } --strong_alias (system_compat, system_ifunc) -- --# endif /* HAVE_IFUNC */ -- --compat_symbol (libpthread, system_ifunc, system, GLIBC_2_0); -+strong_alias (system_compat, system_alias) -+compat_symbol (libpthread, system_alias, system, GLIBC_2_0); - - #endif -diff --git a/nptl/pthread_mutex_lock.c b/nptl/pthread_mutex_lock.c -index dc9ca4c476..4425927c30 100644 ---- a/nptl/pthread_mutex_lock.c -+++ b/nptl/pthread_mutex_lock.c -@@ -197,11 +197,14 @@ __pthread_mutex_lock_full (pthread_mutex_t *mutex) - { - /* Try to acquire the lock through a CAS from 0 (not acquired) to - our TID | assume_other_futex_waiters. */ -- if (__glibc_likely ((oldval == 0) -- && (atomic_compare_and_exchange_bool_acq -- (&mutex->__data.__lock, -- id | assume_other_futex_waiters, 0) == 0))) -- break; -+ if (__glibc_likely (oldval == 0)) -+ { -+ oldval -+ = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock, -+ id | assume_other_futex_waiters, 0); -+ if (__glibc_likely (oldval == 0)) -+ break; -+ } - - if ((oldval & FUTEX_OWNER_DIED) != 0) - { -diff --git a/nptl/pthread_mutex_timedlock.c b/nptl/pthread_mutex_timedlock.c -index a4beb7b0dc..dd88cc4ec9 100644 ---- a/nptl/pthread_mutex_timedlock.c -+++ b/nptl/pthread_mutex_timedlock.c -@@ -154,11 +154,14 @@ pthread_mutex_timedlock (pthread_mutex_t *mutex, - { - /* Try to acquire the lock through a CAS from 0 (not acquired) to - our TID | assume_other_futex_waiters. */ -- if (__glibc_likely ((oldval == 0) -- && (atomic_compare_and_exchange_bool_acq -- (&mutex->__data.__lock, -- id | assume_other_futex_waiters, 0) == 0))) -- break; -+ if (__glibc_likely (oldval == 0)) -+ { -+ oldval -+ = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock, -+ id | assume_other_futex_waiters, 0); -+ if (__glibc_likely (oldval == 0)) -+ break; -+ } - - if ((oldval & FUTEX_OWNER_DIED) != 0) - { -diff --git a/nptl/pthread_rwlock_common.c b/nptl/pthread_rwlock_common.c -index 256508ca2a..846687e1cf 100644 ---- a/nptl/pthread_rwlock_common.c -+++ b/nptl/pthread_rwlock_common.c -@@ -55,7 +55,6 @@ - lock acquisition attempts, so that new incoming readers do not prolong a - phase in which readers have acquired the lock. - -- - The main components of the rwlock are a writer-only lock that allows only - one of the concurrent writers to be the primary writer, and a - single-writer-multiple-readers lock that decides between read phases, in -@@ -70,15 +69,16 @@ - --------------------------- - #1 0 0 0 0 Lock is idle (and in a read phase). - #2 0 0 >0 0 Readers have acquired the lock. -- #3 0 1 0 0 Lock is not acquired; a writer is waiting for a write -- phase to start or will try to start one. -+ #3 0 1 0 0 Lock is not acquired; a writer will try to start a -+ write phase. - #4 0 1 >0 0 Readers have acquired the lock; a writer is waiting - and explicit hand-over to the writer is required. - #4a 0 1 >0 1 Same as #4 except that there are further readers - waiting because the writer is to be preferred. - #5 1 0 0 0 Lock is idle (and in a write phase). -- #6 1 0 >0 0 Write phase; readers are waiting for a read phase to -- start or will try to start one. -+ #6 1 0 >0 0 Write phase; readers will try to start a read phase -+ (requires explicit hand-over to all readers that -+ do not start the read phase). - #7 1 1 0 0 Lock is acquired by a writer. - #8 1 1 >0 0 Lock acquired by a writer and readers are waiting; - explicit hand-over to the readers is required. -@@ -375,9 +375,9 @@ __pthread_rwlock_rdlock_full (pthread_rwlock_t *rwlock, - complexity. */ - if (__glibc_likely ((r & PTHREAD_RWLOCK_WRPHASE) == 0)) - return 0; -- -- /* If there is no primary writer but we are in a write phase, we can try -- to install a read phase ourself. */ -+ /* Otherwise, if we were in a write phase (states #6 or #8), we must wait -+ for explicit hand-over of the read phase; the only exception is if we -+ can start a read phase if there is no primary writer currently. */ - while (((r & PTHREAD_RWLOCK_WRPHASE) != 0) - && ((r & PTHREAD_RWLOCK_WRLOCKED) == 0)) - { -@@ -390,15 +390,18 @@ __pthread_rwlock_rdlock_full (pthread_rwlock_t *rwlock, - { - /* We started the read phase, so we are also responsible for - updating the write-phase futex. Relaxed MO is sufficient. -- Note that there can be no other reader that we have to wake -- because all other readers will see the read phase started by us -- (or they will try to start it themselves); if a writer started -- the read phase, we cannot have started it. Furthermore, we -- cannot discard a PTHREAD_RWLOCK_FUTEX_USED flag because we will -- overwrite the value set by the most recent writer (or the readers -- before it in case of explicit hand-over) and we know that there -- are no waiting readers. */ -- atomic_store_relaxed (&rwlock->__data.__wrphase_futex, 0); -+ We have to do the same steps as a writer would when handing -+ over the read phase to us because other readers cannot -+ distinguish between us and the writer; this includes -+ explicit hand-over and potentially having to wake other readers -+ (but we can pretend to do the setting and unsetting of WRLOCKED -+ atomically, and thus can skip this step). */ -+ if ((atomic_exchange_relaxed (&rwlock->__data.__wrphase_futex, 0) -+ & PTHREAD_RWLOCK_FUTEX_USED) != 0) -+ { -+ int private = __pthread_rwlock_get_private (rwlock); -+ futex_wake (&rwlock->__data.__wrphase_futex, INT_MAX, private); -+ } - return 0; - } - else -@@ -407,102 +410,98 @@ __pthread_rwlock_rdlock_full (pthread_rwlock_t *rwlock, - } - } - -- if ((r & PTHREAD_RWLOCK_WRPHASE) != 0) -+ /* We were in a write phase but did not install the read phase. We cannot -+ distinguish between a writer and another reader starting the read phase, -+ so we must wait for explicit hand-over via __wrphase_futex. -+ However, __wrphase_futex might not have been set to 1 yet (either -+ because explicit hand-over to the writer is still ongoing, or because -+ the writer has started the write phase but has not yet updated -+ __wrphase_futex). The least recent value of __wrphase_futex we can -+ read from here is the modification of the last read phase (because -+ we synchronize with the last reader in this read phase through -+ __readers; see the use of acquire MO on the fetch_add above). -+ Therefore, if we observe a value of 0 for __wrphase_futex, we need -+ to subsequently check that __readers now indicates a read phase; we -+ need to use acquire MO for this so that if we observe a read phase, -+ we will also see the modification of __wrphase_futex by the previous -+ writer. We then need to load __wrphase_futex again and continue to -+ wait if it is not 0, so that we do not skip explicit hand-over. -+ Relaxed MO is sufficient for the load from __wrphase_futex because -+ we just use it as an indicator for when we can proceed; we use -+ __readers and the acquire MO accesses to it to eventually read from -+ the proper stores to __wrphase_futex. */ -+ unsigned int wpf; -+ bool ready = false; -+ for (;;) - { -- /* We are in a write phase, and there must be a primary writer because -- of the previous loop. Block until the primary writer gives up the -- write phase. This case requires explicit hand-over using -- __wrphase_futex. -- However, __wrphase_futex might not have been set to 1 yet (either -- because explicit hand-over to the writer is still ongoing, or because -- the writer has started the write phase but does not yet have updated -- __wrphase_futex). The least recent value of __wrphase_futex we can -- read from here is the modification of the last read phase (because -- we synchronize with the last reader in this read phase through -- __readers; see the use of acquire MO on the fetch_add above). -- Therefore, if we observe a value of 0 for __wrphase_futex, we need -- to subsequently check that __readers now indicates a read phase; we -- need to use acquire MO for this so that if we observe a read phase, -- we will also see the modification of __wrphase_futex by the previous -- writer. We then need to load __wrphase_futex again and continue to -- wait if it is not 0, so that we do not skip explicit hand-over. -- Relaxed MO is sufficient for the load from __wrphase_futex because -- we just use it as an indicator for when we can proceed; we use -- __readers and the acquire MO accesses to it to eventually read from -- the proper stores to __wrphase_futex. */ -- unsigned int wpf; -- bool ready = false; -- for (;;) -+ while (((wpf = atomic_load_relaxed (&rwlock->__data.__wrphase_futex)) -+ | PTHREAD_RWLOCK_FUTEX_USED) == (1 | PTHREAD_RWLOCK_FUTEX_USED)) - { -- while (((wpf = atomic_load_relaxed (&rwlock->__data.__wrphase_futex)) -- | PTHREAD_RWLOCK_FUTEX_USED) == (1 | PTHREAD_RWLOCK_FUTEX_USED)) -+ int private = __pthread_rwlock_get_private (rwlock); -+ if (((wpf & PTHREAD_RWLOCK_FUTEX_USED) == 0) -+ && !atomic_compare_exchange_weak_relaxed -+ (&rwlock->__data.__wrphase_futex, -+ &wpf, wpf | PTHREAD_RWLOCK_FUTEX_USED)) -+ continue; -+ int err = futex_abstimed_wait (&rwlock->__data.__wrphase_futex, -+ 1 | PTHREAD_RWLOCK_FUTEX_USED, abstime, private); -+ if (err == ETIMEDOUT) - { -- int private = __pthread_rwlock_get_private (rwlock); -- if (((wpf & PTHREAD_RWLOCK_FUTEX_USED) == 0) -- && !atomic_compare_exchange_weak_relaxed -- (&rwlock->__data.__wrphase_futex, -- &wpf, wpf | PTHREAD_RWLOCK_FUTEX_USED)) -- continue; -- int err = futex_abstimed_wait (&rwlock->__data.__wrphase_futex, -- 1 | PTHREAD_RWLOCK_FUTEX_USED, abstime, private); -- if (err == ETIMEDOUT) -+ /* If we timed out, we need to unregister. If no read phase -+ has been installed while we waited, we can just decrement -+ the number of readers. Otherwise, we just acquire the -+ lock, which is allowed because we give no precise timing -+ guarantees, and because the timeout is only required to -+ be in effect if we would have had to wait for other -+ threads (e.g., if futex_wait would time-out immediately -+ because the given absolute time is in the past). */ -+ r = atomic_load_relaxed (&rwlock->__data.__readers); -+ while ((r & PTHREAD_RWLOCK_WRPHASE) != 0) - { -- /* If we timed out, we need to unregister. If no read phase -- has been installed while we waited, we can just decrement -- the number of readers. Otherwise, we just acquire the -- lock, which is allowed because we give no precise timing -- guarantees, and because the timeout is only required to -- be in effect if we would have had to wait for other -- threads (e.g., if futex_wait would time-out immediately -- because the given absolute time is in the past). */ -- r = atomic_load_relaxed (&rwlock->__data.__readers); -- while ((r & PTHREAD_RWLOCK_WRPHASE) != 0) -- { -- /* We don't need to make anything else visible to -- others besides unregistering, so relaxed MO is -- sufficient. */ -- if (atomic_compare_exchange_weak_relaxed -- (&rwlock->__data.__readers, &r, -- r - (1 << PTHREAD_RWLOCK_READER_SHIFT))) -- return ETIMEDOUT; -- /* TODO Back-off. */ -- } -- /* Use the acquire MO fence to mirror the steps taken in the -- non-timeout case. Note that the read can happen both -- in the atomic_load above as well as in the failure case -- of the CAS operation. */ -- atomic_thread_fence_acquire (); -- /* We still need to wait for explicit hand-over, but we must -- not use futex_wait anymore because we would just time out -- in this case and thus make the spin-waiting we need -- unnecessarily expensive. */ -- while ((atomic_load_relaxed (&rwlock->__data.__wrphase_futex) -- | PTHREAD_RWLOCK_FUTEX_USED) -- == (1 | PTHREAD_RWLOCK_FUTEX_USED)) -- { -- /* TODO Back-off? */ -- } -- ready = true; -- break; -+ /* We don't need to make anything else visible to -+ others besides unregistering, so relaxed MO is -+ sufficient. */ -+ if (atomic_compare_exchange_weak_relaxed -+ (&rwlock->__data.__readers, &r, -+ r - (1 << PTHREAD_RWLOCK_READER_SHIFT))) -+ return ETIMEDOUT; -+ /* TODO Back-off. */ - } -- /* If we got interrupted (EINTR) or the futex word does not have the -- expected value (EAGAIN), retry. */ -+ /* Use the acquire MO fence to mirror the steps taken in the -+ non-timeout case. Note that the read can happen both -+ in the atomic_load above as well as in the failure case -+ of the CAS operation. */ -+ atomic_thread_fence_acquire (); -+ /* We still need to wait for explicit hand-over, but we must -+ not use futex_wait anymore because we would just time out -+ in this case and thus make the spin-waiting we need -+ unnecessarily expensive. */ -+ while ((atomic_load_relaxed (&rwlock->__data.__wrphase_futex) -+ | PTHREAD_RWLOCK_FUTEX_USED) -+ == (1 | PTHREAD_RWLOCK_FUTEX_USED)) -+ { -+ /* TODO Back-off? */ -+ } -+ ready = true; -+ break; - } -- if (ready) -- /* See below. */ -- break; -- /* We need acquire MO here so that we synchronize with the lock -- release of the writer, and so that we observe a recent value of -- __wrphase_futex (see below). */ -- if ((atomic_load_acquire (&rwlock->__data.__readers) -- & PTHREAD_RWLOCK_WRPHASE) == 0) -- /* We are in a read phase now, so the least recent modification of -- __wrphase_futex we can read from is the store by the writer -- with value 1. Thus, only now we can assume that if we observe -- a value of 0, explicit hand-over is finished. Retry the loop -- above one more time. */ -- ready = true; -+ /* If we got interrupted (EINTR) or the futex word does not have the -+ expected value (EAGAIN), retry. */ - } -+ if (ready) -+ /* See below. */ -+ break; -+ /* We need acquire MO here so that we synchronize with the lock -+ release of the writer, and so that we observe a recent value of -+ __wrphase_futex (see below). */ -+ if ((atomic_load_acquire (&rwlock->__data.__readers) -+ & PTHREAD_RWLOCK_WRPHASE) == 0) -+ /* We are in a read phase now, so the least recent modification of -+ __wrphase_futex we can read from is the store by the writer -+ with value 1. Thus, only now we can assume that if we observe -+ a value of 0, explicit hand-over is finished. Retry the loop -+ above one more time. */ -+ ready = true; - } - - return 0; -@@ -741,10 +740,23 @@ __pthread_rwlock_wrlock_full (pthread_rwlock_t *rwlock, - r = atomic_load_relaxed (&rwlock->__data.__readers); - } - /* Our snapshot of __readers is up-to-date at this point because we -- either set WRLOCKED using a CAS or were handed over WRLOCKED from -+ either set WRLOCKED using a CAS (and update r accordingly below, -+ which was used as expected value for the CAS) or got WRLOCKED from - another writer whose snapshot of __readers we inherit. */ -+ r |= PTHREAD_RWLOCK_WRLOCKED; - } - -+ /* We are the primary writer; enable blocking on __writers_futex. Relaxed -+ MO is sufficient for futex words; acquire MO on the previous -+ modifications of __readers ensures that this store happens after the -+ store of value 0 by the previous primary writer. */ -+ atomic_store_relaxed (&rwlock->__data.__writers_futex, -+ 1 | (may_share_futex_used_flag ? PTHREAD_RWLOCK_FUTEX_USED : 0)); -+ -+ /* If we are in a write phase, we have acquired the lock. */ -+ if ((r & PTHREAD_RWLOCK_WRPHASE) != 0) -+ goto done; -+ - /* If we are in a read phase and there are no readers, try to start a write - phase. */ - while (((r & PTHREAD_RWLOCK_WRPHASE) == 0) -@@ -758,166 +770,156 @@ __pthread_rwlock_wrlock_full (pthread_rwlock_t *rwlock, - &r, r | PTHREAD_RWLOCK_WRPHASE)) - { - /* We have started a write phase, so need to enable readers to wait. -- See the similar case in__pthread_rwlock_rdlock_full. */ -+ See the similar case in __pthread_rwlock_rdlock_full. Unlike in -+ that similar case, we are the (only) primary writer and so do -+ not need to wake another writer. */ - atomic_store_relaxed (&rwlock->__data.__wrphase_futex, 1); -- /* Make sure we fall through to the end of the function. */ -- r |= PTHREAD_RWLOCK_WRPHASE; -- break; -+ -+ goto done; - } - /* TODO Back-off. */ - } - -- /* We are the primary writer; enable blocking on __writers_futex. Relaxed -- MO is sufficient for futex words; acquire MO on the previous -- modifications of __readers ensures that this store happens after the -- store of value 0 by the previous primary writer. */ -- atomic_store_relaxed (&rwlock->__data.__writers_futex, -- 1 | (may_share_futex_used_flag ? PTHREAD_RWLOCK_FUTEX_USED : 0)); -- -- if (__glibc_unlikely ((r & PTHREAD_RWLOCK_WRPHASE) == 0)) -+ /* We became the primary writer in a read phase and there were readers when -+ we did (because of the previous loop). Thus, we have to wait for -+ explicit hand-over from one of these readers. -+ We basically do the same steps as for the similar case in -+ __pthread_rwlock_rdlock_full, except that we additionally might try -+ to directly hand over to another writer and need to wake up -+ other writers or waiting readers (i.e., PTHREAD_RWLOCK_RWAITING). */ -+ unsigned int wpf; -+ bool ready = false; -+ for (;;) - { -- /* We are not in a read phase and there are readers (because of the -- previous loop). Thus, we have to wait for explicit hand-over from -- one of these readers. -- We basically do the same steps as for the similar case in -- __pthread_rwlock_rdlock_full, except that we additionally might try -- to directly hand over to another writer and need to wake up -- other writers or waiting readers (i.e., PTHREAD_RWLOCK_RWAITING). */ -- unsigned int wpf; -- bool ready = false; -- for (;;) -+ while (((wpf = atomic_load_relaxed (&rwlock->__data.__wrphase_futex)) -+ | PTHREAD_RWLOCK_FUTEX_USED) == PTHREAD_RWLOCK_FUTEX_USED) - { -- while (((wpf = atomic_load_relaxed (&rwlock->__data.__wrphase_futex)) -- | PTHREAD_RWLOCK_FUTEX_USED) == PTHREAD_RWLOCK_FUTEX_USED) -+ int private = __pthread_rwlock_get_private (rwlock); -+ if (((wpf & PTHREAD_RWLOCK_FUTEX_USED) == 0) -+ && !atomic_compare_exchange_weak_relaxed -+ (&rwlock->__data.__wrphase_futex, &wpf, -+ PTHREAD_RWLOCK_FUTEX_USED)) -+ continue; -+ int err = futex_abstimed_wait (&rwlock->__data.__wrphase_futex, -+ PTHREAD_RWLOCK_FUTEX_USED, abstime, private); -+ if (err == ETIMEDOUT) - { -- int private = __pthread_rwlock_get_private (rwlock); -- if (((wpf & PTHREAD_RWLOCK_FUTEX_USED) == 0) -- && !atomic_compare_exchange_weak_relaxed -- (&rwlock->__data.__wrphase_futex, &wpf, -- PTHREAD_RWLOCK_FUTEX_USED)) -- continue; -- int err = futex_abstimed_wait (&rwlock->__data.__wrphase_futex, -- PTHREAD_RWLOCK_FUTEX_USED, abstime, private); -- if (err == ETIMEDOUT) -+ if (rwlock->__data.__flags -+ != PTHREAD_RWLOCK_PREFER_READER_NP) - { -- if (rwlock->__data.__flags -- != PTHREAD_RWLOCK_PREFER_READER_NP) -- { -- /* We try writer--writer hand-over. */ -- unsigned int w = atomic_load_relaxed -- (&rwlock->__data.__writers); -- if (w != 0) -- { -- /* We are about to hand over WRLOCKED, so we must -- release __writers_futex too; otherwise, we'd have -- a pending store, which could at least prevent -- other threads from waiting using the futex -- because it could interleave with the stores -- by subsequent writers. In turn, this means that -- we have to clean up when we do not hand over -- WRLOCKED. -- Release MO so that another writer that gets -- WRLOCKED from us can take over our view of -- __readers. */ -- unsigned int wf = atomic_exchange_relaxed -- (&rwlock->__data.__writers_futex, 0); -- while (w != 0) -- { -- if (atomic_compare_exchange_weak_release -- (&rwlock->__data.__writers, &w, -- w | PTHREAD_RWLOCK_WRHANDOVER)) -- { -- /* Wake other writers. */ -- if ((wf & PTHREAD_RWLOCK_FUTEX_USED) != 0) -- futex_wake -- (&rwlock->__data.__writers_futex, 1, -- private); -- return ETIMEDOUT; -- } -- /* TODO Back-off. */ -- } -- /* We still own WRLOCKED and someone else might set -- a write phase concurrently, so enable waiting -- again. Make sure we don't loose the flag that -- signals whether there are threads waiting on -- this futex. */ -- atomic_store_relaxed -- (&rwlock->__data.__writers_futex, wf); -- } -- } -- /* If we timed out and we are not in a write phase, we can -- just stop being a primary writer. Otherwise, we just -- acquire the lock. */ -- r = atomic_load_relaxed (&rwlock->__data.__readers); -- if ((r & PTHREAD_RWLOCK_WRPHASE) == 0) -+ /* We try writer--writer hand-over. */ -+ unsigned int w = atomic_load_relaxed -+ (&rwlock->__data.__writers); -+ if (w != 0) - { -- /* We are about to release WRLOCKED, so we must release -- __writers_futex too; see the handling of -- writer--writer hand-over above. */ -+ /* We are about to hand over WRLOCKED, so we must -+ release __writers_futex too; otherwise, we'd have -+ a pending store, which could at least prevent -+ other threads from waiting using the futex -+ because it could interleave with the stores -+ by subsequent writers. In turn, this means that -+ we have to clean up when we do not hand over -+ WRLOCKED. -+ Release MO so that another writer that gets -+ WRLOCKED from us can take over our view of -+ __readers. */ - unsigned int wf = atomic_exchange_relaxed - (&rwlock->__data.__writers_futex, 0); -- while ((r & PTHREAD_RWLOCK_WRPHASE) == 0) -+ while (w != 0) - { -- /* While we don't need to make anything from a -- caller's critical section visible to other -- threads, we need to ensure that our changes to -- __writers_futex are properly ordered. -- Therefore, use release MO to synchronize with -- subsequent primary writers. Also wake up any -- waiting readers as they are waiting because of -- us. */ - if (atomic_compare_exchange_weak_release -- (&rwlock->__data.__readers, &r, -- (r ^ PTHREAD_RWLOCK_WRLOCKED) -- & ~(unsigned int) PTHREAD_RWLOCK_RWAITING)) -+ (&rwlock->__data.__writers, &w, -+ w | PTHREAD_RWLOCK_WRHANDOVER)) - { - /* Wake other writers. */ - if ((wf & PTHREAD_RWLOCK_FUTEX_USED) != 0) - futex_wake (&rwlock->__data.__writers_futex, -- 1, private); -- /* Wake waiting readers. */ -- if ((r & PTHREAD_RWLOCK_RWAITING) != 0) -- futex_wake (&rwlock->__data.__readers, -- INT_MAX, private); -+ 1, private); - return ETIMEDOUT; - } -+ /* TODO Back-off. */ - } -- /* We still own WRLOCKED and someone else might set a -- write phase concurrently, so enable waiting again. -- Make sure we don't loose the flag that signals -- whether there are threads waiting on this futex. */ -- atomic_store_relaxed (&rwlock->__data.__writers_futex, -- wf); -+ /* We still own WRLOCKED and someone else might set -+ a write phase concurrently, so enable waiting -+ again. Make sure we don't loose the flag that -+ signals whether there are threads waiting on -+ this futex. */ -+ atomic_store_relaxed -+ (&rwlock->__data.__writers_futex, wf); - } -- /* Use the acquire MO fence to mirror the steps taken in the -- non-timeout case. Note that the read can happen both -- in the atomic_load above as well as in the failure case -- of the CAS operation. */ -- atomic_thread_fence_acquire (); -- /* We still need to wait for explicit hand-over, but we must -- not use futex_wait anymore. */ -- while ((atomic_load_relaxed -- (&rwlock->__data.__wrphase_futex) -- | PTHREAD_RWLOCK_FUTEX_USED) -- == PTHREAD_RWLOCK_FUTEX_USED) -+ } -+ /* If we timed out and we are not in a write phase, we can -+ just stop being a primary writer. Otherwise, we just -+ acquire the lock. */ -+ r = atomic_load_relaxed (&rwlock->__data.__readers); -+ if ((r & PTHREAD_RWLOCK_WRPHASE) == 0) -+ { -+ /* We are about to release WRLOCKED, so we must release -+ __writers_futex too; see the handling of -+ writer--writer hand-over above. */ -+ unsigned int wf = atomic_exchange_relaxed -+ (&rwlock->__data.__writers_futex, 0); -+ while ((r & PTHREAD_RWLOCK_WRPHASE) == 0) - { -- /* TODO Back-off. */ -+ /* While we don't need to make anything from a -+ caller's critical section visible to other -+ threads, we need to ensure that our changes to -+ __writers_futex are properly ordered. -+ Therefore, use release MO to synchronize with -+ subsequent primary writers. Also wake up any -+ waiting readers as they are waiting because of -+ us. */ -+ if (atomic_compare_exchange_weak_release -+ (&rwlock->__data.__readers, &r, -+ (r ^ PTHREAD_RWLOCK_WRLOCKED) -+ & ~(unsigned int) PTHREAD_RWLOCK_RWAITING)) -+ { -+ /* Wake other writers. */ -+ if ((wf & PTHREAD_RWLOCK_FUTEX_USED) != 0) -+ futex_wake (&rwlock->__data.__writers_futex, -+ 1, private); -+ /* Wake waiting readers. */ -+ if ((r & PTHREAD_RWLOCK_RWAITING) != 0) -+ futex_wake (&rwlock->__data.__readers, -+ INT_MAX, private); -+ return ETIMEDOUT; -+ } - } -- ready = true; -- break; -+ /* We still own WRLOCKED and someone else might set a -+ write phase concurrently, so enable waiting again. -+ Make sure we don't loose the flag that signals -+ whether there are threads waiting on this futex. */ -+ atomic_store_relaxed (&rwlock->__data.__writers_futex, wf); - } -- /* If we got interrupted (EINTR) or the futex word does not have -- the expected value (EAGAIN), retry. */ -+ /* Use the acquire MO fence to mirror the steps taken in the -+ non-timeout case. Note that the read can happen both -+ in the atomic_load above as well as in the failure case -+ of the CAS operation. */ -+ atomic_thread_fence_acquire (); -+ /* We still need to wait for explicit hand-over, but we must -+ not use futex_wait anymore. */ -+ while ((atomic_load_relaxed -+ (&rwlock->__data.__wrphase_futex) -+ | PTHREAD_RWLOCK_FUTEX_USED) -+ == PTHREAD_RWLOCK_FUTEX_USED) -+ { -+ /* TODO Back-off. */ -+ } -+ ready = true; -+ break; - } -- /* See pthread_rwlock_rdlock_full. */ -- if (ready) -- break; -- if ((atomic_load_acquire (&rwlock->__data.__readers) -- & PTHREAD_RWLOCK_WRPHASE) != 0) -- ready = true; -+ /* If we got interrupted (EINTR) or the futex word does not have -+ the expected value (EAGAIN), retry. */ - } -+ /* See pthread_rwlock_rdlock_full. */ -+ if (ready) -+ break; -+ if ((atomic_load_acquire (&rwlock->__data.__readers) -+ & PTHREAD_RWLOCK_WRPHASE) != 0) -+ ready = true; - } - -+ done: - atomic_store_relaxed (&rwlock->__data.__cur_writer, - THREAD_GETMEM (THREAD_SELF, tid)); - return 0; -diff --git a/nptl/tst-compat-forwarder-mod.c b/nptl/tst-compat-forwarder-mod.c -new file mode 100644 -index 0000000000..823bfa22de ---- /dev/null -+++ b/nptl/tst-compat-forwarder-mod.c -@@ -0,0 +1,28 @@ -+/* 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 -+ . */ -+ -+/* Call the function system through a statically initialized pointer. */ -+ -+#include -+ -+int (*system_function) (const char *) = system; -+ -+void -+call_system (void) -+{ -+ system_function (NULL); -+} -diff --git a/nptl/tst-compat-forwarder.c b/nptl/tst-compat-forwarder.c -new file mode 100644 -index 0000000000..f96806b7fe ---- /dev/null -+++ b/nptl/tst-compat-forwarder.c -@@ -0,0 +1,35 @@ -+/* 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 -+ . */ -+ -+/* Test that the compat forwaders in libpthread work correctly. */ -+ -+#include -+ -+extern void call_system (void); -+ -+int -+do_test (void) -+{ -+ /* Calling the system function from a shared library that is not linked -+ against libpthread, when the main program is linked against -+ libpthread, should not crash. */ -+ call_system (); -+ -+ return 0; -+} -+ -+#include -diff --git a/nptl/tst-mutex7.c b/nptl/tst-mutex7.c -index a11afdba5e..08fe251eeb 100644 ---- a/nptl/tst-mutex7.c -+++ b/nptl/tst-mutex7.c -@@ -22,25 +22,41 @@ - #include - #include - -- -+/* This test is a template for other tests to use. Other tests define -+ the following macros to change the behaviour of the template test. -+ The test is very simple, it configures N threads given the parameters -+ below and then proceeds to go through mutex lock and unlock -+ operations in each thread as described before for the thread -+ function. */ - #ifndef TYPE - # define TYPE PTHREAD_MUTEX_DEFAULT - #endif -- -+#ifndef ROBUST -+# define ROBUST PTHREAD_MUTEX_STALLED -+#endif -+#ifndef DELAY_NSEC -+# define DELAY_NSEC 11000 -+#endif -+#ifndef ROUNDS -+# define ROUNDS 1000 -+#endif -+#ifndef N -+# define N 100 -+#endif - - static pthread_mutex_t lock; - -- --#define ROUNDS 1000 --#define N 100 -- -- -+/* Each thread locks and the subsequently unlocks the lock, yielding -+ the smallest critical section possible. After the unlock the thread -+ waits DELAY_NSEC nanoseconds before doing the lock and unlock again. -+ Every thread does this ROUNDS times. The lock and unlock are -+ checked for errors. */ - static void * - tf (void *arg) - { - int nr = (long int) arg; - int cnt; -- struct timespec ts = { .tv_sec = 0, .tv_nsec = 11000 }; -+ struct timespec ts = { .tv_sec = 0, .tv_nsec = DELAY_NSEC }; - - for (cnt = 0; cnt < ROUNDS; ++cnt) - { -@@ -56,13 +72,16 @@ tf (void *arg) - return (void *) 1l; - } - -- nanosleep (&ts, NULL); -+ if ((ts.tv_sec > 0) || (ts.tv_nsec > 0)) -+ nanosleep (&ts, NULL); - } - - return NULL; - } - -- -+/* Setup and run N threads, where each thread does as described -+ in the above thread function. The threads are given a minimal 1MiB -+ stack since they don't do anything between the lock and unlock. */ - static int - do_test (void) - { -@@ -80,6 +99,12 @@ do_test (void) - exit (1); - } - -+ if (pthread_mutexattr_setrobust (&a, ROBUST) != 0) -+ { -+ puts ("mutexattr_setrobust failed"); -+ exit (1); -+ } -+ - #ifdef ENABLE_PI - if (pthread_mutexattr_setprotocol (&a, PTHREAD_PRIO_INHERIT) != 0) - { -diff --git a/nptl/tst-mutex7robust.c b/nptl/tst-mutex7robust.c -new file mode 100644 -index 0000000000..8221a61d29 ---- /dev/null -+++ b/nptl/tst-mutex7robust.c -@@ -0,0 +1,7 @@ -+/* Bug 21778: Fix oversight in robust mutex lock acquisition. */ -+#define TYPE PTHREAD_MUTEX_NORMAL -+#define ROBUST PTHREAD_MUTEX_ROBUST -+#define DELAY_NSEC 0 -+#define ROUNDS 1000 -+#define N 32 -+#include "tst-mutex7.c" -diff --git a/nptl/tst-rwlock20.c b/nptl/tst-rwlock20.c -new file mode 100644 -index 0000000000..4aeea2b8f5 ---- /dev/null -+++ b/nptl/tst-rwlock20.c -@@ -0,0 +1,116 @@ -+/* Test program for a read-phase / write-phase explicit hand-over. -+ Copyright (C) 2017 Free Software Foundation, Inc. -+ -+ 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 . */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/* We realy want to set threads to 2 to reproduce this issue. The goal -+ is to have one primary writer and a single reader, and to hit the -+ bug that happens in the interleaving of those two phase transitions. -+ However, on most hardware, adding a second writer seems to help the -+ interleaving happen slightly more often, say 20% of the time. On a -+ 16 core ppc64 machine this fails 100% of the time with an unpatched -+ glibc. On a 8 core x86_64 machine this fails ~93% of the time, but -+ it doesn't fail at all on a 4 core system, so having available -+ unloaded cores makes a big difference in reproducibility. On an 8 -+ core qemu/kvm guest the reproducer reliability drops to ~10%. */ -+#define THREADS 3 -+ -+#define KIND PTHREAD_RWLOCK_PREFER_READER_NP -+ -+static pthread_rwlock_t lock; -+static int done = 0; -+ -+static void* -+tf (void* arg) -+{ -+ while (atomic_load_relaxed (&done) == 0) -+ { -+ int rcnt = 0; -+ int wcnt = 100; -+ if ((uintptr_t) arg == 0) -+ { -+ rcnt = 1; -+ wcnt = 1; -+ } -+ -+ do -+ { -+ if (wcnt) -+ { -+ xpthread_rwlock_wrlock (&lock); -+ xpthread_rwlock_unlock (&lock); -+ wcnt--; -+ } -+ if (rcnt) -+ { -+ xpthread_rwlock_rdlock (&lock); -+ xpthread_rwlock_unlock (&lock); -+ rcnt--; -+ } -+ } -+ while ((atomic_load_relaxed (&done) == 0) && (rcnt + wcnt > 0)); -+ -+ } -+ return NULL; -+} -+ -+ -+ -+static int -+do_test (void) -+{ -+ pthread_t thr[THREADS]; -+ int n; -+ pthread_rwlockattr_t attr; -+ -+ xpthread_rwlockattr_init (&attr); -+ xpthread_rwlockattr_setkind_np (&attr, KIND); -+ -+ xpthread_rwlock_init (&lock, &attr); -+ -+ /* Make standard error the same as standard output. */ -+ dup2 (1, 2); -+ -+ /* Make sure we see all message, even those on stdout. */ -+ setvbuf (stdout, NULL, _IONBF, 0); -+ -+ for (n = 0; n < THREADS; ++n) -+ thr[n] = xpthread_create (NULL, tf, (void *) (uintptr_t) n); -+ -+ struct timespec delay; -+ delay.tv_sec = 10; -+ delay.tv_nsec = 0; -+ nanosleep (&delay, NULL); -+ atomic_store_relaxed (&done, 1); -+ -+ /* Wait for all the threads. */ -+ for (n = 0; n < THREADS; ++n) -+ xpthread_join (thr[n]); -+ -+ return 0; -+} -+ -+#include -diff --git a/posix/Makefile b/posix/Makefile -index 8f23d647c8..ccbfcf3c48 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 \ -@@ -91,7 +91,8 @@ tests := tstgetopt testfnm runtests runptests \ - tst-pathconf tst-getaddrinfo4 tst-rxspencer-no-utf8 \ - tst-fnmatch3 bug-regex36 tst-getaddrinfo5 \ - tst-posix_spawn-fd \ -- tst-posix_fadvise tst-posix_fadvise64 -+ tst-posix_fadvise tst-posix_fadvise64 \ -+ tst-glob-tilde - xtests := bug-ga2 - ifeq (yes,$(build-shared)) - test-srcs := globtest -@@ -134,7 +135,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 - -@@ -341,6 +343,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/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 -+ . -+ -+ Written by Paul Eggert. */ -+ -+#include -+ -+/* 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 c653809118..b2273ea7bc 100644 ---- a/posix/glob.c -+++ b/posix/glob.c -@@ -15,7 +15,7 @@ - License along with the GNU C Library; if not, see - . */ - --#ifdef HAVE_CONFIG_H -+#ifndef _LIBC - # include - #endif - -@@ -27,29 +27,15 @@ - #include - #include - #include -- --/* Outcomment the following line for production quality code. */ --/* #define NDEBUG 1 */ - #include -+#include - --#include /* Needed on stupid SunOS for assert. */ -- --#if !defined _LIBC || !defined GLOB_ONLY_P --#if defined HAVE_UNISTD_H || defined _LIBC --# include --# ifndef POSIX --# ifdef _POSIX_VERSION --# define POSIX --# endif --# endif -+#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ -+# define WINDOWS32 - #endif - --#include -- --#if defined HAVE_STDINT_H || defined _LIBC --# include --#elif !defined UINTPTR_MAX --# define UINTPTR_MAX (~((size_t) 0)) -+#ifndef WINDOWS32 -+# include - #endif - - #include -@@ -57,24 +43,7 @@ - # define __set_errno(val) errno = (val) - #endif - --#if defined HAVE_DIRENT_H || defined __GNU_LIBRARY__ --# include --#else --# define dirent direct --# ifdef HAVE_SYS_NDIR_H --# include --# endif --# ifdef HAVE_SYS_DIR_H --# include --# endif --# ifdef HAVE_NDIR_H --# include --# endif --# ifdef HAVE_VMSDIR_H --# include "vmsdir.h" --# endif /* HAVE_VMSDIR_H */ --#endif -- -+#include - #include - #include - #include -@@ -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 - -+#include -+#include -+ - #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; - -@@ -372,14 +373,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) - return GLOB_NOSPACE; - } -@@ -392,11 +391,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); - flags &= ~GLOB_BRACE; - goto no_brace; -@@ -437,9 +434,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)) - { -@@ -458,9 +453,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) -@@ -476,14 +469,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) - { -@@ -508,11 +503,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int), - } - - filename = pattern; --#ifdef _AMIGA -- dirname = (char *) ""; --#else - dirname = (char *) "."; --#endif - dirlen = 0; - } - } -@@ -536,22 +527,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) -@@ -562,14 +552,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] == '\\') -@@ -602,7 +595,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] == '/' -@@ -612,100 +604,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 -@@ -720,26 +739,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') - { -@@ -754,8 +779,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 -@@ -779,12 +803,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; -@@ -806,7 +833,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 - { -@@ -823,11 +850,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 -@@ -843,7 +870,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; - } -@@ -851,20 +878,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 - { -@@ -877,32 +905,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); - } -@@ -923,7 +951,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 -@@ -931,8 +959,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; - } -@@ -944,24 +971,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. */ -@@ -980,19 +1007,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; -@@ -1006,12 +1032,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; -@@ -1021,7 +1054,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)); -@@ -1067,7 +1101,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; - } - -@@ -1078,19 +1115,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) -@@ -1105,7 +1129,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. */ -@@ -1116,13 +1141,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) -@@ -1134,28 +1160,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; -@@ -1167,7 +1193,8 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int), - else - { - globfree (&dirs); -- return GLOB_NOMATCH; -+ retval = GLOB_NOMATCH; -+ goto out; - } - } - -@@ -1213,7 +1240,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) -@@ -1225,7 +1253,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; - } - } - } -@@ -1250,7 +1279,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; -@@ -1276,32 +1306,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; -@@ -1322,28 +1332,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 -@@ -1351,7 +1357,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) -@@ -1361,7 +1367,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]); -@@ -1371,103 +1377,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). */ -@@ -1478,25 +1438,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))) -@@ -1516,14 +1476,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; - } -@@ -1531,9 +1493,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; -@@ -1555,16 +1519,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) -@@ -1584,19 +1542,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)) - { -@@ -1604,10 +1567,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)) -@@ -1623,6 +1589,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; - } - } - } -@@ -1633,29 +1601,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: -@@ -1671,7 +1637,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; -@@ -1697,7 +1663,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 6cb3d654a8..a515a1c12f 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 -+ . */ -+ -+#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 -+ . */ -+ -+#ifndef _LIBC -+# include -+#endif -+ -+#include -+#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 -+ . */ -+ -+#ifndef _LIBC -+# include -+#endif -+ -+#include -+#include -+ -+/* 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 -+ . */ -+ -+#ifndef _LIBC -+# include -+#endif -+ -+#include -+#include -+ -+/* Free storage allocated in PGLOB by a previous `glob' call. */ -+void -+globfree64 (glob64_t *pglob) -+{ -+} -+libc_hidden_def (globfree64) -diff --git a/posix/globtest.sh b/posix/globtest.sh -index f9cc80b4b5..73f7ae31cc 100755 ---- a/posix/globtest.sh -+++ b/posix/globtest.sh -@@ -47,7 +47,12 @@ testout=${common_objpfx}posix/globtest-out - rm -rf $testdir $testout - mkdir $testdir - --trap 'chmod 777 $testdir/noread; rm -fr $testdir $testout' 1 2 3 15 -+cleanup() { -+ chmod 777 $testdir/noread -+ rm -fr $testdir $testout -+} -+ -+trap cleanup 0 HUP INT QUIT TERM - - echo 1 > $testdir/file1 - echo 2 > $testdir/file2 -@@ -811,8 +816,6 @@ if test $failed -ne 0; then - fi - - if test $result -eq 0; then -- chmod 777 $testdir/noread -- rm -fr $testdir $testout - echo "All OK." > $logfile - fi - -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 -+ . */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/* 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 -diff --git a/resolv/Makefile b/resolv/Makefile -index fdc37edff1..01086d569f 100644 ---- a/resolv/Makefile -+++ b/resolv/Makefile -@@ -46,6 +46,7 @@ tests += \ - tst-res_hconf_reorder \ - tst-res_use_inet6 \ - tst-resolv-basic \ -+ tst-resolv-edns \ - tst-resolv-network \ - tst-resolv-search \ - -@@ -124,6 +125,7 @@ $(objpfx)tst-bug18665-tcp: $(objpfx)libresolv.so $(shared-thread-library) - $(objpfx)tst-bug18665: $(objpfx)libresolv.so $(shared-thread-library) - $(objpfx)tst-res_use_inet6: $(objpfx)libresolv.so $(shared-thread-library) - $(objpfx)tst-resolv-basic: $(objpfx)libresolv.so $(shared-thread-library) -+$(objpfx)tst-resolv-edns: $(objpfx)libresolv.so $(shared-thread-library) - $(objpfx)tst-resolv-network: $(objpfx)libresolv.so $(shared-thread-library) - $(objpfx)tst-resolv-qtypes: $(objpfx)libresolv.so $(shared-thread-library) - $(objpfx)tst-resolv-search: $(objpfx)libresolv.so $(shared-thread-library) -diff --git a/resolv/res_mkquery.c b/resolv/res_mkquery.c -index d80b5318e5..5a0bb1044b 100644 ---- a/resolv/res_mkquery.c -+++ b/resolv/res_mkquery.c -@@ -69,7 +69,7 @@ - #include - #include - #include --#include -+#include - #include - #include - #include -@@ -243,7 +243,30 @@ __res_nopt(res_state statp, - *cp++ = 0; /* "." */ - - NS_PUT16(T_OPT, cp); /* TYPE */ -- NS_PUT16(MIN(anslen, 0xffff), cp); /* CLASS = UDP payload size */ -+ -+ /* Lowering the advertised buffer size based on the actual -+ answer buffer size is desirable because the server will -+ minimize the reply to fit into the UDP packet (and A -+ non-minimal response might not fit the buffer). -+ -+ The RESOLV_EDNS_BUFFER_SIZE limit could still result in TCP -+ fallback and a non-minimal response which has to be -+ hard-truncated in the stub resolver, but this is price to -+ pay for avoiding fragmentation. (This issue does not -+ affect the nss_dns functions because they use the stub -+ resolver in such a way that it allocates a properly sized -+ response buffer.) */ -+ { -+ uint16_t buffer_size; -+ if (anslen < 512) -+ buffer_size = 512; -+ else if (anslen > RESOLV_EDNS_BUFFER_SIZE) -+ buffer_size = RESOLV_EDNS_BUFFER_SIZE; -+ else -+ buffer_size = anslen; -+ NS_PUT16 (buffer_size, cp); -+ } -+ - *cp++ = NOERROR; /* extended RCODE */ - *cp++ = 0; /* EDNS version */ - -@@ -261,4 +284,3 @@ __res_nopt(res_state statp, - - return cp - buf; - } --libresolv_hidden_def (__res_nopt) -diff --git a/resolv/res_query.c b/resolv/res_query.c -index 07dc6f6583..57156d01ec 100644 ---- a/resolv/res_query.c -+++ b/resolv/res_query.c -@@ -77,6 +77,7 @@ - #include - #include - #include -+#include - - /* Options. Leave them on. */ - /* #undef DEBUG */ -@@ -146,7 +147,10 @@ __libc_res_nquery(res_state statp, - if ((oflags & RES_F_EDNS0ERR) == 0 - && (statp->options & (RES_USE_EDNS0|RES_USE_DNSSEC)) != 0) - { -- n = __res_nopt(statp, n, query1, bufsize, anslen / 2); -+ /* Use RESOLV_EDNS_BUFFER_SIZE because the receive -+ buffer can be reallocated. */ -+ n = __res_nopt (statp, n, query1, bufsize, -+ RESOLV_EDNS_BUFFER_SIZE); - if (n < 0) - goto unspec_nomem; - } -@@ -167,8 +171,10 @@ __libc_res_nquery(res_state statp, - if (n > 0 - && (oflags & RES_F_EDNS0ERR) == 0 - && (statp->options & (RES_USE_EDNS0|RES_USE_DNSSEC)) != 0) -- n = __res_nopt(statp, n, query2, bufsize - nused - n, -- anslen / 2); -+ /* Use RESOLV_EDNS_BUFFER_SIZE because the receive -+ buffer can be reallocated. */ -+ n = __res_nopt (statp, n, query2, bufsize, -+ RESOLV_EDNS_BUFFER_SIZE); - nquery2 = n; - } - -@@ -182,7 +188,16 @@ __libc_res_nquery(res_state statp, - if (n > 0 - && (oflags & RES_F_EDNS0ERR) == 0 - && (statp->options & (RES_USE_EDNS0|RES_USE_DNSSEC)) != 0) -- n = __res_nopt(statp, n, query1, bufsize, anslen); -+ { -+ /* Use RESOLV_EDNS_BUFFER_SIZE if the receive buffer -+ can be reallocated. */ -+ size_t advertise; -+ if (answerp == NULL) -+ advertise = anslen; -+ else -+ advertise = RESOLV_EDNS_BUFFER_SIZE; -+ n = __res_nopt (statp, n, query1, bufsize, advertise); -+ } - - nquery1 = n; - } -diff --git a/resolv/resolv-internal.h b/resolv/resolv-internal.h -index 99fc17c609..76fbe2f1a6 100644 ---- a/resolv/resolv-internal.h -+++ b/resolv/resolv-internal.h -@@ -32,4 +32,22 @@ res_use_inet6 (void) - return _res.options & DEPRECATED_RES_USE_INET6; - } - -+enum -+ { -+ /* The advertized EDNS buffer size. The value 1200 is derived -+ from the IPv6 minimum MTU (1280 bytes) minus some arbitrary -+ space for tunneling overhead. If the DNS server does not react -+ to ICMP Fragmentation Needed But DF Set messages, this should -+ avoid all UDP fragments on current networks. Avoiding UDP -+ fragments is desirable because it prevents fragmentation-based -+ spoofing attacks because the randomness in a DNS packet is -+ concentrated in the first fragment (with the headers) and does -+ not protect subsequent fragments. */ -+ RESOLV_EDNS_BUFFER_SIZE = 1200, -+ }; -+ -+/* Add an OPT record to a DNS query. */ -+int __res_nopt (res_state, int n0, unsigned char *buf, int buflen, -+ int anslen) attribute_hidden; -+ - #endif /* _RESOLV_INTERNAL_H */ -diff --git a/resolv/tst-resolv-edns.c b/resolv/tst-resolv-edns.c -new file mode 100644 -index 0000000000..f17dbc3450 ---- /dev/null -+++ b/resolv/tst-resolv-edns.c -@@ -0,0 +1,501 @@ -+/* Test EDNS handling in the stub resolver. -+ Copyright (C) 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 -+ . */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/* Data produced by a test query. */ -+struct response_data -+{ -+ char *qname; -+ uint16_t qtype; -+ struct resolv_edns_info edns; -+}; -+ -+/* Global array used by put_response and get_response to record -+ response data. The test DNS server returns the index of the array -+ element which contains the actual response data. This enables the -+ test case to return arbitrary amounts of data with the limited -+ number of bits which fit into an IP addres. -+ -+ The volatile specifier is needed because the test case accesses -+ these variables from a callback function called from a function -+ which is marked as __THROW (i.e., a leaf function which actually is -+ not). */ -+static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; -+static struct response_data ** volatile response_data_array; -+volatile static size_t response_data_count; -+ -+/* Extract information from the query, store it in a struct -+ response_data object, and return its index in the -+ response_data_array. */ -+static unsigned int -+put_response (const struct resolv_response_context *ctx, -+ const char *qname, uint16_t qtype) -+{ -+ xpthread_mutex_lock (&mutex); -+ ++response_data_count; -+ /* We only can represent 2**24 indexes in 10.0.0.0/8. */ -+ TEST_VERIFY (response_data_count < (1 << 24)); -+ response_data_array = xrealloc -+ (response_data_array, sizeof (*response_data_array) * response_data_count); -+ unsigned int index = response_data_count - 1; -+ struct response_data *data = xmalloc (sizeof (*data)); -+ *data = (struct response_data) -+ { -+ .qname = xstrdup (qname), -+ .qtype = qtype, -+ .edns = ctx->edns, -+ }; -+ response_data_array[index] = data; -+ xpthread_mutex_unlock (&mutex); -+ return index; -+} -+ -+/* Verify the index into the response_data array and return the data -+ at it. */ -+static struct response_data * -+get_response (unsigned int index) -+{ -+ xpthread_mutex_lock (&mutex); -+ TEST_VERIFY_EXIT (index < response_data_count); -+ struct response_data *result = response_data_array[index]; -+ xpthread_mutex_unlock (&mutex); -+ return result; -+} -+ -+/* Deallocate all response data. */ -+static void -+free_response_data (void) -+{ -+ xpthread_mutex_lock (&mutex); -+ size_t count = response_data_count; -+ struct response_data **array = response_data_array; -+ for (unsigned int i = 0; i < count; ++i) -+ { -+ struct response_data *data = array[i]; -+ free (data->qname); -+ free (data); -+ } -+ free (array); -+ response_data_array = NULL; -+ response_data_count = 0; -+ xpthread_mutex_unlock (&mutex); -+} -+ -+#define EDNS_PROBE_EXAMPLE "edns-probe.example" -+ -+static void -+response (const struct resolv_response_context *ctx, -+ struct resolv_response_builder *b, -+ const char *qname, uint16_t qclass, uint16_t qtype) -+{ -+ TEST_VERIFY_EXIT (qname != NULL); -+ -+ /* The "tcp." prefix can be used to request TCP fallback. */ -+ const char *qname_compare = qname; -+ bool force_tcp; -+ if (strncmp ("tcp.", qname_compare, strlen ("tcp.")) == 0) -+ { -+ force_tcp = true; -+ qname_compare += strlen ("tcp."); -+ } -+ else -+ force_tcp = false; -+ -+ enum {edns_probe} requested_qname; -+ if (strcmp (qname_compare, EDNS_PROBE_EXAMPLE) == 0) -+ requested_qname = edns_probe; -+ else -+ { -+ support_record_failure (); -+ printf ("error: unexpected QNAME: %s\n", qname); -+ return; -+ } -+ TEST_VERIFY_EXIT (qclass == C_IN); -+ struct resolv_response_flags flags = {.tc = force_tcp && !ctx->tcp}; -+ resolv_response_init (b, flags); -+ resolv_response_add_question (b, qname, qclass, qtype); -+ if (flags.tc) -+ return; -+ -+ if (test_verbose) -+ printf ("info: edns=%d payload_size=%d\n", -+ ctx->edns.active, ctx->edns.payload_size); -+ -+ /* Encode the response_data object in multiple address records. -+ Each record carries two bytes of payload data, and an index. */ -+ resolv_response_section (b, ns_s_an); -+ switch (requested_qname) -+ { -+ case edns_probe: -+ { -+ unsigned int index = put_response (ctx, qname, qtype); -+ switch (qtype) -+ { -+ case T_A: -+ { -+ uint32_t addr = htonl (0x0a000000 | index); -+ resolv_response_open_record (b, qname, qclass, qtype, 0); -+ resolv_response_add_data (b, &addr, sizeof (addr)); -+ resolv_response_close_record (b); -+ } -+ break; -+ case T_AAAA: -+ { -+ char addr[16] -+ = {0x20, 0x01, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, -+ index >> 16, index >> 8, index}; -+ resolv_response_open_record (b, qname, qclass, qtype, 0); -+ resolv_response_add_data (b, &addr, sizeof (addr)); -+ resolv_response_close_record (b); -+ } -+ } -+ } -+ break; -+ } -+} -+ -+/* Update *DATA with data from ADDRESS of SIZE. Set the corresponding -+ flag in SHADOW for each byte written. */ -+static struct response_data * -+decode_address (const void *address, size_t size) -+{ -+ switch (size) -+ { -+ case 4: -+ TEST_VERIFY (memcmp (address, "\x0a", 1) == 0); -+ break; -+ case 16: -+ TEST_VERIFY (memcmp (address, "\x20\x01\x0d\xb8", 4) == 0); -+ break; -+ default: -+ FAIL_EXIT1 ("unexpected address size %zu", size); -+ } -+ const unsigned char *addr = address; -+ unsigned int index = addr[size - 3] * 256 * 256 -+ + addr[size - 2] * 256 -+ + addr[size - 1]; -+ return get_response (index); -+} -+ -+static struct response_data * -+decode_hostent (struct hostent *e) -+{ -+ TEST_VERIFY_EXIT (e != NULL); -+ TEST_VERIFY_EXIT (e->h_addr_list[0] != NULL); -+ TEST_VERIFY (e->h_addr_list[1] == NULL); -+ return decode_address (e->h_addr_list[0], e->h_length); -+} -+ -+static struct response_data * -+decode_addrinfo (struct addrinfo *ai, int family) -+{ -+ struct response_data *data = NULL; -+ while (ai != NULL) -+ { -+ if (ai->ai_family == family) -+ { -+ struct response_data *new_data; -+ switch (family) -+ { -+ case AF_INET: -+ { -+ struct sockaddr_in *pin = (struct sockaddr_in *) ai->ai_addr; -+ new_data = decode_address (&pin->sin_addr.s_addr, 4); -+ } -+ break; -+ case AF_INET6: -+ { -+ struct sockaddr_in6 *pin = (struct sockaddr_in6 *) ai->ai_addr; -+ new_data = decode_address (&pin->sin6_addr.s6_addr, 16); -+ } -+ break; -+ default: -+ FAIL_EXIT1 ("invalid address family %d", ai->ai_family); -+ } -+ if (data == NULL) -+ data = new_data; -+ else -+ /* Check pointer equality because this should be the same -+ response (same index). */ -+ TEST_VERIFY (data == new_data); -+ } -+ ai = ai->ai_next; -+ } -+ TEST_VERIFY_EXIT (data != NULL); -+ return data; -+} -+ -+/* Updated by the main test loop in accordance with what is set in -+ _res.options. */ -+static bool use_edns; -+static bool use_dnssec; -+ -+/* Verify the decoded response data against the flags above. */ -+static void -+verify_response_data_payload (struct response_data *data, -+ size_t expected_payload) -+{ -+ bool edns = use_edns || use_dnssec; -+ TEST_VERIFY (data->edns.active == edns); -+ if (!edns) -+ expected_payload = 0; -+ if (data->edns.payload_size != expected_payload) -+ { -+ support_record_failure (); -+ printf ("error: unexpected payload size %d (edns=%d)\n", -+ (int) data->edns.payload_size, edns); -+ } -+ uint16_t expected_flags = 0; -+ if (use_dnssec) -+ expected_flags |= 0x8000; /* DO flag. */ -+ if (data->edns.flags != expected_flags) -+ { -+ support_record_failure (); -+ printf ("error: unexpected EDNS flags 0x%04x (edns=%d)\n", -+ (int) data->edns.flags, edns); -+ } -+} -+ -+/* Same as verify_response_data_payload, but use the default -+ payload. */ -+static void -+verify_response_data (struct response_data *data) -+{ -+ verify_response_data_payload (data, 1200); -+} -+ -+static void -+check_hostent (struct hostent *e) -+{ -+ TEST_VERIFY_EXIT (e != NULL); -+ verify_response_data (decode_hostent (e)); -+} -+ -+static void -+do_ai (int family) -+{ -+ struct addrinfo hints = { .ai_family = family }; -+ struct addrinfo *ai; -+ int ret = getaddrinfo (EDNS_PROBE_EXAMPLE, "80", &hints, &ai); -+ TEST_VERIFY_EXIT (ret == 0); -+ switch (family) -+ { -+ case AF_INET: -+ case AF_INET6: -+ verify_response_data (decode_addrinfo (ai, family)); -+ break; -+ case AF_UNSPEC: -+ verify_response_data (decode_addrinfo (ai, AF_INET)); -+ verify_response_data (decode_addrinfo (ai, AF_INET6)); -+ break; -+ default: -+ FAIL_EXIT1 ("invalid address family %d", family); -+ } -+ freeaddrinfo (ai); -+} -+ -+enum res_op -+{ -+ res_op_search, -+ res_op_query, -+ res_op_querydomain, -+ res_op_nsearch, -+ res_op_nquery, -+ res_op_nquerydomain, -+ -+ res_op_last = res_op_nquerydomain, -+}; -+ -+static const char * -+res_op_string (enum res_op op) -+{ -+ switch (op) -+ { -+ case res_op_search: -+ return "res_search"; -+ case res_op_query: -+ return "res_query"; -+ case res_op_querydomain: -+ return "res_querydomain"; -+ case res_op_nsearch: -+ return "res_nsearch"; -+ case res_op_nquery: -+ return "res_nquery"; -+ case res_op_nquerydomain: -+ return "res_nquerydomain"; -+ } -+ FAIL_EXIT1 ("invalid res_op value %d", (int) op); -+} -+ -+/* Call libresolv function OP to look up PROBE_NAME, with an answer -+ buffer of SIZE bytes. Check that the advertised UDP buffer size is -+ in fact EXPECTED_BUFFER_SIZE. */ -+static void -+do_res_search (const char *probe_name, enum res_op op, size_t size, -+ size_t expected_buffer_size) -+{ -+ if (test_verbose) -+ printf ("info: testing %s with buffer size %zu\n", -+ res_op_string (op), size); -+ unsigned char *buffer = xmalloc (size); -+ int ret = -1; -+ switch (op) -+ { -+ case res_op_search: -+ ret = res_search (probe_name, C_IN, T_A, buffer, size); -+ break; -+ case res_op_query: -+ ret = res_query (probe_name, C_IN, T_A, buffer, size); -+ break; -+ case res_op_nsearch: -+ ret = res_nsearch (&_res, probe_name, C_IN, T_A, buffer, size); -+ break; -+ case res_op_nquery: -+ ret = res_nquery (&_res, probe_name, C_IN, T_A, buffer, size); -+ break; -+ case res_op_querydomain: -+ case res_op_nquerydomain: -+ { -+ char *example_stripped = xstrdup (probe_name); -+ char *dot_example = strstr (example_stripped, ".example"); -+ if (dot_example != NULL && strcmp (dot_example, ".example") == 0) -+ { -+ /* Truncate the domain name. */ -+ *dot_example = '\0'; -+ if (op == res_op_querydomain) -+ ret = res_querydomain -+ (example_stripped, "example", C_IN, T_A, buffer, size); -+ else -+ ret = res_nquerydomain -+ (&_res, example_stripped, "example", C_IN, T_A, buffer, size); -+ } -+ else -+ FAIL_EXIT1 ("invalid probe name: %s", probe_name); -+ free (example_stripped); -+ } -+ break; -+ } -+ TEST_VERIFY_EXIT (ret > 12); -+ unsigned char *end = buffer + ret; -+ -+ HEADER *hd = (HEADER *) buffer; -+ TEST_VERIFY (ntohs (hd->qdcount) == 1); -+ TEST_VERIFY (ntohs (hd->ancount) == 1); -+ /* Skip over the header. */ -+ unsigned char *p = buffer + sizeof (*hd); -+ /* Skip over the question. */ -+ ret = dn_skipname (p, end); -+ TEST_VERIFY_EXIT (ret > 0); -+ p += ret; -+ TEST_VERIFY_EXIT (end - p >= 4); -+ p += 4; -+ /* Skip over the RNAME and the RR header, but stop at the RDATA -+ length. */ -+ ret = dn_skipname (p, end); -+ TEST_VERIFY_EXIT (ret > 0); -+ p += ret; -+ TEST_VERIFY_EXIT (end - p >= 2 + 2 + 4 + 2 + 4); -+ p += 2 + 2 + 4; -+ /* The IP address should be 4 bytes long. */ -+ TEST_VERIFY_EXIT (p[0] == 0); -+ TEST_VERIFY_EXIT (p[1] == 4); -+ /* Extract the address information. */ -+ p += 2; -+ struct response_data *data = decode_address (p, 4); -+ -+ verify_response_data_payload (data, expected_buffer_size); -+ -+ free (buffer); -+} -+ -+static void -+run_test (const char *probe_name) -+{ -+ if (test_verbose) -+ printf ("\ninfo: * use_edns=%d use_dnssec=%d\n", -+ use_edns, use_dnssec); -+ check_hostent (gethostbyname (probe_name)); -+ check_hostent (gethostbyname2 (probe_name, AF_INET)); -+ check_hostent (gethostbyname2 (probe_name, AF_INET6)); -+ do_ai (AF_UNSPEC); -+ do_ai (AF_INET); -+ do_ai (AF_INET6); -+ -+ for (int op = 0; op <= res_op_last; ++op) -+ { -+ do_res_search (probe_name, op, 301, 512); -+ do_res_search (probe_name, op, 511, 512); -+ do_res_search (probe_name, op, 512, 512); -+ do_res_search (probe_name, op, 513, 513); -+ do_res_search (probe_name, op, 657, 657); -+ do_res_search (probe_name, op, 1199, 1199); -+ do_res_search (probe_name, op, 1200, 1200); -+ do_res_search (probe_name, op, 1201, 1200); -+ do_res_search (probe_name, op, 65535, 1200); -+ } -+} -+ -+static int -+do_test (void) -+{ -+ for (int do_edns = 0; do_edns < 2; ++do_edns) -+ for (int do_dnssec = 0; do_dnssec < 2; ++do_dnssec) -+ for (int do_tcp = 0; do_tcp < 2; ++do_tcp) -+ { -+ struct resolv_test *aux = resolv_test_start -+ ((struct resolv_redirect_config) -+ { -+ .response_callback = response, -+ }); -+ -+ use_edns = do_edns; -+ if (do_edns) -+ _res.options |= RES_USE_EDNS0; -+ use_dnssec = do_dnssec; -+ if (do_dnssec) -+ _res.options |= RES_USE_DNSSEC; -+ -+ char *probe_name = xstrdup (EDNS_PROBE_EXAMPLE); -+ if (do_tcp) -+ { -+ char *n = xasprintf ("tcp.%s", probe_name); -+ free (probe_name); -+ probe_name = n; -+ } -+ -+ run_test (probe_name); -+ -+ free (probe_name); -+ resolv_test_end (aux); -+ } -+ -+ free_response_data (); -+ return 0; -+} -+ -+#include -diff --git a/resolv/tst-resolv-qtypes.c b/resolv/tst-resolv-qtypes.c -index dcb39e505e..da3325f80c 100644 ---- a/resolv/tst-resolv-qtypes.c -+++ b/resolv/tst-resolv-qtypes.c -@@ -50,7 +50,7 @@ response (const struct resolv_response_context *ctx, - resolv_response_close_record (b); - } - --static const const char *domain = "www.example.com"; -+static const char domain[] = "www.example.com"; - - static int - wrap_res_query (int type, unsigned char *answer, int answer_length) -diff --git a/scripts/backport-support.sh b/scripts/backport-support.sh -new file mode 100644 -index 0000000000..2ece7ce575 ---- /dev/null -+++ b/scripts/backport-support.sh -@@ -0,0 +1,110 @@ -+#!/bin/bash -+# Create a patch which backports the support/ subdirectory. -+# 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 -+# . -+ -+# This script does not backport the Makefile tweaks outside the -+# support/ directory (which need to be backported separately), or the -+# changes to test-skeleton.c (which should not be backported). -+ -+set -e -+ -+export LC_ALL=C -+export GIT_CONFIG=/dev/null -+export GTT_CONFIG_NOSYSTEM=0 -+export GIT_PAGER= -+ -+usage () { -+ cat >&2 <&2 -+ echo "# rm -rf $patch_targets" >&2 -+} -+ -+command_commit () { -+ git status --porcelain | while read line ; do -+ echo "error: working copy is not clean, cannot commit" >&2 -+ exit 1 -+ done -+ for path in $patch_targets; do -+ echo "# Processing $path" >&2 -+ case "$path" in -+ [a-zA-Z0-9]*/) -+ # Directory. -+ git rm --cached --ignore-unmatch -r "$path" -+ rm -rf "$path" -+ git read-tree --prefix="$path" "$latest_commit":"$path" -+ git checkout "$path" -+ ;; -+ *) -+ # File. -+ git show "$latest_commit":"$path" > "$path" -+ git add "$path" -+ esac -+ done -+ git commit -m "Synchronize support/ infrastructure with $branch_name -+ -+This commit updates the support/ subdirectory to -+commit $latest_commit -+on the $branch_name branch. -+" -+} -+ -+command_$command -diff --git a/stdlib/getentropy.c b/stdlib/getentropy.c -index a71d4cd8f5..a88bbf8de3 100644 ---- a/stdlib/getentropy.c -+++ b/stdlib/getentropy.c -@@ -21,7 +21,7 @@ - - /* Write LENGTH bytes of randomness starting at BUFFER. Return 0 on - success and -1 on failure. */ --ssize_t -+int - getentropy (void *buffer, size_t length) - { - __set_errno (ENOSYS); -diff --git a/string/stratcliff.c b/string/stratcliff.c -index e672644888..2cd8686082 100644 ---- a/string/stratcliff.c -+++ b/string/stratcliff.c -@@ -58,8 +58,8 @@ - static int - do_test (void) - { -- int size = sysconf (_SC_PAGESIZE); -- int nchars = size / sizeof (CHAR); -+ size_t size = sysconf (_SC_PAGESIZE); -+ size_t nchars = size / sizeof (CHAR); - CHAR *adr; - CHAR *dest; - int result = 0; -@@ -80,7 +80,17 @@ do_test (void) - } - else - { -- int inner, middle, outer; -+ size_t inner, middle, outer, nchars64, max128; -+ -+ if (nchars > 64) -+ nchars64 = nchars - 64; -+ else -+ nchars64 = 0; -+ -+ if (nchars > 128) -+ max128 = nchars - 128; -+ else -+ max128 = 0; - - mprotect (adr, size, PROT_NONE); - mprotect (adr + 2 * nchars, size, PROT_NONE); -@@ -93,59 +103,65 @@ do_test (void) - MEMSET (adr, L('T'), nchars); - - /* strlen/wcslen test */ -- for (outer = nchars - 1; outer >= MAX (0, nchars - 128); --outer) -+ for (outer = nchars - 1; outer >= max128; --outer) - { -- for (inner = MAX (outer, nchars - 64); inner < nchars; ++inner) -+ for (inner = MAX (outer, nchars64); inner < nchars; ++inner) - { - adr[inner] = L('\0'); - - if (STRLEN (&adr[outer]) != (size_t) (inner - outer)) - { -- printf ("%s flunked for outer = %d, inner = %d\n", -+ printf ("%s flunked for outer = %zu, inner = %zu\n", - STRINGIFY (STRLEN), outer, inner); - result = 1; - } - - adr[inner] = L('T'); - } -+ if (outer == 0) -+ break; - } - - /* strnlen/wcsnlen test */ -- for (outer = nchars; outer >= MAX (0, nchars - 128); --outer) -+ for (outer = nchars; outer >= max128; --outer) - { -- for (inner = MAX (outer, nchars - 64); inner < nchars; ++inner) -+ for (inner = MAX (outer, nchars64); inner < nchars; ++inner) - { - adr[inner] = L('\0'); - - if (STRNLEN (&adr[outer], inner - outer + 1) - != (size_t) (inner - outer)) - { -- printf ("%s flunked for outer = %d, inner = %d\n", -+ printf ("%s flunked for outer = %zu, inner = %zu\n", - STRINGIFY (STRNLEN), outer, inner); - result = 1; - } - - adr[inner] = L('T'); - } -+ if (outer == 0) -+ break; - } -- for (outer = nchars; outer >= MAX (0, nchars - 128); --outer) -+ for (outer = nchars; outer >= max128; --outer) - { -- for (inner = MAX (outer, nchars - 64); inner <= nchars; ++inner) -+ for (inner = MAX (outer, nchars64); inner <= nchars; ++inner) - { - if (STRNLEN (&adr[outer], inner - outer) - != (size_t) (inner - outer)) - { -- printf ("%s flunked bounded for outer = %d, inner = %d\n", -+ printf ("%s flunked bounded for outer = %zu, inner = %zu\n", - STRINGIFY (STRNLEN), outer, inner); - result = 1; - } - } -+ if (outer == 0) -+ break; - } - - /* strchr/wcschr test */ -- for (outer = nchars - 1; outer >= MAX (0, nchars - 128); --outer) -+ for (outer = nchars - 1; outer >= max128; --outer) - { -- for (middle = MAX (outer, nchars - 64); middle < nchars; ++middle) -+ for (middle = MAX (outer, nchars64); middle < nchars; ++middle) - { - for (inner = middle; inner < nchars; ++inner) - { -@@ -158,8 +174,8 @@ do_test (void) - || (inner != middle - && (cp - &adr[outer]) != middle - outer)) - { -- printf ("%s flunked for outer = %d, middle = %d, " -- "inner = %d\n", -+ printf ("%s flunked for outer = %zu, middle = %zu, " -+ "inner = %zu\n", - STRINGIFY (STRCHR), outer, middle, inner); - result = 1; - } -@@ -168,6 +184,8 @@ do_test (void) - adr[middle] = L('T'); - } - } -+ if (outer == 0) -+ break; - } - - /* Special test. */ -@@ -180,9 +198,9 @@ do_test (void) - } - - /* strrchr/wcsrchr test */ -- for (outer = nchars - 1; outer >= MAX (0, nchars - 128); --outer) -+ for (outer = nchars - 1; outer >= max128; --outer) - { -- for (middle = MAX (outer, nchars - 64); middle < nchars; ++middle) -+ for (middle = MAX (outer, nchars64); middle < nchars; ++middle) - { - for (inner = middle; inner < nchars; ++inner) - { -@@ -195,8 +213,8 @@ do_test (void) - || (inner != middle - && (cp - &adr[outer]) != middle - outer)) - { -- printf ("%s flunked for outer = %d, middle = %d, " -- "inner = %d\n", -+ printf ("%s flunked for outer = %zu, middle = %zu, " -+ "inner = %zu\n", - STRINGIFY (STRRCHR), outer, middle, inner); - result = 1; - } -@@ -205,12 +223,14 @@ do_test (void) - adr[middle] = L('T'); - } - } -+ if (outer == 0) -+ break; - } - - /* memchr test */ -- for (outer = nchars - 1; outer >= MAX (0, nchars - 128); --outer) -+ for (outer = nchars - 1; outer >= max128; --outer) - { -- for (middle = MAX (outer, nchars - 64); middle < nchars; ++middle) -+ for (middle = MAX (outer, nchars64); middle < nchars; ++middle) - { - adr[middle] = L('V'); - -@@ -218,32 +238,36 @@ do_test (void) - - if (cp - &adr[outer] != middle - outer) - { -- printf ("%s flunked for outer = %d, middle = %d\n", -+ printf ("%s flunked for outer = %zu, middle = %zu\n", - STRINGIFY (MEMCHR), outer, middle); - result = 1; - } - - adr[middle] = L('T'); - } -+ if (outer == 0) -+ break; - } -- for (outer = nchars; outer >= MAX (0, nchars - 128); --outer) -+ for (outer = nchars; outer >= max128; --outer) - { - CHAR *cp = MEMCHR (&adr[outer], L('V'), nchars - outer); - - if (cp != NULL) - { -- printf ("%s flunked for outer = %d\n", -+ printf ("%s flunked for outer = %zu\n", - STRINGIFY (MEMCHR), outer); - result = 1; - } -+ if (outer == 0) -+ break; - } - - /* These functions only exist for single-byte characters. */ - #ifndef WCSTEST - /* rawmemchr test */ -- for (outer = nchars - 1; outer >= MAX (0, nchars - 128); --outer) -+ for (outer = nchars - 1; outer >= max128; --outer) - { -- for (middle = MAX (outer, nchars - 64); middle < nchars; ++middle) -+ for (middle = MAX (outer, nchars64); middle < nchars; ++middle) - { - adr[middle] = L('V'); - -@@ -251,19 +275,21 @@ do_test (void) - - if (cp - &adr[outer] != middle - outer) - { -- printf ("%s flunked for outer = %d, middle = %d\n", -+ printf ("%s flunked for outer = %zu, middle = %zu\n", - STRINGIFY (rawmemchr), outer, middle); - result = 1; - } - - adr[middle] = L('T'); - } -+ if (outer == 0) -+ break; - } - - /* memrchr test */ -- for (outer = nchars - 1; outer >= MAX (0, nchars - 128); --outer) -+ for (outer = nchars - 1; outer >= max128; --outer) - { -- for (middle = MAX (outer, nchars - 64); middle < nchars; ++middle) -+ for (middle = MAX (outer, nchars64); middle < nchars; ++middle) - { - adr[middle] = L('V'); - -@@ -271,44 +297,50 @@ do_test (void) - - if (cp - &adr[outer] != middle - outer) - { -- printf ("%s flunked for outer = %d, middle = %d\n", -+ printf ("%s flunked for outer = %zu, middle = %zu\n", - STRINGIFY (memrchr), outer, middle); - result = 1; - } - - adr[middle] = L('T'); - } -+ if (outer == 0) -+ break; - } -- for (outer = nchars; outer >= MAX (0, nchars - 128); --outer) -+ for (outer = nchars; outer >= max128; --outer) - { - CHAR *cp = memrchr (&adr[outer], L('V'), nchars - outer); - - if (cp != NULL) - { -- printf ("%s flunked for outer = %d\n", -+ printf ("%s flunked for outer = %zu\n", - STRINGIFY (memrchr), outer); - result = 1; - } -+ if (outer == 0) -+ break; - } - #endif - - /* strcpy/wcscpy test */ -- for (outer = nchars - 1; outer >= MAX (0, nchars - 128); --outer) -+ for (outer = nchars - 1; outer >= max128; --outer) - { -- for (inner = MAX (outer, nchars - 64); inner < nchars; ++inner) -+ for (inner = MAX (outer, nchars64); inner < nchars; ++inner) - { - adr[inner] = L('\0'); - - if (STRCPY (dest, &adr[outer]) != dest - || STRLEN (dest) != (size_t) (inner - outer)) - { -- printf ("%s flunked for outer = %d, inner = %d\n", -+ printf ("%s flunked for outer = %zu, inner = %zu\n", - STRINGIFY (STRCPY), outer, inner); - result = 1; - } - - adr[inner] = L('T'); - } -+ if (outer == 0) -+ break; - } - - /* strcmp/wcscmp tests */ -@@ -322,14 +354,14 @@ do_test (void) - - if (STRCMP (adr + middle, dest + nchars - outer) <= 0) - { -- printf ("%s 1 flunked for outer = %d, middle = %d\n", -+ printf ("%s 1 flunked for outer = %zu, middle = %zu\n", - STRINGIFY (STRCMP), outer, middle); - result = 1; - } - - if (STRCMP (dest + nchars - outer, adr + middle) >= 0) - { -- printf ("%s 2 flunked for outer = %d, middle = %d\n", -+ printf ("%s 2 flunked for outer = %zu, middle = %zu\n", - STRINGIFY (STRCMP), outer, middle); - result = 1; - } -@@ -348,16 +380,16 @@ do_test (void) - { - if (STRNCMP (adr + middle, dest + nchars - outer, inner) != 0) - { -- printf ("%s 1 flunked for outer = %d, middle = %d, " -- "inner = %d\n", -+ printf ("%s 1 flunked for outer = %zu, middle = %zu, " -+ "inner = %zu\n", - STRINGIFY (STRNCMP), outer, middle, inner); - result = 1; - } - - if (STRNCMP (dest + nchars - outer, adr + middle, inner) != 0) - { -- printf ("%s 2 flunked for outer = %d, middle = %d, " -- "inner = %d\n", -+ printf ("%s 2 flunked for outer = %zu, middle = %zu, " -+ "inner = %zu\n", - STRINGIFY (STRNCMP), outer, middle, inner); - result = 1; - } -@@ -365,14 +397,14 @@ do_test (void) - - if (STRNCMP (adr + middle, dest + nchars - outer, outer) >= 0) - { -- printf ("%s 1 flunked for outer = %d, middle = %d, full\n", -+ printf ("%s 1 flunked for outer = %zu, middle = %zu, full\n", - STRINGIFY (STRNCMP), outer, middle); - result = 1; - } - - if (STRNCMP (dest + nchars - outer, adr + middle, outer) <= 0) - { -- printf ("%s 2 flunked for outer = %d, middle = %d, full\n", -+ printf ("%s 2 flunked for outer = %zu, middle = %zu, full\n", - STRINGIFY (STRNCMP), outer, middle); - result = 1; - } -@@ -380,7 +412,7 @@ do_test (void) - - /* strncpy/wcsncpy tests */ - adr[nchars - 1] = L('T'); -- for (outer = nchars; outer >= MAX (0, nchars - 128); --outer) -+ for (outer = nchars; outer >= max128; --outer) - { - size_t len; - -@@ -389,17 +421,19 @@ do_test (void) - if (STRNCPY (dest, &adr[outer], len) != dest - || MEMCMP (dest, &adr[outer], len) != 0) - { -- printf ("outer %s flunked for outer = %d, len = %Zd\n", -+ printf ("outer %s flunked for outer = %zu, len = %zu\n", - STRINGIFY (STRNCPY), outer, len); - result = 1; - } - } -+ if (outer == 0) -+ break; - } - adr[nchars - 1] = L('\0'); - -- for (outer = nchars - 1; outer >= MAX (0, nchars - 128); --outer) -+ for (outer = nchars - 1; outer >= max128; --outer) - { -- for (inner = MAX (outer, nchars - 64); inner < nchars; ++inner) -+ for (inner = MAX (outer, nchars64); inner < nchars; ++inner) - { - size_t len; - -@@ -413,8 +447,8 @@ do_test (void) - || (inner - outer < len - && STRLEN (dest) != (inner - outer))) - { -- printf ("%s flunked for outer = %d, inner = %d, " -- "len = %Zd\n", -+ printf ("%s flunked for outer = %zu, inner = %zu, " -+ "len = %zu\n", - STRINGIFY (STRNCPY), outer, inner, len); - result = 1; - } -@@ -424,8 +458,8 @@ do_test (void) - || (inner - outer < len - && STRLEN (dest + 1) != (inner - outer))) - { -- printf ("%s+1 flunked for outer = %d, inner = %d, " -- "len = %Zd\n", -+ printf ("%s+1 flunked for outer = %zu, inner = %zu, " -+ "len = %zu\n", - STRINGIFY (STRNCPY), outer, inner, len); - result = 1; - } -@@ -433,29 +467,33 @@ do_test (void) - - adr[inner] = L('T'); - } -+ if (outer == 0) -+ break; - } - - /* stpcpy/wcpcpy test */ -- for (outer = nchars - 1; outer >= MAX (0, nchars - 128); --outer) -+ for (outer = nchars - 1; outer >= max128; --outer) - { -- for (inner = MAX (outer, nchars - 64); inner < nchars; ++inner) -+ for (inner = MAX (outer, nchars64); inner < nchars; ++inner) - { - adr[inner] = L('\0'); - - if ((STPCPY (dest, &adr[outer]) - dest) != inner - outer) - { -- printf ("%s flunked for outer = %d, inner = %d\n", -+ printf ("%s flunked for outer = %zu, inner = %zu\n", - STRINGIFY (STPCPY), outer, inner); - result = 1; - } - - adr[inner] = L('T'); - } -+ if (outer == 0) -+ break; - } - - /* stpncpy/wcpncpy test */ - adr[nchars - 1] = L('T'); -- for (outer = nchars; outer >= MAX (0, nchars - 128); --outer) -+ for (outer = nchars; outer >= max128; --outer) - { - size_t len; - -@@ -464,17 +502,19 @@ do_test (void) - if (STPNCPY (dest, &adr[outer], len) != dest + len - || MEMCMP (dest, &adr[outer], len) != 0) - { -- printf ("outer %s flunked for outer = %d, len = %Zd\n", -+ printf ("outer %s flunked for outer = %zu, len = %zu\n", - STRINGIFY (STPNCPY), outer, len); - result = 1; - } - } -+ if (outer == 0) -+ break; - } - adr[nchars - 1] = L('\0'); - -- for (outer = nchars - 1; outer >= MAX (0, nchars - 128); --outer) -+ for (outer = nchars - 1; outer >= max128; --outer) - { -- for (middle = MAX (outer, nchars - 64); middle < nchars; ++middle) -+ for (middle = MAX (outer, nchars64); middle < nchars; ++middle) - { - adr[middle] = L('\0'); - -@@ -483,8 +523,8 @@ do_test (void) - if ((STPNCPY (dest, &adr[outer], inner) - dest) - != MIN (inner, middle - outer)) - { -- printf ("%s flunked for outer = %d, middle = %d, " -- "inner = %d\n", -+ printf ("%s flunked for outer = %zu, middle = %zu, " -+ "inner = %zu\n", - STRINGIFY (STPNCPY), outer, middle, inner); - result = 1; - } -@@ -492,66 +532,84 @@ do_test (void) - - adr[middle] = L('T'); - } -+ if (outer == 0) -+ break; - } - - /* memcpy/wmemcpy test */ -- for (outer = nchars; outer >= MAX (0, nchars - 128); --outer) -- for (inner = 0; inner < nchars - outer; ++inner) -- if (MEMCPY (dest, &adr[outer], inner) != dest) -- { -- printf ("%s flunked for outer = %d, inner = %d\n", -- STRINGIFY (MEMCPY), outer, inner); -- result = 1; -- } -+ for (outer = nchars; outer >= max128; --outer) -+ { -+ for (inner = 0; inner < nchars - outer; ++inner) -+ if (MEMCPY (dest, &adr[outer], inner) != dest) -+ { -+ printf ("%s flunked for outer = %zu, inner = %zu\n", -+ STRINGIFY (MEMCPY), outer, inner); -+ result = 1; -+ } -+ if (outer == 0) -+ break; -+ } - - /* mempcpy/wmempcpy test */ -- for (outer = nchars; outer >= MAX (0, nchars - 128); --outer) -- for (inner = 0; inner < nchars - outer; ++inner) -- if (MEMPCPY (dest, &adr[outer], inner) != dest + inner) -- { -- printf ("%s flunked for outer = %d, inner = %d\n", -- STRINGIFY (MEMPCPY), outer, inner); -- result = 1; -- } -+ for (outer = nchars; outer >= max128; --outer) -+ { -+ for (inner = 0; inner < nchars - outer; ++inner) -+ if (MEMPCPY (dest, &adr[outer], inner) != dest + inner) -+ { -+ printf ("%s flunked for outer = %zu, inner = %zu\n", -+ STRINGIFY (MEMPCPY), outer, inner); -+ result = 1; -+ } -+ if (outer == 0) -+ break; -+ } - - /* This function only exists for single-byte characters. */ - #ifndef WCSTEST - /* memccpy test */ - memset (adr, '\0', nchars); -- for (outer = nchars; outer >= MAX (0, nchars - 128); --outer) -- for (inner = 0; inner < nchars - outer; ++inner) -- if (memccpy (dest, &adr[outer], L('\1'), inner) != NULL) -- { -- printf ("memccpy flunked full copy for outer = %d, inner = %d\n", -- outer, inner); -- result = 1; -- } -- for (outer = nchars - 1; outer >= MAX (0, nchars - 128); --outer) -- for (middle = 0; middle < nchars - outer; ++middle) -- { -- memset (dest, L('\2'), middle + 1); -- for (inner = 0; inner < middle; ++inner) -+ for (outer = nchars; outer >= max128; --outer) -+ { -+ for (inner = 0; inner < nchars - outer; ++inner) -+ if (memccpy (dest, &adr[outer], L('\1'), inner) != NULL) - { -- adr[outer + inner] = L('\1'); -- -- if (memccpy (dest, &adr[outer], '\1', middle + 128) -- != dest + inner + 1) -- { -- printf ("\ --memccpy flunked partial copy for outer = %d, middle = %d, inner = %d\n", -- outer, middle, inner); -- result = 1; -- } -- else if (dest[inner + 1] != L('\2')) -- { -- printf ("\ --memccpy copied too much for outer = %d, middle = %d, inner = %d\n", -- outer, middle, inner); -- result = 1; -- } -- adr[outer + inner] = L('\0'); -+ printf ("memccpy flunked full copy for outer = %zu, inner = %zu\n", -+ outer, inner); -+ result = 1; - } -- } -+ if (outer == 0) -+ break; -+ } -+ for (outer = nchars - 1; outer >= max128; --outer) -+ { -+ for (middle = 0; middle < nchars - outer; ++middle) -+ { -+ memset (dest, L('\2'), middle + 1); -+ for (inner = 0; inner < middle; ++inner) -+ { -+ adr[outer + inner] = L('\1'); -+ -+ if (memccpy (dest, &adr[outer], '\1', middle + 128) -+ != dest + inner + 1) -+ { -+ printf ("\ -+ memccpy flunked partial copy for outer = %zu, middle = %zu, inner = %zu\n", -+ outer, middle, inner); -+ result = 1; -+ } -+ else if (dest[inner + 1] != L('\2')) -+ { -+ printf ("\ -+ memccpy copied too much for outer = %zu, middle = %zu, inner = %zu\n", -+ outer, middle, inner); -+ result = 1; -+ } -+ adr[outer + inner] = L('\0'); -+ } -+ } -+ if (outer == 0) -+ break; -+ } - #endif - } - -diff --git a/string/test-memchr.c b/string/test-memchr.c -index d62889ff8f..6431605c7e 100644 ---- a/string/test-memchr.c -+++ b/string/test-memchr.c -@@ -208,6 +208,12 @@ test_main (void) - do_test (0, i, i + 1, i + 1, 0); - } - -+ /* BZ#21182 - wrong overflow calculation for i686 implementation -+ with address near end of the page. */ -+ for (i = 2; i < 16; ++i) -+ /* page_size is in fact getpagesize() * 2. */ -+ do_test (page_size / 2 - i, i, i, 1, 0x9B); -+ - do_random_tests (); - return ret; - } -diff --git a/sunrpc/Makefile b/sunrpc/Makefile -index 0c1e6124ff..7e5d2955a0 100644 ---- a/sunrpc/Makefile -+++ b/sunrpc/Makefile -@@ -93,11 +93,12 @@ rpcgen-objs = rpc_main.o rpc_hout.o rpc_cout.o rpc_parse.o \ - extra-objs = $(rpcgen-objs) $(addprefix cross-,$(rpcgen-objs)) - others += rpcgen - --tests = tst-xdrmem tst-xdrmem2 test-rpcent -+tests = tst-xdrmem tst-xdrmem2 test-rpcent tst-udp-error tst-udp-timeout \ -+ tst-udp-nonblocking - xtests := tst-getmyaddr - - ifeq ($(have-thread-library),yes) --xtests += thrsvc -+xtests += thrsvc tst-udp-garbage - endif - - ifeq ($(run-built-tests),yes) -@@ -155,6 +156,7 @@ BUILD_CPPFLAGS += $(sunrpc-CPPFLAGS) - $(objpfx)tst-getmyaddr: $(common-objpfx)linkobj/libc.so - $(objpfx)tst-xdrmem: $(common-objpfx)linkobj/libc.so - $(objpfx)tst-xdrmem2: $(common-objpfx)linkobj/libc.so -+$(objpfx)tst-udp-error: $(common-objpfx)linkobj/libc.so - - $(objpfx)rpcgen: $(addprefix $(objpfx),$(rpcgen-objs)) - -@@ -234,3 +236,8 @@ $(rpcgen-tests): $(objpfx)%.out: %.x $(objpfx)rpcgen - $(built-program-cmd) -c $< -o $@; \ - $(evaluate-test) - endif -+ -+$(objpfx)tst-udp-timeout: $(common-objpfx)linkobj/libc.so -+$(objpfx)tst-udp-nonblocking: $(common-objpfx)linkobj/libc.so -+$(objpfx)tst-udp-garbage: \ -+ $(common-objpfx)linkobj/libc.so $(shared-thread-library) -diff --git a/sunrpc/clnt_udp.c b/sunrpc/clnt_udp.c -index 4d9acb1e6a..6ce16eb298 100644 ---- a/sunrpc/clnt_udp.c -+++ b/sunrpc/clnt_udp.c -@@ -55,6 +55,7 @@ - #endif - - #include -+#include - - extern u_long _create_xid (void); - -@@ -80,7 +81,9 @@ static const struct clnt_ops udp_ops = - }; - - /* -- * Private data kept per client handle -+ * Private data kept per client handle. This private struct is -+ * unfortunately part of the ABI; ypbind contains a copy of it and -+ * accesses it through CLIENT::cl_private field. - */ - struct cu_data - { -@@ -278,28 +281,38 @@ clntudp_call (/* client handle */ - int inlen; - socklen_t fromlen; - struct pollfd fd; -- int milliseconds = (cu->cu_wait.tv_sec * 1000) + -- (cu->cu_wait.tv_usec / 1000); - struct sockaddr_in from; - struct rpc_msg reply_msg; - XDR reply_xdrs; -- struct timeval time_waited; - bool_t ok; - int nrefreshes = 2; /* number of times to refresh cred */ -- struct timeval timeout; - int anyup; /* any network interface up */ - -- if (cu->cu_total.tv_usec == -1) -- { -- timeout = utimeout; /* use supplied timeout */ -- } -- else -+ struct deadline_current_time current_time = __deadline_current_time (); -+ struct deadline total_deadline; /* Determined once by overall timeout. */ -+ struct deadline response_deadline; /* Determined anew for each query. */ -+ -+ /* Choose the timeout value. For non-sending usage (xargs == NULL), -+ the total deadline does not matter, only cu->cu_wait is used -+ below. */ -+ if (xargs != NULL) - { -- timeout = cu->cu_total; /* use default timeout */ -+ struct timeval tv; -+ if (cu->cu_total.tv_usec == -1) -+ /* Use supplied timeout. */ -+ tv = utimeout; -+ else -+ /* Use default timeout. */ -+ tv = cu->cu_total; -+ if (!__is_timeval_valid_timeout (tv)) -+ return (cu->cu_error.re_status = RPC_TIMEDOUT); -+ total_deadline = __deadline_from_timeval (current_time, tv); - } - -- time_waited.tv_sec = 0; -- time_waited.tv_usec = 0; -+ /* Guard against bad timeout specification. */ -+ if (!__is_timeval_valid_timeout (cu->cu_wait)) -+ return (cu->cu_error.re_status = RPC_TIMEDOUT); -+ - call_again: - xdrs = &(cu->cu_outxdrs); - if (xargs == NULL) -@@ -325,27 +338,46 @@ send_again: - return (cu->cu_error.re_status = RPC_CANTSEND); - } - -- /* -- * Hack to provide rpc-based message passing -- */ -- if (timeout.tv_sec == 0 && timeout.tv_usec == 0) -- { -- return (cu->cu_error.re_status = RPC_TIMEDOUT); -- } -+ /* sendto may have blocked, so recompute the current time. */ -+ current_time = __deadline_current_time (); - get_reply: -- /* -- * sub-optimal code appears here because we have -- * some clock time to spare while the packets are in flight. -- * (We assume that this is actually only executed once.) -- */ -+ response_deadline = __deadline_from_timeval (current_time, cu->cu_wait); -+ - reply_msg.acpted_rply.ar_verf = _null_auth; - reply_msg.acpted_rply.ar_results.where = resultsp; - reply_msg.acpted_rply.ar_results.proc = xresults; - fd.fd = cu->cu_sock; - fd.events = POLLIN; - anyup = 0; -+ -+ /* Per-response retry loop. current_time must be up-to-date at the -+ top of the loop. */ - for (;;) - { -+ int milliseconds; -+ if (xargs != NULL) -+ { -+ if (__deadline_elapsed (current_time, total_deadline)) -+ /* Overall timeout expired. */ -+ return (cu->cu_error.re_status = RPC_TIMEDOUT); -+ milliseconds = __deadline_to_ms -+ (current_time, __deadline_first (total_deadline, -+ response_deadline)); -+ if (milliseconds == 0) -+ /* Per-query timeout expired. */ -+ goto send_again; -+ } -+ else -+ { -+ /* xatgs == NULL. Collect a response without sending a -+ query. In this mode, we need to ignore the total -+ deadline. */ -+ milliseconds = __deadline_to_ms (current_time, response_deadline); -+ if (milliseconds == 0) -+ /* Cannot send again, so bail out. */ -+ return (cu->cu_error.re_status = RPC_CANTSEND); -+ } -+ - switch (__poll (&fd, 1, milliseconds)) - { - -@@ -356,27 +388,10 @@ send_again: - if (!anyup) - return (cu->cu_error.re_status = RPC_CANTRECV); - } -- -- time_waited.tv_sec += cu->cu_wait.tv_sec; -- time_waited.tv_usec += cu->cu_wait.tv_usec; -- while (time_waited.tv_usec >= 1000000) -- { -- time_waited.tv_sec++; -- time_waited.tv_usec -= 1000000; -- } -- if ((time_waited.tv_sec < timeout.tv_sec) || -- ((time_waited.tv_sec == timeout.tv_sec) && -- (time_waited.tv_usec < timeout.tv_usec))) -- goto send_again; -- return (cu->cu_error.re_status = RPC_TIMEDOUT); -- -- /* -- * buggy in other cases because time_waited is not being -- * updated. -- */ -+ goto next_response; - case -1: - if (errno == EINTR) -- continue; -+ goto next_response; - cu->cu_error.re_errno = errno; - return (cu->cu_error.re_status = RPC_CANTRECV); - } -@@ -421,9 +436,9 @@ send_again: - cmsg = CMSG_NXTHDR (&msg, cmsg)) - if (cmsg->cmsg_level == SOL_IP && cmsg->cmsg_type == IP_RECVERR) - { -- free (cbuf); - e = (struct sock_extended_err *) CMSG_DATA(cmsg); - cu->cu_error.re_errno = e->ee_errno; -+ free (cbuf); - return (cu->cu_error.re_status = RPC_CANTRECV); - } - free (cbuf); -@@ -440,20 +455,22 @@ send_again: - if (inlen < 0) - { - if (errno == EWOULDBLOCK) -- continue; -+ goto next_response; - cu->cu_error.re_errno = errno; - return (cu->cu_error.re_status = RPC_CANTRECV); - } -- if (inlen < 4) -- continue; -- -- /* see if reply transaction id matches sent id. -- Don't do this if we only wait for a replay */ -- if (xargs != NULL -- && memcmp (cu->cu_inbuf, cu->cu_outbuf, sizeof (u_int32_t)) != 0) -- continue; -- /* we now assume we have the proper reply */ -- break; -+ /* Accept the response if the packet is sufficiently long and -+ the transaction ID matches the query (if available). */ -+ if (inlen >= 4 -+ && (xargs == NULL -+ || memcmp (cu->cu_inbuf, cu->cu_outbuf, -+ sizeof (u_int32_t)) == 0)) -+ break; -+ -+ next_response: -+ /* Update the current time because poll and recvmsg waited for -+ an unknown time. */ -+ current_time = __deadline_current_time (); - } - - /* -diff --git a/sunrpc/tst-udp-error.c b/sunrpc/tst-udp-error.c -new file mode 100644 -index 0000000000..1efc02f5c6 ---- /dev/null -+++ b/sunrpc/tst-udp-error.c -@@ -0,0 +1,62 @@ -+/* Check for use-after-free in clntudp_call (bug 21115). -+ 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 -+ . */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+static int -+do_test (void) -+{ -+ support_become_root (); -+ support_enter_network_namespace (); -+ -+ /* Obtain a likely-unused port number. */ -+ struct sockaddr_in sin = -+ { -+ .sin_family = AF_INET, -+ .sin_addr.s_addr = htonl (INADDR_LOOPBACK), -+ }; -+ { -+ int fd = xsocket (AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0); -+ xbind (fd, (struct sockaddr *) &sin, sizeof (sin)); -+ socklen_t sinlen = sizeof (sin); -+ xgetsockname (fd, (struct sockaddr *) &sin, &sinlen); -+ /* Close the socket, so that we will receive an error below. */ -+ close (fd); -+ } -+ -+ int sock = RPC_ANYSOCK; -+ CLIENT *clnt = clntudp_create -+ (&sin, 1, 2, (struct timeval) { 1, 0 }, &sock); -+ TEST_VERIFY_EXIT (clnt != NULL); -+ TEST_VERIFY (clnt_call (clnt, 3, -+ (xdrproc_t) xdr_void, NULL, -+ (xdrproc_t) xdr_void, NULL, -+ ((struct timeval) { 3, 0 })) -+ == RPC_CANTRECV); -+ clnt_destroy (clnt); -+ -+ return 0; -+} -+ -+#include -diff --git a/sunrpc/tst-udp-garbage.c b/sunrpc/tst-udp-garbage.c -new file mode 100644 -index 0000000000..4abda93f08 ---- /dev/null -+++ b/sunrpc/tst-udp-garbage.c -@@ -0,0 +1,104 @@ -+/* Test that garbage packets do not affect timeout handling. -+ 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 -+ . */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/* Descriptor for the server UDP socket. */ -+static int server_fd; -+ -+static void * -+garbage_sender_thread (void *unused) -+{ -+ while (true) -+ { -+ struct sockaddr_storage sa; -+ socklen_t salen = sizeof (sa); -+ char buf[1]; -+ if (recvfrom (server_fd, buf, sizeof (buf), 0, -+ (struct sockaddr *) &sa, &salen) < 0) -+ FAIL_EXIT1 ("recvfrom: %m"); -+ -+ /* Send garbage packets indefinitely. */ -+ buf[0] = 0; -+ while (true) -+ { -+ /* sendto can fail if the client closed the socket. */ -+ if (sendto (server_fd, buf, sizeof (buf), 0, -+ (struct sockaddr *) &sa, salen) < 0) -+ break; -+ -+ /* Wait a bit, to avoid burning too many CPU cycles in a -+ tight loop. The wait period must be much shorter than -+ the client timeouts configured below. */ -+ usleep (50 * 1000); -+ } -+ } -+} -+ -+static int -+do_test (void) -+{ -+ support_become_root (); -+ support_enter_network_namespace (); -+ -+ server_fd = xsocket (AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, IPPROTO_UDP); -+ struct sockaddr_in server_address = -+ { -+ .sin_family = AF_INET, -+ .sin_addr.s_addr = htonl (INADDR_LOOPBACK), -+ }; -+ xbind (server_fd, -+ (struct sockaddr *) &server_address, sizeof (server_address)); -+ { -+ socklen_t sinlen = sizeof (server_address); -+ xgetsockname (server_fd, (struct sockaddr *) &server_address, &sinlen); -+ TEST_VERIFY (sizeof (server_address) == sinlen); -+ } -+ -+ /* Garbage packet source. */ -+ xpthread_detach (xpthread_create (NULL, garbage_sender_thread, NULL)); -+ -+ /* Test client. Use an arbitrary timeout of one second, which is -+ much longer than the garbage packet interval, but still -+ reasonably short, so that the test completes quickly. */ -+ int client_fd = RPC_ANYSOCK; -+ CLIENT *clnt = clntudp_create (&server_address, -+ 1, 2, /* Arbitrary RPC endpoint numbers. */ -+ (struct timeval) { 1, 0 }, -+ &client_fd); -+ if (clnt == NULL) -+ FAIL_EXIT1 ("clntudp_create: %m"); -+ -+ TEST_VERIFY (clnt_call (clnt, 3, /* Arbitrary RPC procedure number. */ -+ (xdrproc_t) xdr_void, NULL, -+ (xdrproc_t) xdr_void, NULL, -+ ((struct timeval) { 1, 0 }))); -+ -+ return 0; -+} -+ -+#include -diff --git a/sunrpc/tst-udp-nonblocking.c b/sunrpc/tst-udp-nonblocking.c -new file mode 100644 -index 0000000000..1d6a7f4b56 ---- /dev/null -+++ b/sunrpc/tst-udp-nonblocking.c -@@ -0,0 +1,333 @@ -+/* Test non-blocking use of the UDP client. -+ 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 -+ . */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/* Test data serialization and deserialization. */ -+ -+struct test_query -+{ -+ uint32_t a; -+ uint32_t b; -+ uint32_t timeout_ms; -+}; -+ -+static bool_t -+xdr_test_query (XDR *xdrs, void *data, ...) -+{ -+ struct test_query *p = data; -+ return xdr_uint32_t (xdrs, &p->a) -+ && xdr_uint32_t (xdrs, &p->b) -+ && xdr_uint32_t (xdrs, &p->timeout_ms); -+} -+ -+struct test_response -+{ -+ uint32_t server_id; -+ uint32_t seq; -+ uint32_t sum; -+}; -+ -+static bool_t -+xdr_test_response (XDR *xdrs, void *data, ...) -+{ -+ struct test_response *p = data; -+ return xdr_uint32_t (xdrs, &p->server_id) -+ && xdr_uint32_t (xdrs, &p->seq) -+ && xdr_uint32_t (xdrs, &p->sum); -+} -+ -+/* Implementation of the test server. */ -+ -+enum -+ { -+ /* Number of test servers to run. */ -+ SERVER_COUNT = 3, -+ -+ /* RPC parameters, chosen at random. */ -+ PROGNUM = 8242, -+ VERSNUM = 19654, -+ -+ /* Main RPC operation. */ -+ PROC_ADD = 1, -+ -+ /* Request process termination. */ -+ PROC_EXIT, -+ -+ /* Special exit status to mark successful processing. */ -+ EXIT_MARKER = 55, -+ }; -+ -+/* Set by the parent process to tell test servers apart. */ -+static int server_id; -+ -+/* Implementation of the test server. */ -+static void -+server_dispatch (struct svc_req *request, SVCXPRT *transport) -+{ -+ /* Query sequence number. */ -+ static uint32_t seq = 0; -+ ++seq; -+ static bool proc_add_seen; -+ -+ if (test_verbose) -+ printf ("info: server_dispatch server_id=%d seq=%u rq_proc=%lu\n", -+ server_id, seq, request->rq_proc); -+ -+ switch (request->rq_proc) -+ { -+ case PROC_ADD: -+ { -+ struct test_query query; -+ memset (&query, 0xc0, sizeof (query)); -+ TEST_VERIFY_EXIT -+ (svc_getargs (transport, xdr_test_query, -+ (void *) &query)); -+ -+ if (test_verbose) -+ printf (" a=%u b=%u timeout_ms=%u\n", -+ query.a, query.b, query.timeout_ms); -+ -+ usleep (query.timeout_ms * 1000); -+ -+ struct test_response response = -+ { -+ .server_id = server_id, -+ .seq = seq, -+ .sum = query.a + query.b, -+ }; -+ TEST_VERIFY (svc_sendreply (transport, xdr_test_response, -+ (void *) &response)); -+ if (test_verbose) -+ printf (" server id %d response seq=%u sent\n", server_id, seq); -+ proc_add_seen = true; -+ } -+ break; -+ -+ case PROC_EXIT: -+ TEST_VERIFY (proc_add_seen); -+ TEST_VERIFY (svc_sendreply (transport, (xdrproc_t) xdr_void, NULL)); -+ _exit (EXIT_MARKER); -+ break; -+ -+ default: -+ FAIL_EXIT1 ("invalid rq_proc value: %lu", request->rq_proc); -+ break; -+ } -+} -+ -+/* Return the number seconds since an arbitrary point in time. */ -+static double -+get_ticks (void) -+{ -+ { -+ struct timespec ts; -+ if (clock_gettime (CLOCK_MONOTONIC, &ts) == 0) -+ return ts.tv_sec + ts.tv_nsec * 1e-9; -+ } -+ { -+ struct timeval tv; -+ TEST_VERIFY_EXIT (gettimeofday (&tv, NULL) == 0); -+ return tv.tv_sec + tv.tv_usec * 1e-6; -+ } -+} -+ -+static int -+do_test (void) -+{ -+ support_become_root (); -+ support_enter_network_namespace (); -+ -+ /* Information about the test servers. */ -+ struct -+ { -+ SVCXPRT *transport; -+ struct sockaddr_in address; -+ pid_t pid; -+ uint32_t xid; -+ } servers[SERVER_COUNT]; -+ -+ /* Spawn the test servers. */ -+ for (int i = 0; i < SERVER_COUNT; ++i) -+ { -+ servers[i].transport = svcudp_create (RPC_ANYSOCK); -+ TEST_VERIFY_EXIT (servers[i].transport != NULL); -+ servers[i].address = (struct sockaddr_in) -+ { -+ .sin_family = AF_INET, -+ .sin_addr.s_addr = htonl (INADDR_LOOPBACK), -+ .sin_port = htons (servers[i].transport->xp_port), -+ }; -+ servers[i].xid = 0xabcd0101 + i; -+ if (test_verbose) -+ printf ("info: setting up server %d xid=%x on port %d\n", -+ i, servers[i].xid, servers[i].transport->xp_port); -+ -+ server_id = i; -+ servers[i].pid = xfork (); -+ if (servers[i].pid == 0) -+ { -+ TEST_VERIFY (svc_register (servers[i].transport, -+ PROGNUM, VERSNUM, server_dispatch, 0)); -+ svc_run (); -+ FAIL_EXIT1 ("supposed to be unreachable"); -+ } -+ /* We need to close the socket so that we do not accidentally -+ consume the request. */ -+ TEST_VERIFY (close (servers[i].transport->xp_sock) == 0); -+ } -+ -+ -+ /* The following code mirrors what ypbind does. */ -+ -+ /* Copied from clnt_udp.c (like ypbind). */ -+ struct cu_data -+ { -+ int cu_sock; -+ bool_t cu_closeit; -+ struct sockaddr_in cu_raddr; -+ int cu_rlen; -+ struct timeval cu_wait; -+ struct timeval cu_total; -+ struct rpc_err cu_error; -+ XDR cu_outxdrs; -+ u_int cu_xdrpos; -+ u_int cu_sendsz; -+ char *cu_outbuf; -+ u_int cu_recvsz; -+ char cu_inbuf[1]; -+ }; -+ -+ int client_socket = xsocket (AF_INET, SOCK_DGRAM | SOCK_NONBLOCK, 0); -+ CLIENT *clnt = clntudp_create (&servers[0].address, PROGNUM, VERSNUM, -+ /* 5 seconds per-response timeout. */ -+ ((struct timeval) { 5, 0 }), -+ &client_socket); -+ TEST_VERIFY (clnt != NULL); -+ clnt->cl_auth = authunix_create_default (); -+ { -+ struct timeval zero = { 0, 0 }; -+ TEST_VERIFY (clnt_control (clnt, CLSET_TIMEOUT, (void *) &zero)); -+ } -+ -+ /* Poke at internal data structures (like ypbind). */ -+ struct cu_data *cu = (struct cu_data *) clnt->cl_private; -+ -+ /* Send a ping to each server. */ -+ double before_pings = get_ticks (); -+ for (int i = 0; i < SERVER_COUNT; ++i) -+ { -+ if (test_verbose) -+ printf ("info: sending server %d ping\n", i); -+ /* Reset the xid because it is changed by each invocation of -+ clnt_call. Subtract one to compensate for the xid update -+ during the call. */ -+ *((u_int32_t *) (cu->cu_outbuf)) = servers[i].xid - 1; -+ cu->cu_raddr = servers[i].address; -+ -+ struct test_query query = { .a = 100, .b = i + 1 }; -+ if (i == 1) -+ /* Shorter timeout to prefer this server. These timeouts must -+ be much shorter than the 5-second per-response timeout -+ configured with clntudp_create. */ -+ query.timeout_ms = 700; -+ else -+ query.timeout_ms = 1400; -+ struct test_response response = { 0 }; -+ /* NB: Do not check the return value. The server reply will -+ prove that the call worked. */ -+ double before_one_ping = get_ticks (); -+ clnt_call (clnt, PROC_ADD, -+ xdr_test_query, (void *) &query, -+ xdr_test_response, (void *) &response, -+ ((struct timeval) { 0, 0 })); -+ double after_one_ping = get_ticks (); -+ if (test_verbose) -+ printf ("info: non-blocking send took %f seconds\n", -+ after_one_ping - before_one_ping); -+ /* clnt_call should return immediately. Accept some delay in -+ case the process is descheduled. */ -+ TEST_VERIFY (after_one_ping - before_one_ping < 0.3); -+ } -+ -+ /* Collect the non-blocking response. */ -+ if (test_verbose) -+ printf ("info: collecting response\n"); -+ struct test_response response = { 0 }; -+ TEST_VERIFY -+ (clnt_call (clnt, PROC_ADD, NULL, NULL, -+ xdr_test_response, (void *) &response, -+ ((struct timeval) { 0, 0 })) == RPC_SUCCESS); -+ double after_pings = get_ticks (); -+ if (test_verbose) -+ printf ("info: send/receive took %f seconds\n", -+ after_pings - before_pings); -+ /* Expected timeout is 0.7 seconds. */ -+ TEST_VERIFY (0.7 <= after_pings - before_pings); -+ TEST_VERIFY (after_pings - before_pings < 1.2); -+ -+ uint32_t xid; -+ memcpy (&xid, &cu->cu_inbuf, sizeof (xid)); -+ if (test_verbose) -+ printf ("info: non-blocking response: xid=%x server_id=%u seq=%u sum=%u\n", -+ xid, response.server_id, response.seq, response.sum); -+ /* Check that the reply from the preferred server was used. */ -+ TEST_VERIFY (servers[1].xid == xid); -+ TEST_VERIFY (response.server_id == 1); -+ TEST_VERIFY (response.seq == 1); -+ TEST_VERIFY (response.sum == 102); -+ -+ auth_destroy (clnt->cl_auth); -+ clnt_destroy (clnt); -+ -+ for (int i = 0; i < SERVER_COUNT; ++i) -+ { -+ if (test_verbose) -+ printf ("info: requesting server %d termination\n", i); -+ client_socket = RPC_ANYSOCK; -+ clnt = clntudp_create (&servers[i].address, PROGNUM, VERSNUM, -+ ((struct timeval) { 5, 0 }), -+ &client_socket); -+ TEST_VERIFY_EXIT (clnt != NULL); -+ TEST_VERIFY (clnt_call (clnt, PROC_EXIT, -+ (xdrproc_t) xdr_void, NULL, -+ (xdrproc_t) xdr_void, NULL, -+ ((struct timeval) { 3, 0 })) == RPC_SUCCESS); -+ clnt_destroy (clnt); -+ -+ int status; -+ xwaitpid (servers[i].pid, &status, 0); -+ TEST_VERIFY (WIFEXITED (status) && WEXITSTATUS (status) == EXIT_MARKER); -+ } -+ -+ return 0; -+} -+ -+#include -diff --git a/sunrpc/tst-udp-timeout.c b/sunrpc/tst-udp-timeout.c -new file mode 100644 -index 0000000000..db9943a03e ---- /dev/null -+++ b/sunrpc/tst-udp-timeout.c -@@ -0,0 +1,402 @@ -+/* Test timeout handling in the UDP client. -+ 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 -+ . */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/* Test data serialization and deserialization. */ -+ -+struct test_query -+{ -+ uint32_t a; -+ uint32_t b; -+ uint32_t timeout_ms; -+ uint32_t wait_for_seq; -+ uint32_t garbage_packets; -+}; -+ -+static bool_t -+xdr_test_query (XDR *xdrs, void *data, ...) -+{ -+ struct test_query *p = data; -+ return xdr_uint32_t (xdrs, &p->a) -+ && xdr_uint32_t (xdrs, &p->b) -+ && xdr_uint32_t (xdrs, &p->timeout_ms) -+ && xdr_uint32_t (xdrs, &p->wait_for_seq) -+ && xdr_uint32_t (xdrs, &p->garbage_packets); -+} -+ -+struct test_response -+{ -+ uint32_t seq; -+ uint32_t sum; -+}; -+ -+static bool_t -+xdr_test_response (XDR *xdrs, void *data, ...) -+{ -+ struct test_response *p = data; -+ return xdr_uint32_t (xdrs, &p->seq) -+ && xdr_uint32_t (xdrs, &p->sum); -+} -+ -+/* Implementation of the test server. */ -+ -+enum -+ { -+ /* RPC parameters, chosen at random. */ -+ PROGNUM = 15717, -+ VERSNUM = 13689, -+ -+ /* Main RPC operation. */ -+ PROC_ADD = 1, -+ -+ /* Reset the sequence number. */ -+ PROC_RESET_SEQ, -+ -+ /* Request process termination. */ -+ PROC_EXIT, -+ -+ /* Special exit status to mark successful processing. */ -+ EXIT_MARKER = 55, -+ }; -+ -+static void -+server_dispatch (struct svc_req *request, SVCXPRT *transport) -+{ -+ /* Query sequence number. */ -+ static uint32_t seq = 0; -+ ++seq; -+ -+ if (test_verbose) -+ printf ("info: server_dispatch seq=%u rq_proc=%lu\n", -+ seq, request->rq_proc); -+ -+ switch (request->rq_proc) -+ { -+ case PROC_ADD: -+ { -+ struct test_query query; -+ memset (&query, 0xc0, sizeof (query)); -+ TEST_VERIFY_EXIT -+ (svc_getargs (transport, xdr_test_query, -+ (void *) &query)); -+ -+ if (test_verbose) -+ printf (" a=%u b=%u timeout_ms=%u wait_for_seq=%u" -+ " garbage_packets=%u\n", -+ query.a, query.b, query.timeout_ms, query.wait_for_seq, -+ query.garbage_packets); -+ -+ if (seq < query.wait_for_seq) -+ { -+ /* No response at this point. */ -+ if (test_verbose) -+ printf (" skipped response\n"); -+ break; -+ } -+ -+ if (query.garbage_packets > 0) -+ { -+ int per_packet_timeout; -+ if (query.timeout_ms > 0) -+ per_packet_timeout -+ = query.timeout_ms * 1000 / query.garbage_packets; -+ else -+ per_packet_timeout = 0; -+ -+ char buf[20]; -+ memset (&buf, 0xc0, sizeof (buf)); -+ for (int i = 0; i < query.garbage_packets; ++i) -+ { -+ /* 13 is relatively prime to 20 = sizeof (buf) + 1, so -+ the len variable will cover the entire interval -+ [0, 20] if query.garbage_packets is sufficiently -+ large. */ -+ size_t len = (i * 13 + 1) % (sizeof (buf) + 1); -+ TEST_VERIFY (sendto (transport->xp_sock, -+ buf, len, MSG_NOSIGNAL, -+ (struct sockaddr *) &transport->xp_raddr, -+ transport->xp_addrlen) == len); -+ if (per_packet_timeout > 0) -+ usleep (per_packet_timeout); -+ } -+ } -+ else if (query.timeout_ms > 0) -+ usleep (query.timeout_ms * 1000); -+ -+ struct test_response response = -+ { -+ .seq = seq, -+ .sum = query.a + query.b, -+ }; -+ TEST_VERIFY (svc_sendreply (transport, xdr_test_response, -+ (void *) &response)); -+ } -+ break; -+ -+ case PROC_RESET_SEQ: -+ seq = 0; -+ TEST_VERIFY (svc_sendreply (transport, (xdrproc_t) xdr_void, NULL)); -+ break; -+ -+ case PROC_EXIT: -+ TEST_VERIFY (svc_sendreply (transport, (xdrproc_t) xdr_void, NULL)); -+ _exit (EXIT_MARKER); -+ break; -+ -+ default: -+ FAIL_EXIT1 ("invalid rq_proc value: %lu", request->rq_proc); -+ break; -+ } -+} -+ -+/* Implementation of the test client. */ -+ -+static struct test_response -+test_call (CLIENT *clnt, int proc, struct test_query query, -+ struct timeval timeout) -+{ -+ if (test_verbose) -+ printf ("info: test_call proc=%d timeout=%lu.%06lu\n", -+ proc, (unsigned long) timeout.tv_sec, -+ (unsigned long) timeout.tv_usec); -+ struct test_response response; -+ TEST_VERIFY_EXIT (clnt_call (clnt, proc, -+ xdr_test_query, (void *) &query, -+ xdr_test_response, (void *) &response, -+ timeout) -+ == RPC_SUCCESS); -+ return response; -+} -+ -+static void -+test_call_timeout (CLIENT *clnt, int proc, struct test_query query, -+ struct timeval timeout) -+{ -+ struct test_response response; -+ TEST_VERIFY (clnt_call (clnt, proc, -+ xdr_test_query, (void *) &query, -+ xdr_test_response, (void *) &response, -+ timeout) -+ == RPC_TIMEDOUT); -+} -+ -+/* Complete one regular RPC call to drain the server socket -+ buffer. Resets the sequence number. */ -+static void -+test_call_flush (CLIENT *clnt) -+{ -+ /* This needs a longer timeout to flush out all pending requests. -+ The choice of 5 seconds is larger than the per-response timeouts -+ requested via the timeout_ms field. */ -+ if (test_verbose) -+ printf ("info: flushing pending queries\n"); -+ TEST_VERIFY_EXIT (clnt_call (clnt, PROC_RESET_SEQ, -+ (xdrproc_t) xdr_void, NULL, -+ (xdrproc_t) xdr_void, NULL, -+ ((struct timeval) { 5, 0 })) -+ == RPC_SUCCESS); -+} -+ -+/* Return the number seconds since an arbitrary point in time. */ -+static double -+get_ticks (void) -+{ -+ { -+ struct timespec ts; -+ if (clock_gettime (CLOCK_MONOTONIC, &ts) == 0) -+ return ts.tv_sec + ts.tv_nsec * 1e-9; -+ } -+ { -+ struct timeval tv; -+ TEST_VERIFY_EXIT (gettimeofday (&tv, NULL) == 0); -+ return tv.tv_sec + tv.tv_usec * 1e-6; -+ } -+} -+ -+static void -+test_udp_server (int port) -+{ -+ struct sockaddr_in sin = -+ { -+ .sin_family = AF_INET, -+ .sin_addr.s_addr = htonl (INADDR_LOOPBACK), -+ .sin_port = htons (port) -+ }; -+ int sock = RPC_ANYSOCK; -+ -+ /* The client uses a 1.5 second timeout for retries. The timeouts -+ are arbitrary, but chosen so that there is a substantial gap -+ between them, but the total time spent waiting is not too -+ large. */ -+ CLIENT *clnt = clntudp_create (&sin, PROGNUM, VERSNUM, -+ (struct timeval) { 1, 500 * 1000 }, -+ &sock); -+ TEST_VERIFY_EXIT (clnt != NULL); -+ -+ /* Basic call/response test. */ -+ struct test_response response = test_call -+ (clnt, PROC_ADD, -+ (struct test_query) { .a = 17, .b = 4 }, -+ (struct timeval) { 3, 0 }); -+ TEST_VERIFY (response.sum == 21); -+ TEST_VERIFY (response.seq == 1); -+ -+ /* Check that garbage packets do not interfere with timeout -+ processing. */ -+ double before = get_ticks (); -+ response = test_call -+ (clnt, PROC_ADD, -+ (struct test_query) { -+ .a = 19, .b = 4, .timeout_ms = 500, .garbage_packets = 21, -+ }, -+ (struct timeval) { 3, 0 }); -+ TEST_VERIFY (response.sum == 23); -+ TEST_VERIFY (response.seq == 2); -+ double after = get_ticks (); -+ if (test_verbose) -+ printf ("info: 21 garbage packets took %f seconds\n", after - before); -+ /* Expected timeout is 0.5 seconds. Add some slack in case process -+ scheduling delays processing the query or response, but do not -+ accept a retry (which would happen at 1.5 seconds). */ -+ TEST_VERIFY (0.5 <= after - before); -+ TEST_VERIFY (after - before < 1.2); -+ test_call_flush (clnt); -+ -+ /* Check that missing a response introduces a 1.5 second timeout, as -+ requested when calling clntudp_create. */ -+ before = get_ticks (); -+ response = test_call -+ (clnt, PROC_ADD, -+ (struct test_query) { .a = 170, .b = 40, .wait_for_seq = 2 }, -+ (struct timeval) { 3, 0 }); -+ TEST_VERIFY (response.sum == 210); -+ TEST_VERIFY (response.seq == 2); -+ after = get_ticks (); -+ if (test_verbose) -+ printf ("info: skipping one response took %f seconds\n", -+ after - before); -+ /* Expected timeout is 1.5 seconds. Do not accept a second retry -+ (which would happen at 3 seconds). */ -+ TEST_VERIFY (1.5 <= after - before); -+ TEST_VERIFY (after - before < 2.9); -+ test_call_flush (clnt); -+ -+ /* Check that the overall timeout wins against the per-query -+ timeout. */ -+ before = get_ticks (); -+ test_call_timeout -+ (clnt, PROC_ADD, -+ (struct test_query) { .a = 170, .b = 41, .wait_for_seq = 2 }, -+ (struct timeval) { 0, 750 * 1000 }); -+ after = get_ticks (); -+ if (test_verbose) -+ printf ("info: 0.75 second timeout took %f seconds\n", -+ after - before); -+ TEST_VERIFY (0.75 <= after - before); -+ TEST_VERIFY (after - before < 1.4); -+ test_call_flush (clnt); -+ -+ for (int with_garbage = 0; with_garbage < 2; ++with_garbage) -+ { -+ /* Check that no response at all causes the client to bail out. */ -+ before = get_ticks (); -+ test_call_timeout -+ (clnt, PROC_ADD, -+ (struct test_query) { -+ .a = 170, .b = 40, .timeout_ms = 1200, -+ .garbage_packets = with_garbage * 21 -+ }, -+ (struct timeval) { 0, 750 * 1000 }); -+ after = get_ticks (); -+ if (test_verbose) -+ printf ("info: test_udp_server: 0.75 second timeout took %f seconds" -+ " (garbage %d)\n", -+ after - before, with_garbage); -+ TEST_VERIFY (0.75 <= after - before); -+ TEST_VERIFY (after - before < 1.4); -+ test_call_flush (clnt); -+ -+ /* As above, but check the total timeout. */ -+ before = get_ticks (); -+ test_call_timeout -+ (clnt, PROC_ADD, -+ (struct test_query) { -+ .a = 170, .b = 40, .timeout_ms = 3000, -+ .garbage_packets = with_garbage * 30 -+ }, -+ (struct timeval) { 2, 300 * 1000 }); -+ after = get_ticks (); -+ if (test_verbose) -+ printf ("info: test_udp_server: 2.3 second timeout took %f seconds" -+ " (garbage %d)\n", -+ after - before, with_garbage); -+ TEST_VERIFY (2.3 <= after - before); -+ TEST_VERIFY (after - before < 3.0); -+ test_call_flush (clnt); -+ } -+ -+ TEST_VERIFY_EXIT (clnt_call (clnt, PROC_EXIT, -+ (xdrproc_t) xdr_void, NULL, -+ (xdrproc_t) xdr_void, NULL, -+ ((struct timeval) { 5, 0 })) -+ == RPC_SUCCESS); -+ clnt_destroy (clnt); -+} -+ -+static int -+do_test (void) -+{ -+ support_become_root (); -+ support_enter_network_namespace (); -+ -+ SVCXPRT *transport = svcudp_create (RPC_ANYSOCK); -+ TEST_VERIFY_EXIT (transport != NULL); -+ TEST_VERIFY (svc_register (transport, PROGNUM, VERSNUM, server_dispatch, 0)); -+ -+ pid_t pid = xfork (); -+ if (pid == 0) -+ { -+ svc_run (); -+ FAIL_EXIT1 ("supposed to be unreachable"); -+ } -+ test_udp_server (transport->xp_port); -+ -+ int status; -+ xwaitpid (pid, &status, 0); -+ TEST_VERIFY (WIFEXITED (status) && WEXITSTATUS (status) == EXIT_MARKER); -+ -+ SVC_DESTROY (transport); -+ return 0; -+} -+ -+/* The minimum run time is around 17 seconds. */ -+#define TIMEOUT 25 -+#include -diff --git a/support/Makefile b/support/Makefile -index 2ace559ae0..027a663000 100644 ---- a/support/Makefile -+++ b/support/Makefile -@@ -35,7 +35,12 @@ libsupport-routines = \ - oom_error \ - resolv_test \ - set_fortify_handler \ -+ support-xstat \ - support_become_root \ -+ support_can_chroot \ -+ support_capture_subprocess \ -+ support_capture_subprocess_check \ -+ support_chroot \ - support_enter_network_namespace \ - support_format_address_family \ - support_format_addrinfo \ -@@ -43,17 +48,25 @@ libsupport-routines = \ - support_format_herrno \ - support_format_hostent \ - support_format_netent \ -+ support_isolate_in_subprocess \ - support_record_failure \ - support_run_diff \ -+ support_shared_allocate \ -+ support_write_file_string \ - support_test_main \ - support_test_verify_impl \ - temp_file \ - write_message \ - xaccept \ -+ xaccept4 \ - xasprintf \ - xbind \ - xcalloc \ -+ xchroot \ -+ xclose \ - xconnect \ -+ xdlfcn \ -+ xdup2 \ - xfclose \ - xfopen \ - xfork \ -@@ -61,13 +74,18 @@ libsupport-routines = \ - xlisten \ - xmalloc \ - xmemstream \ -+ xmkdir \ - xmmap \ -+ xmprotect \ - xmunmap \ -+ xopen \ -+ xpipe \ - xpoll \ - xpthread_attr_destroy \ - xpthread_attr_init \ - xpthread_attr_setdetachstate \ - xpthread_attr_setstacksize \ -+ xpthread_attr_setguardsize \ - xpthread_barrier_destroy \ - xpthread_barrier_init \ - xpthread_barrier_wait \ -@@ -89,6 +107,12 @@ libsupport-routines = \ - xpthread_mutexattr_setrobust \ - xpthread_mutexattr_settype \ - xpthread_once \ -+ xpthread_rwlock_init \ -+ xpthread_rwlock_rdlock \ -+ xpthread_rwlock_wrlock \ -+ xpthread_rwlock_unlock \ -+ xpthread_rwlockattr_init \ -+ xpthread_rwlockattr_setkind_np \ - xpthread_sigmask \ - xpthread_spin_lock \ - xpthread_spin_unlock \ -@@ -111,6 +135,8 @@ endif - tests = \ - README-testing \ - tst-support-namespace \ -+ tst-support_capture_subprocess \ -+ tst-support_format_dns_packet \ - tst-support_record_failure \ - - ifeq ($(run-built-tests),yes) -@@ -125,4 +151,6 @@ $(objpfx)tst-support_record_failure-2.out: tst-support_record_failure-2.sh \ - $(evaluate-test) - endif - -+$(objpfx)tst-support_format_dns_packet: $(common-objpfx)resolv/libresolv.so -+ - include ../Rules -diff --git a/support/capture_subprocess.h b/support/capture_subprocess.h -new file mode 100644 -index 0000000000..43caf9bce4 ---- /dev/null -+++ b/support/capture_subprocess.h -@@ -0,0 +1,61 @@ -+/* Capture output from a subprocess. -+ 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 -+ . */ -+ -+#ifndef SUPPORT_CAPTURE_SUBPROCESS_H -+#define SUPPORT_CAPTURE_SUBPROCESS_H -+ -+#include -+ -+struct support_capture_subprocess -+{ -+ struct xmemstream out; -+ struct xmemstream err; -+ int status; -+}; -+ -+/* Invoke CALLBACK (CLOSURE) in a subprocess and capture standard -+ output, standard error, and the exit status. The out.buffer and -+ err.buffer members in the result are null-terminated strings which -+ can be examined by the caller (out.out and err.out are NULL). */ -+struct support_capture_subprocess support_capture_subprocess -+ (void (*callback) (void *), void *closure); -+ -+/* Deallocate the subprocess data captured by -+ support_capture_subprocess. */ -+void support_capture_subprocess_free (struct support_capture_subprocess *); -+ -+enum support_capture_allow -+{ -+ /* No output is allowed. */ -+ sc_allow_none = 0x01, -+ /* Output to stdout is permitted. */ -+ sc_allow_stdout = 0x02, -+ /* Output to standard error is permitted. */ -+ sc_allow_stderr = 0x04, -+}; -+ -+/* Check that the subprocess exited with STATUS and that only the -+ allowed outputs happened. ALLOWED is a combination of -+ support_capture_allow flags. Report errors under the CONTEXT -+ message. */ -+void support_capture_subprocess_check (struct support_capture_subprocess *, -+ const char *context, int status, -+ int allowed) -+ __attribute__ ((nonnull (1, 2))); -+ -+#endif /* SUPPORT_CAPTURE_SUBPROCESS_H */ -diff --git a/support/check.h b/support/check.h -index 1d244a3557..bdcd12952a 100644 ---- a/support/check.h -+++ b/support/check.h -@@ -51,7 +51,7 @@ __BEGIN_DECLS - if (expr) \ - ; \ - else \ -- support_test_verify_impl (-1, __FILE__, __LINE__, #expr); \ -+ support_test_verify_impl (__FILE__, __LINE__, #expr); \ - }) - - /* Record a test failure and exit if EXPR evaluates to false. */ -@@ -60,7 +60,8 @@ __BEGIN_DECLS - if (expr) \ - ; \ - else \ -- support_test_verify_impl (1, __FILE__, __LINE__, #expr); \ -+ support_test_verify_exit_impl \ -+ (1, __FILE__, __LINE__, #expr); \ - }) - - int support_print_failure_impl (const char *file, int line, -@@ -70,8 +71,11 @@ void support_exit_failure_impl (int exit_status, - const char *file, int line, - const char *format, ...) - __attribute__ ((noreturn, nonnull (2), format (printf, 4, 5))); --void support_test_verify_impl (int status, const char *file, int line, -+void support_test_verify_impl (const char *file, int line, - const char *expr); -+void support_test_verify_exit_impl (int status, const char *file, int line, -+ const char *expr) -+ __attribute__ ((noreturn)); - - /* Record a test failure. This function returns and does not - terminate the process. The failure counter is stored in a shared -diff --git a/support/namespace.h b/support/namespace.h -index 6bc82d619b..9eddb1a0e9 100644 ---- a/support/namespace.h -+++ b/support/namespace.h -@@ -35,6 +35,13 @@ __BEGIN_DECLS - single-threaded processes. */ - bool support_become_root (void); - -+/* Return true if this process can perform a chroot operation. In -+ general, this is only possible if support_become_root has been -+ called. Note that the actual test is performed in a subprocess, -+ after fork, so that the file system root of the original process is -+ not changed. */ -+bool support_can_chroot (void); -+ - /* Enter a network namespace (and a UTS namespace if possible) and - configure the loopback interface. Return true if a network - namespace could be created. Print diagnostics to standard output. -@@ -48,6 +55,48 @@ bool support_enter_network_namespace (void); - UTS namespace. */ - bool support_in_uts_namespace (void); - -+/* Invoke CALLBACK (CLOSURE) in a subprocess created using fork. -+ Terminate the calling process if the subprocess exits with a -+ non-zero exit status. */ -+void support_isolate_in_subprocess (void (*callback) (void *), void *closure); -+ -+/* Describe the setup of a chroot environment, for -+ support_chroot_create below. */ -+struct support_chroot_configuration -+{ -+ /* File contents. The files are not created if the field is -+ NULL. */ -+ const char *resolv_conf; /* /etc/resolv.conf. */ -+ const char *hosts; /* /etc/hosts. */ -+ const char *host_conf; /* /etc/host.conf. */ -+}; -+ -+/* The result of the creation of a chroot. */ -+struct support_chroot -+{ -+ /* Path information. All these paths are relative to the parent -+ chroot. */ -+ -+ /* Path to the chroot directory. */ -+ char *path_chroot; -+ -+ /* Paths to files in the chroot. These are absolute and outside of -+ the chroot. */ -+ char *path_resolv_conf; /* /etc/resolv.conf. */ -+ char *path_hosts; /* /etc/hosts. */ -+ char *path_host_conf; /* /etc/host.conf. */ -+}; -+ -+/* Create a chroot environment. The returned data should be freed -+ using support_chroot_free below. The files will be deleted when -+ the process exits. This function does not enter the chroot. */ -+struct support_chroot *support_chroot_create -+ (struct support_chroot_configuration); -+ -+/* Deallocate the chroot information created by -+ support_chroot_create. */ -+void support_chroot_free (struct support_chroot *); -+ - __END_DECLS - - #endif -diff --git a/support/resolv_test.c b/support/resolv_test.c -index 2d0ea3c17c..1625dcf43a 100644 ---- a/support/resolv_test.c -+++ b/support/resolv_test.c -@@ -32,9 +32,11 @@ - #include - #include - #include -+#include -+#include - #include - --/* Response builder. */ -+/* Response builder. */ - - enum - { -@@ -428,6 +430,7 @@ struct query_info - char qname[MAXDNAME]; - uint16_t qclass; - uint16_t qtype; -+ struct resolv_edns_info edns; - }; - - /* Update *INFO from the specified DNS packet. */ -@@ -435,10 +438,26 @@ static void - parse_query (struct query_info *info, - const unsigned char *buffer, size_t length) - { -- if (length < 12) -+ HEADER hd; -+ _Static_assert (sizeof (hd) == 12, "DNS header size"); -+ if (length < sizeof (hd)) - FAIL_EXIT1 ("malformed DNS query: too short: %zu bytes", length); -- -- int ret = dn_expand (buffer, buffer + length, buffer + 12, -+ memcpy (&hd, buffer, sizeof (hd)); -+ -+ if (ntohs (hd.qdcount) != 1) -+ FAIL_EXIT1 ("malformed DNS query: wrong question count: %d", -+ (int) ntohs (hd.qdcount)); -+ if (ntohs (hd.ancount) != 0) -+ FAIL_EXIT1 ("malformed DNS query: wrong answer count: %d", -+ (int) ntohs (hd.ancount)); -+ if (ntohs (hd.nscount) != 0) -+ FAIL_EXIT1 ("malformed DNS query: wrong authority count: %d", -+ (int) ntohs (hd.nscount)); -+ if (ntohs (hd.arcount) > 1) -+ FAIL_EXIT1 ("malformed DNS query: wrong additional count: %d", -+ (int) ntohs (hd.arcount)); -+ -+ int ret = dn_expand (buffer, buffer + length, buffer + sizeof (hd), - info->qname, sizeof (info->qname)); - if (ret < 0) - FAIL_EXIT1 ("malformed DNS query: cannot uncompress QNAME"); -@@ -456,6 +475,37 @@ parse_query (struct query_info *info, - memcpy (&qtype_qclass, buffer + 12 + ret, sizeof (qtype_qclass)); - info->qclass = ntohs (qtype_qclass.qclass); - info->qtype = ntohs (qtype_qclass.qtype); -+ -+ memset (&info->edns, 0, sizeof (info->edns)); -+ if (ntohs (hd.arcount) > 0) -+ { -+ /* Parse EDNS record. */ -+ struct __attribute__ ((packed, aligned (1))) -+ { -+ uint8_t root; -+ uint16_t rtype; -+ uint16_t payload; -+ uint8_t edns_extended_rcode; -+ uint8_t edns_version; -+ uint16_t flags; -+ uint16_t rdatalen; -+ } rr; -+ _Static_assert (sizeof (rr) == 11, "EDNS record size"); -+ -+ if (remaining < 4 + sizeof (rr)) -+ FAIL_EXIT1 ("mailformed DNS query: no room for EDNS record"); -+ memcpy (&rr, buffer + 12 + ret + 4, sizeof (rr)); -+ if (rr.root != 0) -+ FAIL_EXIT1 ("malformed DNS query: invalid OPT RNAME: %d\n", rr.root); -+ if (rr.rtype != htons (41)) -+ FAIL_EXIT1 ("malformed DNS query: invalid OPT type: %d\n", -+ ntohs (rr.rtype)); -+ info->edns.active = true; -+ info->edns.extended_rcode = rr.edns_extended_rcode; -+ info->edns.version = rr.edns_version; -+ info->edns.flags = ntohs (rr.flags); -+ info->edns.payload_size = ntohs (rr.payload); -+ } - } - - -@@ -585,6 +635,7 @@ server_thread_udp_process_one (struct resolv_test *obj, int server_index) - .query_length = length, - .server_index = server_index, - .tcp = false, -+ .edns = qinfo.edns, - }; - struct resolv_response_builder *b = response_builder_allocate (query, length); - obj->config.response_callback -@@ -820,6 +871,7 @@ server_thread_tcp_client (void *arg) - .query_length = query_length, - .server_index = closure->server_index, - .tcp = true, -+ .edns = qinfo.edns, - }; - struct resolv_response_builder *b = response_builder_allocate - (query_buffer, query_length); -@@ -860,7 +912,7 @@ server_thread_tcp_client (void *arg) - break; - } - -- close (closure->client_socket); -+ xclose (closure->client_socket); - free (closure); - return NULL; - } -@@ -881,7 +933,7 @@ server_thread_tcp (struct resolv_test *obj, int server_index) - if (obj->termination_requested) - { - xpthread_mutex_unlock (&obj->lock); -- close (client_socket); -+ xclose (client_socket); - break; - } - xpthread_mutex_unlock (&obj->lock); -@@ -941,8 +993,8 @@ make_server_sockets (struct resolv_test_server *server) - next local UDP address randomly. */ - if (errno == EADDRINUSE) - { -- close (server->socket_udp); -- close (server->socket_tcp); -+ xclose (server->socket_udp); -+ xclose (server->socket_tcp); - continue; - } - FAIL_EXIT1 ("TCP bind: %m"); -@@ -952,6 +1004,29 @@ make_server_sockets (struct resolv_test_server *server) - } - } - -+/* Like make_server_sockets, but the caller supplies the address to -+ use. */ -+static void -+make_server_sockets_for_address (struct resolv_test_server *server, -+ const struct sockaddr *addr) -+{ -+ server->socket_udp = xsocket (AF_INET, SOCK_DGRAM, IPPROTO_UDP); -+ server->socket_tcp = xsocket (AF_INET, SOCK_STREAM, IPPROTO_TCP); -+ -+ if (addr->sa_family == AF_INET) -+ server->address = *(const struct sockaddr_in *) addr; -+ else -+ /* We cannot store the server address in the socket. This should -+ not matter if disable_redirect is used. */ -+ server->address = (struct sockaddr_in) { .sin_family = 0, }; -+ -+ xbind (server->socket_udp, -+ (struct sockaddr *)&server->address, sizeof (server->address)); -+ xbind (server->socket_tcp, -+ (struct sockaddr *)&server->address, sizeof (server->address)); -+ xlisten (server->socket_tcp, 5); -+} -+ - /* One-time initialization of NSS. */ - static void - resolv_redirect_once (void) -@@ -1012,11 +1087,17 @@ resolv_test_start (struct resolv_redirect_config config) - .lock = PTHREAD_MUTEX_INITIALIZER, - }; - -- resolv_test_init (); -+ if (!config.disable_redirect) -+ resolv_test_init (); - - /* Create all the servers, to reserve the necessary ports. */ - for (int server_index = 0; server_index < config.nscount; ++server_index) -- make_server_sockets (obj->servers + server_index); -+ if (config.disable_redirect && config.server_address_overrides != NULL) -+ make_server_sockets_for_address -+ (obj->servers + server_index, -+ config.server_address_overrides[server_index]); -+ else -+ make_server_sockets (obj->servers + server_index); - - /* Start server threads. Disable the server ports, as - requested. */ -@@ -1025,7 +1106,7 @@ resolv_test_start (struct resolv_redirect_config config) - struct resolv_test_server *server = obj->servers + server_index; - if (config.servers[server_index].disable_udp) - { -- close (server->socket_udp); -+ xclose (server->socket_udp); - server->socket_udp = -1; - } - else if (!config.single_thread_udp) -@@ -1033,7 +1114,7 @@ resolv_test_start (struct resolv_redirect_config config) - server_thread_udp); - if (config.servers[server_index].disable_tcp) - { -- close (server->socket_tcp); -+ xclose (server->socket_tcp); - server->socket_tcp = -1; - } - else -@@ -1043,6 +1124,9 @@ resolv_test_start (struct resolv_redirect_config config) - if (config.single_thread_udp) - start_server_thread_udp_single (obj); - -+ if (config.disable_redirect) -+ return obj; -+ - int timeout = 1; - - /* Initialize libresolv. */ -@@ -1077,6 +1161,7 @@ resolv_test_start (struct resolv_redirect_config config) - } - for (int server_index = 0; server_index < config.nscount; ++server_index) - { -+ TEST_VERIFY_EXIT (obj->servers[server_index].address.sin_port != 0); - _res.nsaddr_list[server_index] = obj->servers[server_index].address; - if (test_verbose) - { -@@ -1114,7 +1199,7 @@ resolv_test_end (struct resolv_test *obj) - xsendto (sock, "", 1, 0, - (struct sockaddr *) &obj->servers[server_index].address, - sizeof (obj->servers[server_index].address)); -- close (sock); -+ xclose (sock); - } - if (!obj->config.servers[server_index].disable_tcp) - { -@@ -1122,7 +1207,7 @@ resolv_test_end (struct resolv_test *obj) - xconnect (sock, - (struct sockaddr *) &obj->servers[server_index].address, - sizeof (obj->servers[server_index].address)); -- close (sock); -+ xclose (sock); - } - } - -@@ -1137,12 +1222,12 @@ resolv_test_end (struct resolv_test *obj) - { - if (!obj->config.single_thread_udp) - xpthread_join (obj->servers[server_index].thread_udp); -- close (obj->servers[server_index].socket_udp); -+ xclose (obj->servers[server_index].socket_udp); - } - if (!obj->config.servers[server_index].disable_tcp) - { - xpthread_join (obj->servers[server_index].thread_tcp); -- close (obj->servers[server_index].socket_tcp); -+ xclose (obj->servers[server_index].socket_tcp); - } - } - -diff --git a/support/resolv_test.h b/support/resolv_test.h -index 7a9f1f7ae8..b953dc1200 100644 ---- a/support/resolv_test.h -+++ b/support/resolv_test.h -@@ -25,6 +25,16 @@ - - __BEGIN_DECLS - -+/* Information about EDNS properties of a DNS query. */ -+struct resolv_edns_info -+{ -+ bool active; -+ uint8_t extended_rcode; -+ uint8_t version; -+ uint16_t flags; -+ uint16_t payload_size; -+}; -+ - /* This struct provides context information when the response callback - specified in struct resolv_redirect_config is invoked. */ - struct resolv_response_context -@@ -33,6 +43,7 @@ struct resolv_response_context - size_t query_length; - int server_index; - bool tcp; -+ struct resolv_edns_info edns; - }; - - /* This opaque struct is used to construct responses from within the -@@ -82,6 +93,16 @@ struct resolv_redirect_config - may results in more predictable ordering of queries and - responses. */ - bool single_thread_udp; -+ -+ /* Do not rewrite the _res variable or change NSS defaults. Use -+ server_address_overrides below to tell the testing framework on -+ which addresses to create the servers. */ -+ bool disable_redirect; -+ -+ /* Use these addresses for creating the DNS servers. The array must -+ have ns_count (or resolv_max_test_servers) sockaddr * elements if -+ not NULL. */ -+ const struct sockaddr *const *server_address_overrides; - }; - - /* Configure NSS to use, nss_dns only for aplicable databases, and try -diff --git a/support/support-xstat.c b/support/support-xstat.c -new file mode 100644 -index 0000000000..86a81ec601 ---- /dev/null -+++ b/support/support-xstat.c -@@ -0,0 +1,30 @@ -+/* stat64 with error checking. -+ 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 -+ . */ -+ -+/* NB: Non-standard file name to avoid sysdeps override for xstat. */ -+ -+#include -+#include -+#include -+ -+void -+xstat (const char *path, struct stat64 *result) -+{ -+ if (stat64 (path, result) != 0) -+ FAIL_EXIT1 ("stat64 (\"%s\"): %m", path); -+} -diff --git a/support/support.h b/support/support.h -index 7292e2a564..4b5f04c2cc 100644 ---- a/support/support.h -+++ b/support/support.h -@@ -44,6 +44,21 @@ void set_fortify_handler (void (*handler) (int sig)); - void oom_error (const char *function, size_t size) - __attribute__ ((nonnull (1))); - -+/* Return a pointer to a memory region of SIZE bytes. The memory is -+ initialized to zero and will be shared with subprocesses (across -+ fork). The returned pointer must be freed using -+ support_shared_free; it is not compatible with the malloc -+ functions. */ -+void *support_shared_allocate (size_t size); -+ -+/* Deallocate a pointer returned by support_shared_allocate. */ -+void support_shared_free (void *); -+ -+/* Write CONTENTS to the file PATH. Create or truncate the file as -+ needed. The file mode is 0666 masked by the umask. Terminate the -+ process on error. */ -+void support_write_file_string (const char *path, const char *contents); -+ - /* Error-checking wrapper functions which terminate the process on - error. */ - -diff --git a/support/support_can_chroot.c b/support/support_can_chroot.c -new file mode 100644 -index 0000000000..0dfd2deb54 ---- /dev/null -+++ b/support/support_can_chroot.c -@@ -0,0 +1,65 @@ -+/* Return true if the process can perform a chroot operation. -+ 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 -+ . */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+static void -+callback (void *closure) -+{ -+ int *result = closure; -+ struct stat64 before; -+ xstat ("/dev", &before); -+ if (chroot ("/dev") != 0) -+ { -+ *result = errno; -+ return; -+ } -+ struct stat64 after; -+ xstat ("/", &after); -+ TEST_VERIFY (before.st_dev == after.st_dev); -+ TEST_VERIFY (before.st_ino == after.st_ino); -+ *result = 0; -+} -+ -+bool -+support_can_chroot (void) -+{ -+ int *result = support_shared_allocate (sizeof (*result)); -+ *result = 0; -+ support_isolate_in_subprocess (callback, result); -+ bool ok = *result == 0; -+ if (!ok) -+ { -+ static bool already_warned; -+ if (!already_warned) -+ { -+ already_warned = true; -+ errno = *result; -+ printf ("warning: this process does not support chroot: %m\n"); -+ } -+ } -+ support_shared_free (result); -+ return ok; -+} -diff --git a/support/support_capture_subprocess.c b/support/support_capture_subprocess.c -new file mode 100644 -index 0000000000..030f124252 ---- /dev/null -+++ b/support/support_capture_subprocess.c -@@ -0,0 +1,108 @@ -+/* Capture output from a subprocess. -+ 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 -+ . */ -+ -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+static void -+transfer (const char *what, struct pollfd *pfd, struct xmemstream *stream) -+{ -+ if (pfd->revents != 0) -+ { -+ char buf[1024]; -+ ssize_t ret = TEMP_FAILURE_RETRY (read (pfd->fd, buf, sizeof (buf))); -+ if (ret < 0) -+ { -+ support_record_failure (); -+ printf ("error: reading from subprocess %s: %m", what); -+ pfd->events = 0; -+ pfd->revents = 0; -+ } -+ else if (ret == 0) -+ { -+ /* EOF reached. Stop listening. */ -+ pfd->events = 0; -+ pfd->revents = 0; -+ } -+ else -+ /* Store the data just read. */ -+ TEST_VERIFY (fwrite (buf, ret, 1, stream->out) == 1); -+ } -+} -+ -+struct support_capture_subprocess -+support_capture_subprocess (void (*callback) (void *), void *closure) -+{ -+ struct support_capture_subprocess result; -+ xopen_memstream (&result.out); -+ xopen_memstream (&result.err); -+ -+ int stdout_pipe[2]; -+ xpipe (stdout_pipe); -+ int stderr_pipe[2]; -+ xpipe (stderr_pipe); -+ -+ TEST_VERIFY (fflush (stdout) == 0); -+ TEST_VERIFY (fflush (stderr) == 0); -+ -+ pid_t pid = xfork (); -+ if (pid == 0) -+ { -+ xclose (stdout_pipe[0]); -+ xclose (stderr_pipe[0]); -+ xdup2 (stdout_pipe[1], STDOUT_FILENO); -+ xdup2 (stderr_pipe[1], STDERR_FILENO); -+ callback (closure); -+ _exit (0); -+ } -+ xclose (stdout_pipe[1]); -+ xclose (stderr_pipe[1]); -+ -+ struct pollfd fds[2] = -+ { -+ { .fd = stdout_pipe[0], .events = POLLIN }, -+ { .fd = stderr_pipe[0], .events = POLLIN }, -+ }; -+ -+ do -+ { -+ xpoll (fds, 2, -1); -+ transfer ("stdout", &fds[0], &result.out); -+ transfer ("stderr", &fds[1], &result.err); -+ } -+ while (fds[0].events != 0 || fds[1].events != 0); -+ xclose (stdout_pipe[0]); -+ xclose (stderr_pipe[0]); -+ -+ xfclose_memstream (&result.out); -+ xfclose_memstream (&result.err); -+ xwaitpid (pid, &result.status, 0); -+ return result; -+} -+ -+void -+support_capture_subprocess_free (struct support_capture_subprocess *p) -+{ -+ free (p->out.buffer); -+ free (p->err.buffer); -+} -diff --git a/support/support_capture_subprocess_check.c b/support/support_capture_subprocess_check.c -new file mode 100644 -index 0000000000..e1cf73b6a5 ---- /dev/null -+++ b/support/support_capture_subprocess_check.c -@@ -0,0 +1,67 @@ -+/* Verify capture output from a subprocess. -+ 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 -+ . */ -+ -+#include -+#include -+#include -+#include -+ -+static void -+print_context (const char *context, bool *failed) -+{ -+ if (*failed) -+ /* Do not duplicate message. */ -+ return; -+ support_record_failure (); -+ printf ("error: subprocess failed: %s\n", context); -+} -+ -+void -+support_capture_subprocess_check (struct support_capture_subprocess *proc, -+ const char *context, int status, -+ int allowed) -+{ -+ TEST_VERIFY ((allowed & sc_allow_none) -+ || (allowed & sc_allow_stdout) -+ || (allowed & sc_allow_stderr)); -+ TEST_VERIFY (!((allowed & sc_allow_none) -+ && ((allowed & sc_allow_stdout) -+ || (allowed & sc_allow_stderr)))); -+ -+ bool failed = false; -+ if (proc->status != status) -+ { -+ print_context (context, &failed); -+ printf ("error: expected exit status: %d\n", status); -+ printf ("error: actual exit status: %d\n", proc->status); -+ } -+ if (!(allowed & sc_allow_stdout) && proc->out.length != 0) -+ { -+ print_context (context, &failed); -+ printf ("error: unexpected output from subprocess\n"); -+ fwrite (proc->out.buffer, proc->out.length, 1, stdout); -+ puts ("\n"); -+ } -+ if (!(allowed & sc_allow_stderr) && proc->err.length != 0) -+ { -+ print_context (context, &failed); -+ printf ("error: unexpected error output from subprocess\n"); -+ fwrite (proc->err.buffer, proc->err.length, 1, stdout); -+ puts ("\n"); -+ } -+} -diff --git a/support/support_chroot.c b/support/support_chroot.c -new file mode 100644 -index 0000000000..f3ef551b05 ---- /dev/null -+++ b/support/support_chroot.c -@@ -0,0 +1,85 @@ -+/* Setup a chroot environment for use within tests. -+ 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 -+ . */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/* If CONTENTS is not NULL, write it to the file at DIRECTORY/RELPATH, -+ and store the name in *ABSPATH. If CONTENTS is NULL, store NULL in -+ *ABSPATH. */ -+static void -+write_file (const char *directory, const char *relpath, const char *contents, -+ char **abspath) -+{ -+ if (contents != NULL) -+ { -+ *abspath = xasprintf ("%s/%s", directory, relpath); -+ add_temp_file (*abspath); -+ support_write_file_string (*abspath, contents); -+ } -+ else -+ *abspath = NULL; -+} -+ -+struct support_chroot * -+support_chroot_create (struct support_chroot_configuration conf) -+{ -+ struct support_chroot *chroot = xmalloc (sizeof (*chroot)); -+ -+ chroot->path_chroot = xasprintf ("%s/tst-resolv-res_init-XXXXXX", test_dir); -+ if (mkdtemp (chroot->path_chroot) == NULL) -+ FAIL_EXIT1 ("mkdtemp (\"%s\"): %m", chroot->path_chroot); -+ add_temp_file (chroot->path_chroot); -+ -+ /* Create the /etc directory in the chroot environment. */ -+ char *path_etc = xasprintf ("%s/etc", chroot->path_chroot); -+ xmkdir (path_etc, 0777); -+ add_temp_file (path_etc); -+ -+ write_file (path_etc, "resolv.conf", conf.resolv_conf, -+ &chroot->path_resolv_conf); -+ write_file (path_etc, "hosts", conf.hosts, &chroot->path_hosts); -+ write_file (path_etc, "host.conf", conf.host_conf, &chroot->path_host_conf); -+ -+ free (path_etc); -+ -+ /* valgrind needs a temporary directory in the chroot. */ -+ { -+ char *path_tmp = xasprintf ("%s/tmp", chroot->path_chroot); -+ xmkdir (path_tmp, 0777); -+ add_temp_file (path_tmp); -+ free (path_tmp); -+ } -+ -+ return chroot; -+} -+ -+void -+support_chroot_free (struct support_chroot *chroot) -+{ -+ free (chroot->path_chroot); -+ free (chroot->path_resolv_conf); -+ free (chroot->path_hosts); -+ free (chroot->path_host_conf); -+ free (chroot); -+} -diff --git a/support/support_enter_network_namespace.c b/support/support_enter_network_namespace.c -index d2e78fe560..28b0ee29cf 100644 ---- a/support/support_enter_network_namespace.c -+++ b/support/support_enter_network_namespace.c -@@ -23,9 +23,10 @@ - #include - #include - #include -+#include -+#include - #include - #include --#include - - static bool in_uts_namespace; - -@@ -58,7 +59,7 @@ support_enter_network_namespace (void) - req.ifr_flags |= IFF_UP | IFF_RUNNING; - TEST_VERIFY_EXIT (ioctl (fd, SIOCSIFFLAGS, &req) == 0); - } -- close (fd); -+ xclose (fd); - - return !already_up; - } -diff --git a/support/support_format_addrinfo.c b/support/support_format_addrinfo.c -index 262e0df737..eedb030591 100644 ---- a/support/support_format_addrinfo.c -+++ b/support/support_format_addrinfo.c -@@ -39,8 +39,8 @@ socket_address_length (int family) - } - - static void --format_ai_flags (FILE *out, struct addrinfo *ai, int flag, const char *name, -- int * flags_printed) -+format_ai_flags_1 (FILE *out, struct addrinfo *ai, int flag, const char *name, -+ int * flags_printed) - { - if ((ai->ai_flags & flag) != 0) - fprintf (out, " %s", name); -@@ -48,14 +48,16 @@ format_ai_flags (FILE *out, struct addrinfo *ai, int flag, const char *name, - } - - static void --format_ai_one (FILE *out, struct addrinfo *ai, int *flags) -+format_ai_flags (FILE *out, struct addrinfo *ai) - { -- /* ai_flags */ -- if (ai->ai_flags != *flags) -+ if (ai == NULL) -+ return; -+ -+ if (ai->ai_flags != 0) - { - fprintf (out, "flags:"); - int flags_printed = 0; --#define FLAG(flag) format_ai_flags (out, ai, flag, #flag, &flags_printed) -+#define FLAG(flag) format_ai_flags_1 (out, ai, flag, #flag, &flags_printed) - FLAG (AI_PASSIVE); - FLAG (AI_CANONNAME); - FLAG (AI_NUMERICHOST); -@@ -72,9 +74,47 @@ format_ai_one (FILE *out, struct addrinfo *ai, int *flags) - if (remaining != 0) - fprintf (out, " %08x", remaining); - fprintf (out, "\n"); -- *flags = ai->ai_flags; - } - -+ /* Report flag mismatches within the list. */ -+ int flags = ai->ai_flags; -+ int index = 1; -+ ai = ai->ai_next; -+ while (ai != NULL) -+ { -+ if (ai->ai_flags != flags) -+ fprintf (out, "error: flags at %d: 0x%x expected, 0x%x actual\n", -+ index, flags, ai->ai_flags); -+ ai = ai->ai_next; -+ ++index; -+ } -+} -+ -+static void -+format_ai_canonname (FILE *out, struct addrinfo *ai) -+{ -+ if (ai == NULL) -+ return; -+ if (ai->ai_canonname != NULL) -+ fprintf (out, "canonname: %s\n", ai->ai_canonname); -+ -+ /* Report incorrectly set ai_canonname fields on subsequent list -+ entries. */ -+ int index = 1; -+ ai = ai->ai_next; -+ while (ai != NULL) -+ { -+ if (ai->ai_canonname != NULL) -+ fprintf (out, "error: canonname set at %d: %s\n", -+ index, ai->ai_canonname); -+ ai = ai->ai_next; -+ ++index; -+ } -+} -+ -+static void -+format_ai_one (FILE *out, struct addrinfo *ai) -+{ - { - char type_buf[32]; - const char *type_str; -@@ -156,20 +196,16 @@ format_ai_one (FILE *out, struct addrinfo *ai, int *flags) - else - fprintf (out, " %s %u\n", buf, ntohs (port)); - } -- -- /* ai_canonname */ -- if (ai->ai_canonname != NULL) -- fprintf (out, "canonname: %s\n", ai->ai_canonname); - } - - /* Format all the addresses in one address family. */ - static void --format_ai_family (FILE *out, struct addrinfo *ai, int family, int *flags) -+format_ai_family (FILE *out, struct addrinfo *ai, int family) - { - while (ai) - { - if (ai->ai_family == family) -- format_ai_one (out, ai, flags); -+ format_ai_one (out, ai); - ai = ai->ai_next; - } - } -@@ -192,9 +228,10 @@ support_format_addrinfo (struct addrinfo *ai, int ret) - } - else - { -- int flags = 0; -- format_ai_family (mem.out, ai, AF_INET, &flags); -- format_ai_family (mem.out, ai, AF_INET6, &flags); -+ format_ai_flags (mem.out, ai); -+ format_ai_canonname (mem.out, ai); -+ format_ai_family (mem.out, ai, AF_INET); -+ format_ai_family (mem.out, ai, AF_INET6); - } - - xfclose_memstream (&mem); -diff --git a/support/support_format_dns_packet.c b/support/support_format_dns_packet.c -index 21fe7e5c8d..2992c57971 100644 ---- a/support/support_format_dns_packet.c -+++ b/support/support_format_dns_packet.c -@@ -174,7 +174,7 @@ support_format_dns_packet (const unsigned char *buffer, size_t length) - goto out; - } - /* Skip non-matching record types. */ -- if (rtype != qtype || rclass != qclass) -+ if ((rtype != qtype && rtype != T_CNAME) || rclass != qclass) - continue; - switch (rtype) - { -@@ -186,22 +186,29 @@ support_format_dns_packet (const unsigned char *buffer, size_t length) - rdata.data[2], - rdata.data[3]); - else -- fprintf (mem.out, "error: A record of size %d: %s\n", rdlen, rname.name); -+ fprintf (mem.out, "error: A record of size %d: %s\n", -+ rdlen, rname.name); - break; - case T_AAAA: - { -- char buf[100]; -- if (inet_ntop (AF_INET6, rdata.data, buf, sizeof (buf)) == NULL) -- fprintf (mem.out, "error: AAAA record decoding failed: %m\n"); -+ if (rdlen == 16) -+ { -+ char buf[100]; -+ if (inet_ntop (AF_INET6, rdata.data, buf, sizeof (buf)) == NULL) -+ fprintf (mem.out, "error: AAAA record decoding failed: %m\n"); -+ else -+ fprintf (mem.out, "address: %s\n", buf); -+ } - else -- fprintf (mem.out, "address: %s\n", buf); -+ fprintf (mem.out, "error: AAAA record of size %d: %s\n", -+ rdlen, rname.name); - } - break; - case T_CNAME: - case T_PTR: - { - struct dname name; -- if (extract_name (full, &in, &name)) -+ if (extract_name (full, &rdata, &name)) - fprintf (mem.out, "name: %s\n", name.name); - else - fprintf (mem.out, "error: malformed CNAME/PTR record\n"); -diff --git a/support/support_format_hostent.c b/support/support_format_hostent.c -index 5b5f26082e..88c85ec1f1 100644 ---- a/support/support_format_hostent.c -+++ b/support/support_format_hostent.c -@@ -19,6 +19,7 @@ - #include - - #include -+#include - #include - #include - #include -@@ -41,10 +42,15 @@ support_format_hostent (struct hostent *h) - { - if (h == NULL) - { -- char *value = support_format_herrno (h_errno); -- char *result = xasprintf ("error: %s\n", value); -- free (value); -- return result; -+ if (h_errno == NETDB_INTERNAL) -+ return xasprintf ("error: NETDB_INTERNAL (errno %d, %m)\n", errno); -+ else -+ { -+ char *value = support_format_herrno (h_errno); -+ char *result = xasprintf ("error: %s\n", value); -+ free (value); -+ return result; -+ } - } - - struct xmemstream mem; -diff --git a/support/support_isolate_in_subprocess.c b/support/support_isolate_in_subprocess.c -new file mode 100644 -index 0000000000..cf48614383 ---- /dev/null -+++ b/support/support_isolate_in_subprocess.c -@@ -0,0 +1,38 @@ -+/* Run a function in a subprocess. -+ 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 -+ . */ -+ -+#include -+#include -+ -+void -+support_isolate_in_subprocess (void (*callback) (void *), void *closure) -+{ -+ pid_t pid = xfork (); -+ if (pid == 0) -+ { -+ /* Child process. */ -+ callback (closure); -+ _exit (0); -+ } -+ -+ /* Parent process. */ -+ int status; -+ xwaitpid (pid, &status, 0); -+ if (status != 0) -+ FAIL_EXIT1 ("child process exited with status %d", status); -+} -diff --git a/support/support_run_diff.c b/support/support_run_diff.c -index 3085037a69..f5155de727 100644 ---- a/support/support_run_diff.c -+++ b/support/support_run_diff.c -@@ -24,8 +24,8 @@ - #include - #include - #include -+#include - #include --#include - - static char * - write_to_temp_file (const char *prefix, const char *str) -@@ -36,7 +36,7 @@ write_to_temp_file (const char *prefix, const char *str) - TEST_VERIFY_EXIT (fd >= 0); - free (template); - xwrite (fd, str, strlen (str)); -- TEST_VERIFY_EXIT (close (fd) == 0); -+ xclose (fd); - return name; - } - -diff --git a/support/support_shared_allocate.c b/support/support_shared_allocate.c -new file mode 100644 -index 0000000000..61d088e8cf ---- /dev/null -+++ b/support/support_shared_allocate.c -@@ -0,0 +1,57 @@ -+/* Allocate a memory region shared across processes. -+ 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 -+ . */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+/* Header for the allocation. It contains the size of the allocation -+ for subsequent unmapping. */ -+struct header -+{ -+ size_t total_size; -+ char data[] __attribute__ ((aligned (__alignof__ (max_align_t)))); -+}; -+ -+void * -+support_shared_allocate (size_t size) -+{ -+ size_t total_size = size + offsetof (struct header, data); -+ if (total_size < size) -+ { -+ errno = ENOMEM; -+ oom_error (__func__, size); -+ return NULL; -+ } -+ else -+ { -+ struct header *result = xmmap (NULL, total_size, PROT_READ | PROT_WRITE, -+ MAP_ANONYMOUS | MAP_SHARED, -1); -+ result->total_size = total_size; -+ return &result->data; -+ } -+} -+ -+void -+support_shared_free (void *data) -+{ -+ struct header *header = data - offsetof (struct header, data); -+ xmunmap (header, header->total_size); -+} -diff --git a/support/support_test_main.c b/support/support_test_main.c -index 914d64f603..3c411a467b 100644 ---- a/support/support_test_main.c -+++ b/support/support_test_main.c -@@ -211,7 +211,8 @@ support_test_main (int argc, char **argv, const struct test_config *config) - mallopt (M_PERTURB, 42); - } - -- while ((opt = getopt_long (argc, argv, "+", options, NULL)) != -1) -+ while ((opt = getopt_long (argc, argv, config->optstring, options, NULL)) -+ != -1) - switch (opt) - { - case '?': -diff --git a/support/support_test_verify_impl.c b/support/support_test_verify_impl.c -index 5bae38f8b1..55ab2111b3 100644 ---- a/support/support_test_verify_impl.c -+++ b/support/support_test_verify_impl.c -@@ -22,12 +22,16 @@ - #include - - void --support_test_verify_impl (int status, const char *file, int line, -- const char *expr) -+support_test_verify_impl (const char *file, int line, const char *expr) - { - support_record_failure (); - printf ("error: %s:%d: not true: %s\n", file, line, expr); -- if (status >= 0) -- exit (status); -+} - -+void -+support_test_verify_exit_impl (int status, const char *file, int line, -+ const char *expr) -+{ -+ support_test_verify_impl (file, line, expr); -+ exit (status); - } -diff --git a/support/support_write_file_string.c b/support/support_write_file_string.c -new file mode 100644 -index 0000000000..48e89597f3 ---- /dev/null -+++ b/support/support_write_file_string.c -@@ -0,0 +1,39 @@ -+/* Write a string to a file. -+ 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 -+ . */ -+ -+#include -+#include -+#include -+#include -+ -+void -+support_write_file_string (const char *path, const char *contents) -+{ -+ int fd = xopen (path, O_CREAT | O_TRUNC | O_WRONLY, 0666); -+ const char *end = contents + strlen (contents); -+ for (const char *p = contents; p < end; ) -+ { -+ ssize_t ret = write (fd, p, end - p); -+ if (ret < 0) -+ FAIL_EXIT1 ("cannot write to \"%s\": %m", path); -+ if (ret == 0) -+ FAIL_EXIT1 ("zero-length write to \"%s\"", path); -+ p += ret; -+ } -+ xclose (fd); -+} -diff --git a/support/temp_file.c b/support/temp_file.c -index f06647a467..fdb2477ab9 100644 ---- a/support/temp_file.c -+++ b/support/temp_file.c -@@ -25,16 +25,17 @@ - #include - - #include --#include - #include - #include - #include -+#include - - /* List of temporary files. */ - static struct temp_name_list - { -- struct qelem q; -+ struct temp_name_list *next; - char *name; -+ pid_t owner; - } *temp_name_list; - - /* Location of the temporary files. Set by the test skeleton via -@@ -50,10 +51,9 @@ add_temp_file (const char *name) - if (newname != NULL) - { - newp->name = newname; -- if (temp_name_list == NULL) -- temp_name_list = (struct temp_name_list *) &newp->q; -- else -- insque (newp, temp_name_list); -+ newp->next = temp_name_list; -+ newp->owner = getpid (); -+ temp_name_list = newp; - } - else - free (newp); -@@ -97,13 +97,22 @@ support_set_test_dir (const char *path) - void - support_delete_temp_files (void) - { -+ pid_t pid = getpid (); - while (temp_name_list != NULL) - { -- remove (temp_name_list->name); -+ /* Only perform the removal if the path was registed in the same -+ process, as identified by the PID. (This assumes that the -+ parent process which registered the temporary file sticks -+ around, to prevent PID reuse.) */ -+ if (temp_name_list->owner == pid) -+ { -+ if (remove (temp_name_list->name) != 0) -+ printf ("warning: could not remove temporary file: %s: %m\n", -+ temp_name_list->name); -+ } - free (temp_name_list->name); - -- struct temp_name_list *next -- = (struct temp_name_list *) temp_name_list->q.q_forw; -+ struct temp_name_list *next = temp_name_list->next; - free (temp_name_list); - temp_name_list = next; - } -@@ -116,9 +125,7 @@ support_print_temp_files (FILE *f) - { - struct temp_name_list *n; - fprintf (f, "temp_files=(\n"); -- for (n = temp_name_list; -- n != NULL; -- n = (struct temp_name_list *) n->q.q_forw) -+ for (n = temp_name_list; n != NULL; n = n->next) - fprintf (f, " '%s'\n", n->name); - fprintf (f, ")\n"); - } -diff --git a/support/test-driver.c b/support/test-driver.c -index 482066dbeb..47c387c2b4 100644 ---- a/support/test-driver.c -+++ b/support/test-driver.c -@@ -93,6 +93,10 @@ - has this type: - - void CMDLINE_PROCESS (int); -+ -+ If the program also to process custom default short command line -+ argument (similar to getopt) it must define CMDLINE_OPTSTRING -+ with the expected options (for instance "vb"). - */ - - #include -@@ -151,6 +155,11 @@ main (int argc, char **argv) - #ifdef CMDLINE_PROCESS - test_config.cmdline_function = CMDLINE_PROCESS; - #endif -+#ifdef CMDLINE_OPTSTRING -+ test_config.optstring = "+" CMDLINE_OPTSTRING; -+#else -+ test_config.optstring = "+"; -+#endif - - return support_test_main (argc, argv, &test_config); - } -diff --git a/support/test-driver.h b/support/test-driver.h -index af1971a9ca..a8fe9c3565 100644 ---- a/support/test-driver.h -+++ b/support/test-driver.h -@@ -35,6 +35,7 @@ struct test_config - int expected_status; /* Expected exit status. */ - int expected_signal; /* If non-zero, expect termination by signal. */ - char no_mallopt; /* Boolean flag to disable mallopt. */ -+ const char *optstring; /* Short command line options. */ - }; - - enum -diff --git a/support/tst-support-namespace.c b/support/tst-support-namespace.c -index a50b074f5e..dbe7cc07c8 100644 ---- a/support/tst-support-namespace.c -+++ b/support/tst-support-namespace.c -@@ -16,18 +16,98 @@ - License along with the GNU C Library; if not, see - . */ - -+#include -+#include - #include -+#include - #include -+#include -+#include -+ -+/* Check that the loopback interface provides multiple addresses which -+ can be used to run independent servers. */ -+static void -+test_localhost_bind (void) -+{ -+ printf ("info: testing loopback interface with multiple addresses\n"); -+ -+ /* Create the two server addresses. */ -+ static const struct addrinfo hints = -+ { -+ .ai_family = AF_INET, -+ .ai_socktype = SOCK_DGRAM, -+ .ai_protocol = IPPROTO_UDP, -+ }; -+ struct addrinfo *ai[3]; -+ TEST_VERIFY_EXIT (getaddrinfo ("127.0.0.1", "53", &hints, ai + 0) == 0); -+ TEST_VERIFY_EXIT (getaddrinfo ("127.0.0.2", "53", &hints, ai + 1) == 0); -+ TEST_VERIFY_EXIT (getaddrinfo ("127.0.0.3", "53", &hints, ai + 2) == 0); -+ -+ /* Create the server scokets and bind them to these addresses. */ -+ int sockets[3]; -+ for (int i = 0; i < 3; ++i) -+ { -+ sockets[i] = xsocket -+ (ai[i]->ai_family, ai[i]->ai_socktype, ai[i]->ai_protocol); -+ xbind (sockets[i], ai[i]->ai_addr, ai[i]->ai_addrlen); -+ } -+ -+ /* Send two packets to each server. */ -+ int client = xsocket (AF_INET, SOCK_DGRAM, IPPROTO_UDP); -+ for (int i = 0; i < 3; ++i) -+ { -+ TEST_VERIFY (sendto (client, &i, sizeof (i), 0, -+ ai[i]->ai_addr, ai[i]->ai_addrlen) == sizeof (i)); -+ int j = i + 256; -+ TEST_VERIFY (sendto (client, &j, sizeof (j), 0, -+ ai[i]->ai_addr, ai[i]->ai_addrlen) == sizeof (j)); -+ } -+ -+ /* Check that the packets can be received with the expected -+ contents. Note that the receive calls interleave differently, -+ which hopefully proves that the sockets are, indeed, -+ independent. */ -+ for (int i = 0; i < 3; ++i) -+ { -+ int buf; -+ TEST_VERIFY (recv (sockets[i], &buf, sizeof (buf), 0) == sizeof (buf)); -+ TEST_VERIFY (buf == i); -+ } -+ for (int i = 0; i < 3; ++i) -+ { -+ int buf; -+ TEST_VERIFY (recv (sockets[i], &buf, sizeof (buf), 0) == sizeof (buf)); -+ TEST_VERIFY (buf == i + 256); -+ /* Check that there is no more data to receive. */ -+ TEST_VERIFY (recv (sockets[i], &buf, sizeof (buf), MSG_DONTWAIT) == -1); -+ TEST_VERIFY (errno == EWOULDBLOCK || errno == EAGAIN); -+ } -+ -+ /* Close all sockets and free the addresses. */ -+ for (int i = 0; i < 3; ++i) -+ { -+ freeaddrinfo (ai[i]); -+ xclose (sockets[i]); -+ } -+ xclose (client); -+} -+ - - static int - do_test (void) - { -- if (support_become_root ()) -+ bool root = support_become_root (); -+ if (root) - printf ("info: acquired root-like privileges\n"); -- if (support_enter_network_namespace ()) -+ bool netns = support_enter_network_namespace (); -+ if (netns) - printf ("info: entered network namespace\n"); - if (support_in_uts_namespace ()) - printf ("info: also entered UTS namespace\n"); -+ -+ if (root && netns) -+ test_localhost_bind (); -+ - return 0; - } - -diff --git a/support/tst-support_capture_subprocess.c b/support/tst-support_capture_subprocess.c -new file mode 100644 -index 0000000000..5672fba0f7 ---- /dev/null -+++ b/support/tst-support_capture_subprocess.c -@@ -0,0 +1,188 @@ -+/* Test capturing output from a subprocess. -+ 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 -+ . */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/* Write one byte at *P to FD and advance *P. Do nothing if *P is -+ '\0'. */ -+static void -+transfer (const unsigned char **p, int fd) -+{ -+ if (**p != '\0') -+ { -+ TEST_VERIFY (write (fd, *p, 1) == 1); -+ ++*p; -+ } -+} -+ -+/* Determine the order in which stdout and stderr are written. */ -+enum write_mode { out_first, err_first, interleave, -+ write_mode_last = interleave }; -+ -+/* Describe what to write in the subprocess. */ -+struct test -+{ -+ char *out; -+ char *err; -+ enum write_mode write_mode; -+ int signal; -+ int status; -+}; -+ -+/* For use with support_capture_subprocess. */ -+static void -+callback (void *closure) -+{ -+ const struct test *test = closure; -+ bool mode_ok = false; -+ switch (test->write_mode) -+ { -+ case out_first: -+ TEST_VERIFY (fputs (test->out, stdout) >= 0); -+ TEST_VERIFY (fflush (stdout) == 0); -+ TEST_VERIFY (fputs (test->err, stderr) >= 0); -+ TEST_VERIFY (fflush (stderr) == 0); -+ mode_ok = true; -+ break; -+ case err_first: -+ TEST_VERIFY (fputs (test->err, stderr) >= 0); -+ TEST_VERIFY (fflush (stderr) == 0); -+ TEST_VERIFY (fputs (test->out, stdout) >= 0); -+ TEST_VERIFY (fflush (stdout) == 0); -+ mode_ok = true; -+ break; -+ case interleave: -+ { -+ const unsigned char *pout = (const unsigned char *) test->out; -+ const unsigned char *perr = (const unsigned char *) test->err; -+ do -+ { -+ transfer (&pout, STDOUT_FILENO); -+ transfer (&perr, STDERR_FILENO); -+ } -+ while (*pout != '\0' || *perr != '\0'); -+ } -+ mode_ok = true; -+ break; -+ } -+ TEST_VERIFY (mode_ok); -+ -+ if (test->signal != 0) -+ raise (test->signal); -+ exit (test->status); -+} -+ -+/* Create a heap-allocated random string of letters. */ -+static char * -+random_string (size_t length) -+{ -+ char *result = xmalloc (length + 1); -+ for (size_t i = 0; i < length; ++i) -+ result[i] = 'a' + (rand () % 26); -+ result[length] = '\0'; -+ return result; -+} -+ -+/* Check that the specific stream from the captured subprocess matches -+ expectations. */ -+static void -+check_stream (const char *what, const struct xmemstream *stream, -+ const char *expected) -+{ -+ if (strcmp (stream->buffer, expected) != 0) -+ { -+ support_record_failure (); -+ printf ("error: captured %s data incorrect\n" -+ " expected: %s\n" -+ " actual: %s\n", -+ what, expected, stream->buffer); -+ } -+ if (stream->length != strlen (expected)) -+ { -+ support_record_failure (); -+ printf ("error: captured %s data length incorrect\n" -+ " expected: %zu\n" -+ " actual: %zu\n", -+ what, strlen (expected), stream->length); -+ } -+} -+ -+static int -+do_test (void) -+{ -+ const int lengths[] = {0, 1, 17, 512, 20000, -1}; -+ -+ /* Test multiple combinations of support_capture_subprocess. -+ -+ length_idx_stdout: Index into the lengths array above, -+ controls how many bytes are written by the subprocess to -+ standard output. -+ length_idx_stderr: Same for standard error. -+ write_mode: How standard output and standard error writes are -+ ordered. -+ signal: Exit with no signal if zero, with SIGTERM if one. -+ status: Process exit status: 0 if zero, 3 if one. */ -+ for (int length_idx_stdout = 0; lengths[length_idx_stdout] >= 0; -+ ++length_idx_stdout) -+ for (int length_idx_stderr = 0; lengths[length_idx_stderr] >= 0; -+ ++length_idx_stderr) -+ for (int write_mode = 0; write_mode < write_mode_last; ++write_mode) -+ for (int signal = 0; signal < 2; ++signal) -+ for (int status = 0; status < 2; ++status) -+ { -+ struct test test = -+ { -+ .out = random_string (lengths[length_idx_stdout]), -+ .err = random_string (lengths[length_idx_stderr]), -+ .write_mode = write_mode, -+ .signal = signal * SIGTERM, /* 0 or SIGTERM. */ -+ .status = status * 3, /* 0 or 3. */ -+ }; -+ TEST_VERIFY (strlen (test.out) == lengths[length_idx_stdout]); -+ TEST_VERIFY (strlen (test.err) == lengths[length_idx_stderr]); -+ -+ struct support_capture_subprocess result -+ = support_capture_subprocess (callback, &test); -+ check_stream ("stdout", &result.out, test.out); -+ check_stream ("stderr", &result.err, test.err); -+ if (test.signal != 0) -+ { -+ TEST_VERIFY (WIFSIGNALED (result.status)); -+ TEST_VERIFY (WTERMSIG (result.status) == test.signal); -+ } -+ else -+ { -+ TEST_VERIFY (WIFEXITED (result.status)); -+ TEST_VERIFY (WEXITSTATUS (result.status) == test.status); -+ } -+ support_capture_subprocess_free (&result); -+ free (test.out); -+ free (test.err); -+ } -+ return 0; -+} -+ -+#include -diff --git a/support/tst-support_format_dns_packet.c b/support/tst-support_format_dns_packet.c -new file mode 100644 -index 0000000000..9c8589c09c ---- /dev/null -+++ b/support/tst-support_format_dns_packet.c -@@ -0,0 +1,101 @@ -+/* Tests for the support_format_dns_packet function. -+ Copyright (C) 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 -+ . */ -+ -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+static void -+check_packet (const void *buffer, size_t length, -+ const char *name, const char *expected) -+{ -+ char *actual = support_format_dns_packet (buffer, length); -+ if (strcmp (actual, expected) != 0) -+ { -+ support_record_failure (); -+ printf ("error: formatted packet does not match: %s\n", name); -+ support_run_diff ("expected", expected, -+ "actual", actual); -+ } -+ free (actual); -+} -+ -+static void -+test_aaaa_length (void) -+{ -+ static const char packet[] = -+ /* Header: Response with two records. */ -+ "\x12\x34\x80\x00\x00\x01\x00\x02\x00\x00\x00\x00" -+ /* Question section. www.example/IN/AAAA. */ -+ "\x03www\x07""example\x00\x00\x1c\x00\x01" -+ /* Answer section. www.example AAAA [corrupted]. */ -+ "\xc0\x0c" -+ "\x00\x1c\x00\x01\x00\x00\x00\x00\x00\x10" -+ "\x20\x01\x0d\xb8\x05\x06\x07\x08" -+ "\x11\x12\x13\x14\x15\x16\x17\x18" -+ /* www.example AAAA [corrupted]. */ -+ "\xc0\x0c" -+ "\x00\x1c\x00\x01\x00\x00\x00\x00\x00\x11" -+ "\x01\x02\x03\x04\x05\x06\x07\x08" -+ "\x11\x12\x13\x14\x15\x16\x17\x18" "\xff"; -+ check_packet (packet, sizeof (packet) - 1, __func__, -+ "name: www.example\n" -+ "address: 2001:db8:506:708:1112:1314:1516:1718\n" -+ "error: AAAA record of size 17: www.example\n"); -+} -+ -+static void -+test_multiple_cnames (void) -+{ -+ static const char packet[] = -+ /* Header: Response with three records. */ -+ "\x12\x34\x80\x00\x00\x01\x00\x03\x00\x00\x00\x00" -+ /* Question section. www.example/IN/A. */ -+ "\x03www\x07""example\x00\x00\x01\x00\x01" -+ /* Answer section. www.example CNAME www1.example. */ -+ "\xc0\x0c" -+ "\x00\x05\x00\x01\x00\x00\x00\x00\x00\x07" -+ "\x04www1\xc0\x10" -+ /* www1 CNAME www2. */ -+ "\x04www1\xc0\x10" -+ "\x00\x05\x00\x01\x00\x00\x00\x00\x00\x07" -+ "\x04www2\xc0\x10" -+ /* www2 A 192.0.2.1. */ -+ "\x04www2\xc0\x10" -+ "\x00\x01\x00\x01\x00\x00\x00\x00\x00\x04" -+ "\xc0\x00\x02\x01"; -+ check_packet (packet, sizeof (packet) - 1, __func__, -+ "name: www.example\n" -+ "name: www1.example\n" -+ "name: www2.example\n" -+ "address: 192.0.2.1\n"); -+} -+ -+static int -+do_test (void) -+{ -+ test_aaaa_length (); -+ test_multiple_cnames (); -+ return 0; -+} -+ -+#include -diff --git a/support/tst-support_record_failure-2.sh b/support/tst-support_record_failure-2.sh -index 175137780a..2c9372cc29 100644 ---- a/support/tst-support_record_failure-2.sh -+++ b/support/tst-support_record_failure-2.sh -@@ -37,7 +37,7 @@ run_test () { - set -e - echo " exit status: $status" - if test "$output" != "$expected_output" ; then -- echo "error: unexpected ouput: $output" -+ echo "error: unexpected output: $output" - exit 1 - fi - if test "$status" -ne "$expected_status" ; then -@@ -52,9 +52,9 @@ different_status () { - run_test 1 "error: 1 test failures" $direct --status=1 - run_test 2 "error: 1 test failures" $direct --status=2 - run_test 1 "error: 1 test failures" $direct --status=77 -- run_test 2 "error: tst-support_record_failure.c:108: not true: false -+ run_test 2 "error: tst-support_record_failure.c:109: not true: false - error: 1 test failures" $direct --test-verify -- run_test 2 "error: tst-support_record_failure.c:108: not true: false -+ run_test 2 "error: tst-support_record_failure.c:109: not true: false - info: execution passed failed TEST_VERIFY - error: 1 test failures" $direct --test-verify --verbose - } -@@ -62,8 +62,8 @@ error: 1 test failures" $direct --test-verify --verbose - different_status - different_status --direct - --run_test 1 "error: tst-support_record_failure.c:115: not true: false -+run_test 1 "error: tst-support_record_failure.c:116: not true: false - error: 1 test failures" --test-verify-exit - # --direct does not print the summary error message if exit is called. --run_test 1 "error: tst-support_record_failure.c:115: not true: false" \ -+run_test 1 "error: tst-support_record_failure.c:116: not true: false" \ - --direct --test-verify-exit -diff --git a/support/tst-support_record_failure.c b/support/tst-support_record_failure.c -index 62d8e1f057..e739e739c3 100644 ---- a/support/tst-support_record_failure.c -+++ b/support/tst-support_record_failure.c -@@ -25,6 +25,7 @@ - #include - #include - #include -+#include - - static int exit_status_with_failure = -1; - static bool test_verify; -diff --git a/support/xaccept4.c b/support/xaccept4.c -new file mode 100644 -index 0000000000..67dd95e9fb ---- /dev/null -+++ b/support/xaccept4.c -@@ -0,0 +1,32 @@ -+/* accept4 with error checking. -+ 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 -+ . */ -+ -+#include -+ -+#include -+#include -+#include -+ -+int -+xaccept4 (int fd, struct sockaddr *sa, socklen_t *salen, int flags) -+{ -+ int clientfd = accept4 (fd, sa, salen, flags); -+ if (clientfd < 0) -+ FAIL_EXIT1 ("accept4 (%d, 0x%x): %m", fd, flags); -+ return clientfd; -+} -diff --git a/support/xchroot.c b/support/xchroot.c -new file mode 100644 -index 0000000000..abcc299e00 ---- /dev/null -+++ b/support/xchroot.c -@@ -0,0 +1,28 @@ -+/* chroot with error checking. -+ 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 -+ . */ -+ -+#include -+#include -+#include -+ -+void -+xchroot (const char *path) -+{ -+ if (chroot (path) != 0) -+ FAIL_EXIT1 ("chroot (\"%s\"): %m", path); -+} -diff --git a/support/xclose.c b/support/xclose.c -new file mode 100644 -index 0000000000..c931e08421 ---- /dev/null -+++ b/support/xclose.c -@@ -0,0 +1,28 @@ -+/* close with error checking. -+ 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 -+ . */ -+ -+#include -+#include -+#include -+ -+void -+xclose (int fd) -+{ -+ if (close (fd) < 0 && errno != EINTR) -+ FAIL_EXIT1 ("close of descriptor %d failed: %m", fd); -+} -diff --git a/support/xdlfcn.c b/support/xdlfcn.c -new file mode 100644 -index 0000000000..6e3979983d ---- /dev/null -+++ b/support/xdlfcn.c -@@ -0,0 +1,58 @@ -+/* Support functionality for using dlopen/dlclose/dlsym. -+ 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 -+ . */ -+ -+#include -+#include -+ -+void * -+xdlopen (const char *filename, int flags) -+{ -+ void *dso = dlopen (filename, flags); -+ -+ if (dso == NULL) -+ FAIL_EXIT1 ("error: dlopen: %s\n", dlerror ()); -+ -+ /* Clear any errors. */ -+ dlerror (); -+ -+ return dso; -+} -+ -+void * -+xdlsym (void *handle, const char *symbol) -+{ -+ void *sym = dlsym (handle, symbol); -+ -+ if (sym == NULL) -+ FAIL_EXIT1 ("error: dlsym: %s\n", dlerror ()); -+ -+ /* Clear any errors. */ -+ dlerror (); -+ -+ return sym; -+} -+ -+void -+xdlclose (void *handle) -+{ -+ if (dlclose (handle) != 0) -+ FAIL_EXIT1 ("error: dlclose: %s\n", dlerror ()); -+ -+ /* Clear any errors. */ -+ dlerror (); -+} -diff --git a/support/xdlfcn.h b/support/xdlfcn.h -new file mode 100644 -index 0000000000..9bdcb38d3e ---- /dev/null -+++ b/support/xdlfcn.h -@@ -0,0 +1,34 @@ -+/* Support functionality for using dlopen/dlclose/dlsym. -+ 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 -+ . */ -+ -+#ifndef SUPPORT_DLOPEN_H -+#define SUPPORT_DLOPEN_H -+ -+#include -+ -+__BEGIN_DECLS -+ -+/* Each of these terminates process on failure with relevant error message. */ -+void *xdlopen (const char *filename, int flags); -+void *xdlsym (void *handle, const char *symbol); -+void xdlclose (void *handle); -+ -+ -+__END_DECLS -+ -+#endif /* SUPPORT_DLOPEN_H */ -diff --git a/support/xdup2.c b/support/xdup2.c -new file mode 100644 -index 0000000000..dc08c94518 ---- /dev/null -+++ b/support/xdup2.c -@@ -0,0 +1,28 @@ -+/* dup2 with error checking. -+ 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 -+ . */ -+ -+#include -+ -+#include -+ -+void -+xdup2 (int from, int to) -+{ -+ if (dup2 (from, to) < 0) -+ FAIL_EXIT1 ("dup2 (%d, %d): %m", from, to); -+} -diff --git a/support/xmkdir.c b/support/xmkdir.c -new file mode 100644 -index 0000000000..ea17d49391 ---- /dev/null -+++ b/support/xmkdir.c -@@ -0,0 +1,28 @@ -+/* mkdir with error checking. -+ 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 -+ . */ -+ -+#include -+#include -+#include -+ -+void -+xmkdir (const char *path, mode_t mode) -+{ -+ if (mkdir (path, mode) != 0) -+ FAIL_EXIT1 ("mkdir (\"%s\", 0%o): %m", path, mode); -+} -diff --git a/support/xmprotect.c b/support/xmprotect.c -new file mode 100644 -index 0000000000..9410251c32 ---- /dev/null -+++ b/support/xmprotect.c -@@ -0,0 +1,28 @@ -+/* mprotect with error checking. -+ 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 -+ . */ -+ -+#include -+#include -+#include -+ -+void -+xmprotect (void *addr, size_t length, int prot) -+{ -+ if (mprotect (addr, length, prot) != 0) -+ FAIL_EXIT1 ("mprotect (%p, %zu, 0x%x): %m", addr, length, prot); -+} -diff --git a/support/xopen.c b/support/xopen.c -new file mode 100644 -index 0000000000..7f033a03a7 ---- /dev/null -+++ b/support/xopen.c -@@ -0,0 +1,30 @@ -+/* open64 with error checking. -+ 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 -+ . */ -+ -+#include -+#include -+#include -+ -+int -+xopen (const char *path, int flags, mode_t mode) -+{ -+ int ret = open64 (path, flags, mode); -+ if (ret < 0) -+ FAIL_EXIT1 ("open64 (\"%s\", 0x%x, 0%o): %m", path, flags, mode); -+ return ret; -+} -diff --git a/support/xpipe.c b/support/xpipe.c -new file mode 100644 -index 0000000000..89a64a55c1 ---- /dev/null -+++ b/support/xpipe.c -@@ -0,0 +1,28 @@ -+/* pipe with error checking. -+ 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 -+ . */ -+ -+#include -+ -+#include -+ -+void -+xpipe (int fds[2]) -+{ -+ if (pipe (fds) < 0) -+ FAIL_EXIT1 ("pipe: %m"); -+} -diff --git a/support/xpthread_attr_setguardsize.c b/support/xpthread_attr_setguardsize.c -new file mode 100644 -index 0000000000..35fed5d9ec ---- /dev/null -+++ b/support/xpthread_attr_setguardsize.c -@@ -0,0 +1,26 @@ -+/* pthread_attr_setguardsize with error checking. -+ 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 -+ . */ -+ -+#include -+ -+void -+xpthread_attr_setguardsize (pthread_attr_t *attr, size_t guardsize) -+{ -+ xpthread_check_return ("pthread_attr_setguardize", -+ pthread_attr_setguardsize (attr, guardsize)); -+} -diff --git a/support/xpthread_rwlock_init.c b/support/xpthread_rwlock_init.c -new file mode 100644 -index 0000000000..824288c90e ---- /dev/null -+++ b/support/xpthread_rwlock_init.c -@@ -0,0 +1,27 @@ -+/* pthread_rwlock_init with error checking. -+ 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 -+ . */ -+ -+#include -+ -+void -+xpthread_rwlock_init (pthread_rwlock_t *rwlock, -+ const pthread_rwlockattr_t *attr) -+{ -+ xpthread_check_return ("pthread_rwlock_init", -+ pthread_rwlock_init (rwlock, attr)); -+} -diff --git a/support/xpthread_rwlock_rdlock.c b/support/xpthread_rwlock_rdlock.c -new file mode 100644 -index 0000000000..96330a5637 ---- /dev/null -+++ b/support/xpthread_rwlock_rdlock.c -@@ -0,0 +1,26 @@ -+/* pthread_rwlock_rdlock with error checking. -+ 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 -+ . */ -+ -+#include -+ -+void -+xpthread_rwlock_rdlock (pthread_rwlock_t *rwlock) -+{ -+ xpthread_check_return ("pthread_rwlock_rdlock", -+ pthread_rwlock_rdlock (rwlock)); -+} -diff --git a/support/xpthread_rwlock_unlock.c b/support/xpthread_rwlock_unlock.c -new file mode 100644 -index 0000000000..eaa136b3ec ---- /dev/null -+++ b/support/xpthread_rwlock_unlock.c -@@ -0,0 +1,26 @@ -+/* pthread_rwlock_unlock with error checking. -+ 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 -+ . */ -+ -+#include -+ -+void -+xpthread_rwlock_unlock (pthread_rwlock_t *rwlock) -+{ -+ xpthread_check_return ("pthread_rwlock_unlock", -+ pthread_rwlock_unlock (rwlock)); -+} -diff --git a/support/xpthread_rwlock_wrlock.c b/support/xpthread_rwlock_wrlock.c -new file mode 100644 -index 0000000000..8d25d5b818 ---- /dev/null -+++ b/support/xpthread_rwlock_wrlock.c -@@ -0,0 +1,26 @@ -+/* pthread_rwlock_wrlock with error checking. -+ 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 -+ . */ -+ -+#include -+ -+void -+xpthread_rwlock_wrlock (pthread_rwlock_t *rwlock) -+{ -+ xpthread_check_return ("pthread_rwlock_wrlock", -+ pthread_rwlock_wrlock (rwlock)); -+} -diff --git a/support/xpthread_rwlockattr_init.c b/support/xpthread_rwlockattr_init.c -new file mode 100644 -index 0000000000..48baf247f3 ---- /dev/null -+++ b/support/xpthread_rwlockattr_init.c -@@ -0,0 +1,26 @@ -+/* pthread_rwlockattr_init with error checking. -+ 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 -+ . */ -+ -+#include -+ -+void -+xpthread_rwlockattr_init (pthread_rwlockattr_t *attr) -+{ -+ xpthread_check_return ("pthread_rwlockattr_init", -+ pthread_rwlockattr_init (attr)); -+} -diff --git a/support/xpthread_rwlockattr_setkind_np.c b/support/xpthread_rwlockattr_setkind_np.c -new file mode 100644 -index 0000000000..958aace9f6 ---- /dev/null -+++ b/support/xpthread_rwlockattr_setkind_np.c -@@ -0,0 +1,27 @@ -+/* pthread_rwlockattr_setkind_np with error checking. -+ 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 -+ . */ -+ -+#include -+ -+void -+xpthread_rwlockattr_setkind_np (pthread_rwlockattr_t *attr, -+ int pref) -+{ -+ xpthread_check_return ("pthread_rwlockattr_setkind_np", -+ pthread_rwlockattr_setkind_np (attr, pref)); -+} -diff --git a/support/xsocket.h b/support/xsocket.h -index 0dbf13ace9..d6724948d8 100644 ---- a/support/xsocket.h -+++ b/support/xsocket.h -@@ -30,6 +30,7 @@ void xconnect (int, const struct sockaddr *, socklen_t); - void xbind (int, const struct sockaddr *, socklen_t); - void xlisten (int, int); - int xaccept (int, struct sockaddr *, socklen_t *); -+int xaccept4 (int, struct sockaddr *, socklen_t *, int); - void xsendto (int, const void *, size_t, int, - const struct sockaddr *, socklen_t); - size_t xrecvfrom (int, void *, size_t, int, struct sockaddr *, socklen_t *); -diff --git a/support/xthread.h b/support/xthread.h -index 6dd7e709be..472763ebe8 100644 ---- a/support/xthread.h -+++ b/support/xthread.h -@@ -67,11 +67,21 @@ void xpthread_attr_setdetachstate (pthread_attr_t *attr, - int detachstate); - void xpthread_attr_setstacksize (pthread_attr_t *attr, - size_t stacksize); -+void xpthread_attr_setguardsize (pthread_attr_t *attr, -+ size_t guardsize); - - /* This function returns non-zero if pthread_barrier_wait returned - PTHREAD_BARRIER_SERIAL_THREAD. */ - int xpthread_barrier_wait (pthread_barrier_t *barrier); - -+void xpthread_rwlock_init (pthread_rwlock_t *rwlock, -+ const pthread_rwlockattr_t *attr); -+void xpthread_rwlockattr_init (pthread_rwlockattr_t *attr); -+void xpthread_rwlockattr_setkind_np (pthread_rwlockattr_t *attr, int pref); -+void xpthread_rwlock_wrlock (pthread_rwlock_t *rwlock); -+void xpthread_rwlock_rdlock (pthread_rwlock_t *rwlock); -+void xpthread_rwlock_unlock (pthread_rwlock_t *rwlock); -+ - __END_DECLS - - #endif /* SUPPORT_THREAD_H */ -diff --git a/support/xunistd.h b/support/xunistd.h -index a83b1f4541..c947bfd8fb 100644 ---- a/support/xunistd.h -+++ b/support/xunistd.h -@@ -22,20 +22,33 @@ - #ifndef SUPPORT_XUNISTD_H - #define SUPPORT_XUNISTD_H - --#include - #include -+#include -+#include - - __BEGIN_DECLS - -+struct stat64; -+ - pid_t xfork (void); - pid_t xwaitpid (pid_t, int *status, int flags); -+void xpipe (int[2]); -+void xdup2 (int, int); -+int xopen (const char *path, int flags, mode_t); -+void xstat (const char *path, struct stat64 *); -+void xmkdir (const char *path, mode_t); -+void xchroot (const char *path); -+ -+/* Close the file descriptor. Ignore EINTR errors, but terminate the -+ process on other errors. */ -+void xclose (int); - - /* Write the buffer. Retry on short writes. */ - void xwrite (int, const void *, size_t); - - /* Invoke mmap with a zero file offset. */ - void *xmmap (void *addr, size_t length, int prot, int flags, int fd); -- -+void xmprotect (void *addr, size_t length, int prot); - void xmunmap (void *addr, size_t length); - - __END_DECLS -diff --git a/sysdeps/aarch64/dl-machine.h b/sysdeps/aarch64/dl-machine.h -index 84b8aecfb8..6067a1d8a0 100644 ---- a/sysdeps/aarch64/dl-machine.h -+++ b/sysdeps/aarch64/dl-machine.h -@@ -193,8 +193,8 @@ _dl_start_user: \n\ - cmp " PTR "0, #0 \n\ - bne 1b \n\ - // Update _dl_argv \n\ -- adrp x3, _dl_argv \n\ -- str " PTR "2, [x3, #:lo12:_dl_argv] \n\ -+ adrp x3, __GI__dl_argv \n\ -+ str " PTR "2, [x3, #:lo12:__GI__dl_argv] \n\ - .L_done_stack_adjust: \n\ - // compute envp \n\ - add " PTR "3, " PTR "2, " PTR "1, lsl #" PTR_SIZE_LOG " \n\ -diff --git a/sysdeps/generic/unsecvars.h b/sysdeps/generic/unsecvars.h -index a74083786e..5ea8a4a259 100644 ---- a/sysdeps/generic/unsecvars.h -+++ b/sysdeps/generic/unsecvars.h -@@ -16,6 +16,7 @@ - "LD_DEBUG\0" \ - "LD_DEBUG_OUTPUT\0" \ - "LD_DYNAMIC_WEAK\0" \ -+ "LD_HWCAP_MASK\0" \ - "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 - - 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 -+#include -+#include -+ -+#define glob_t glob64_t -+#define globfree(pglob) globfree64 (pglob) -+ -+#include -+ -+libc_hidden_def (globfree64) -diff --git a/sysdeps/hppa/__longjmp.c b/sysdeps/hppa/__longjmp.c -index a7eefc7ad6..2fedb1d738 100644 ---- a/sysdeps/hppa/__longjmp.c -+++ b/sysdeps/hppa/__longjmp.c -@@ -24,15 +24,15 @@ - void - __longjmp (__jmp_buf env, int val) - { -+#ifdef CHECK_SP -+ CHECK_SP (env[0].__jmp_buf.__sp); -+#endif -+ - /* We must use one of the non-callee saves registers - for env. */ - register unsigned long r26 asm ("r26") = (unsigned long)&env[0]; - register unsigned long r25 asm ("r25") = (unsigned long)(val == 0 ? 1 : val); - --#ifdef CHECK_SP -- CHECK_SP (env[0].__jmp_buf.__sp); --#endif -- - asm volatile( - /* Set return value. */ - "copy %0, %%r28\n\t" -@@ -79,6 +79,7 @@ __longjmp (__jmp_buf env, int val) - : /* No outputs. */ - : "r" (r25), "r" (r26) - : /* No point in clobbers. */ ); -+ - /* Avoid `volatile function does return' warnings. */ - for (;;); - } -diff --git a/sysdeps/hppa/dl-fptr.c b/sysdeps/hppa/dl-fptr.c -index 83bdb91202..f74abc02c2 100644 ---- a/sysdeps/hppa/dl-fptr.c -+++ b/sysdeps/hppa/dl-fptr.c -@@ -181,24 +181,29 @@ make_fdesc (ElfW(Addr) ip, ElfW(Addr) gp) - static inline ElfW(Addr) * __attribute__ ((always_inline)) - make_fptr_table (struct link_map *map) - { -- const ElfW(Sym) *symtab -- = (const void *) D_PTR (map, l_info[DT_SYMTAB]); -+ const ElfW(Sym) *symtab = (const void *) D_PTR (map, l_info[DT_SYMTAB]); - const char *strtab = (const void *) D_PTR (map, l_info[DT_STRTAB]); - ElfW(Addr) *fptr_table; - size_t size; - size_t len; -+ const ElfW(Sym) *symtabend; - -- /* XXX Apparently the only way to find out the size of the dynamic -- symbol section is to assume that the string table follows right -- afterwards... */ -- len = ((strtab - (char *) symtab) -+ /* Determine the end of the dynamic symbol table using the hash. */ -+ if (map->l_info[DT_HASH] != NULL) -+ symtabend = (symtab + ((Elf_Symndx *) D_PTR (map, l_info[DT_HASH]))[1]); -+ else -+ /* There is no direct way to determine the number of symbols in the -+ dynamic symbol table and no hash table is present. The ELF -+ binary is ill-formed but what shall we do? Use the beginning of -+ the string table which generally follows the symbol table. */ -+ symtabend = (const ElfW(Sym) *) strtab; -+ -+ len = (((char *) symtabend - (char *) symtab) - / map->l_info[DT_SYMENT]->d_un.d_val); -- size = ((len * sizeof (fptr_table[0]) + GLRO(dl_pagesize) - 1) -- & -GLRO(dl_pagesize)); -- /* XXX We don't support here in the moment systems without MAP_ANON. -- There probably are none for IA-64. In case this is proven wrong -- we will have to open /dev/null here and use the file descriptor -- instead of the hard-coded -1. */ -+ size = ALIGN_UP (len * sizeof (fptr_table[0]), GLRO(dl_pagesize)); -+ -+ /* We don't support systems without MAP_ANON. We avoid using malloc -+ because this might get called before malloc is setup. */ - fptr_table = __mmap (NULL, size, - PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, - -1, 0); -@@ -331,22 +336,45 @@ elf_machine_resolve (void) - return addr; - } - -+static inline int -+_dl_read_access_allowed (unsigned int *addr) -+{ -+ int result; -+ -+ asm ("proberi (%1),3,%0" : "=r" (result) : "r" (addr) : ); -+ -+ return result; -+} -+ - ElfW(Addr) - _dl_lookup_address (const void *address) - { - ElfW(Addr) addr = (ElfW(Addr)) address; - unsigned int *desc, *gptr; - -- /* Check for special cases. */ -- if ((int) addr == -1 -- || (unsigned int) addr < 4096 -- || !((unsigned int) addr & 2)) -+ /* Return ADDR if the least-significant two bits of ADDR are not consistent -+ with ADDR being a linker defined function pointer. The normal value for -+ a code address in a backtrace is 3. */ -+ if (((unsigned int) addr & 3) != 2) -+ return addr; -+ -+ /* Handle special case where ADDR points to page 0. */ -+ if ((unsigned int) addr < 4096) - return addr; - - /* Clear least-significant two bits from descriptor address. */ - desc = (unsigned int *) ((unsigned int) addr & ~3); -+ if (!_dl_read_access_allowed (desc)) -+ return addr; - -- /* Check if descriptor requires resolution. The following trampoline is -+ /* Load first word of candidate descriptor. It should be a pointer -+ with word alignment and point to memory that can be read. */ -+ gptr = (unsigned int *) desc[0]; -+ if (((unsigned int) gptr & 3) != 0 -+ || !_dl_read_access_allowed (gptr)) -+ return addr; -+ -+ /* See if descriptor requires resolution. The following trampoline is - used in each global offset table for function resolution: - - ldw 0(r20),r22 -@@ -358,7 +386,6 @@ _dl_lookup_address (const void *address) - .word "_dl_runtime_resolve ltp" - got: .word _DYNAMIC - .word "struct link map address" */ -- gptr = (unsigned int *) desc[0]; - if (gptr[0] == 0xea9f1fdd /* b,l .-12,r20 */ - && gptr[1] == 0xd6801c1e /* depwi 0,31,2,r20 */ - && (ElfW(Addr)) gptr[2] == elf_machine_resolve ()) -diff --git a/sysdeps/hppa/dl-machine.h b/sysdeps/hppa/dl-machine.h -index 339c7bb771..787b95f502 100644 ---- a/sysdeps/hppa/dl-machine.h -+++ b/sysdeps/hppa/dl-machine.h -@@ -302,6 +302,10 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile) - #define ARCH_LA_PLTENTER hppa_gnu_pltenter - #define ARCH_LA_PLTEXIT hppa_gnu_pltexit - -+/* Adjust DL_STACK_END to get value we want in __libc_stack_end. */ -+#define DL_STACK_END(cookie) \ -+ ((void *) (((long) (cookie)) + 0x160)) -+ - /* Initial entry point code for the dynamic linker. - The C function `_dl_start' is the real entry point; - its return value is the user program's entry point. */ -@@ -401,11 +405,6 @@ asm ( \ - /* Save the entry point in %r3. */ \ - " copy %ret0,%r3\n" \ - \ -- /* Remember the lowest stack address. */ \ --" addil LT'__libc_stack_end,%r19\n" \ --" ldw RT'__libc_stack_end(%r1),%r20\n" \ --" stw %sp,0(%r20)\n" \ -- \ - /* See if we were called as a command with the executable file \ - name as an extra leading argument. */ \ - " addil LT'_dl_skip_args,%r19\n" \ -diff --git a/sysdeps/hppa/dl-trampoline.S b/sysdeps/hppa/dl-trampoline.S -index 856339bffe..3165c6f0e2 100644 ---- a/sysdeps/hppa/dl-trampoline.S -+++ b/sysdeps/hppa/dl-trampoline.S -@@ -82,6 +82,21 @@ _dl_runtime_resolve: - bl _dl_fixup,%rp - copy %r21,%r19 /* set fixup func ltp */ - -+ /* While the linker will set a function pointer to NULL when it -+ encounters an undefined weak function, we need to dynamically -+ detect removed weak functions. The issue arises because a weak -+ __gmon_start__ function was added to shared executables to work -+ around issues in _init that are now resolved. The presence of -+ __gmon_start__ in every shared library breaks the linker -+ `--as-needed' option. This __gmon_start__ function does nothing -+ but removal is tricky. Depending on the binding, removal can -+ cause an application using it to fault. The call to _dl_fixup -+ returns NULL when a function isn't resolved. In order to help -+ with __gmon_start__ removal, we return directly to the caller -+ when _dl_fixup returns NULL. This check could be removed when -+ BZ 19170 is fixed. */ -+ comib,= 0,%r28,1f -+ - /* Load up the returned func descriptor */ - copy %r28, %r22 - copy %r29, %r19 -@@ -107,6 +122,13 @@ _dl_runtime_resolve: - /* Jump to new function, but return to previous function */ - bv %r0(%r22) - ldw -20(%sp),%rp -+ -+1: -+ /* Return to previous function */ -+ ldw -148(%sp),%rp -+ bv %r0(%rp) -+ ldo -128(%sp),%sp -+ - .EXIT - .PROCEND - cfi_endproc -diff --git a/sysdeps/hppa/math-tests.h b/sysdeps/hppa/math-tests.h -new file mode 100644 -index 0000000000..bb205907ad ---- /dev/null -+++ b/sysdeps/hppa/math-tests.h -@@ -0,0 +1,22 @@ -+/* Configuration for math tests. hppa 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 -+ . */ -+ -+/* SNaN tests do not preserve payloads. */ -+#define SNAN_TESTS_PRESERVE_PAYLOAD 0 -+ -+#include_next -diff --git a/sysdeps/hppa/nptl/bits/pthreadtypes.h b/sysdeps/hppa/nptl/bits/pthreadtypes.h -index e37111a2f3..579047b732 100644 ---- a/sysdeps/hppa/nptl/bits/pthreadtypes.h -+++ b/sysdeps/hppa/nptl/bits/pthreadtypes.h -@@ -106,36 +106,34 @@ typedef union - - /* Data structure for conditional variable handling. The structure of - the attribute type is not exposed on purpose. However, this structure -- is exposed via PTHREAD_COND_INITIALIZER, and because of this, the -- Linuxthreads version sets the first four ints to one. In the NPTL -- version we must check, in every function using pthread_cond_t, -- for the static Linuxthreads initializer and clear the appropriate -- words. */ -+ is exposed via PTHREAD_COND_INITIALIZER. Support for Linuxthreads has -+ been dropped but we still need to retain the alignment of the original -+ lock field from Linuxthreads. */ - typedef union - { - struct - { -- /* In the old Linuxthreads pthread_cond_t, this is the -- start of the 4-word lock structure, the next four words -- are set all to 1 by the Linuxthreads -- PTHREAD_COND_INITIALIZER. */ -- int __lock __attribute__ ((__aligned__(16))); -- /* Tracks the initialization of this structure: -- 0 initialized with NPTL PTHREAD_COND_INITIALIZER. -- 1 initialized with Linuxthreads PTHREAD_COND_INITIALIZER. -- 2 initialization in progress. */ -- int __initializer; -- unsigned int __futex; -- void *__mutex; -- /* In the old Linuxthreads this would have been the start -- of the pthread_fastlock status word. */ -- __extension__ unsigned long long int __total_seq; -- __extension__ unsigned long long int __wakeup_seq; -- __extension__ unsigned long long int __woken_seq; -- unsigned int __nwaiters; -- unsigned int __broadcast_seq; -- /* The NPTL pthread_cond_t is exactly the same size as -- the Linuxthreads version, there are no words to spare. */ -+ __extension__ union -+ { -+ __extension__ unsigned long long int __wseq; -+ struct { -+ unsigned int __low; -+ unsigned int __high; -+ } __wseq32; -+ }; -+ __extension__ union -+ { -+ __extension__ unsigned long long int __g1_start; -+ struct { -+ unsigned int __low; -+ unsigned int __high; -+ } __g1_start32; -+ }; -+ unsigned int __g_refs[2] __attribute__ ((__aligned__(16))); -+ unsigned int __g_size[2]; -+ unsigned int __g1_orig_size; -+ unsigned int __wrefs; -+ unsigned int __g_signals[2]; - } __data; - char __size[__SIZEOF_PTHREAD_COND_T]; - __extension__ long long int __align; -diff --git a/sysdeps/i386/i686/fpu/multiarch/libm-test-ulps b/sysdeps/i386/i686/fpu/multiarch/libm-test-ulps -index cb82d3ee36..275dbbe804 100644 ---- a/sysdeps/i386/i686/fpu/multiarch/libm-test-ulps -+++ b/sysdeps/i386/i686/fpu/multiarch/libm-test-ulps -@@ -42,7 +42,7 @@ ldouble: 4 - Function: "acosh_upward": - double: 1 - idouble: 1 --ildouble: 4 -+ildouble: 5 - ldouble: 3 - - Function: "asin": -@@ -900,8 +900,8 @@ double: 3 - float: 3 - idouble: 3 - ifloat: 3 --ildouble: 7 --ldouble: 7 -+ildouble: 8 -+ldouble: 8 - - Function: Imaginary part of "clog10_upward": - double: 1 -@@ -1591,8 +1591,8 @@ double: 3 - float: 4 - idouble: 3 - ifloat: 4 --ildouble: 5 --ldouble: 5 -+ildouble: 6 -+ldouble: 6 - - Function: "hypot": - double: 1 -@@ -1743,8 +1743,8 @@ double: 3 - float: 4 - idouble: 3 - ifloat: 4 --ildouble: 5 --ldouble: 5 -+ildouble: 6 -+ldouble: 6 - - Function: "log": - double: 1 -diff --git a/sysdeps/i386/i686/multiarch/memchr-sse2.S b/sysdeps/i386/i686/multiarch/memchr-sse2.S -index 910679cfc0..e41f324a77 100644 ---- a/sysdeps/i386/i686/multiarch/memchr-sse2.S -+++ b/sysdeps/i386/i686/multiarch/memchr-sse2.S -@@ -117,7 +117,6 @@ L(crosscache): - - # ifndef USE_AS_RAWMEMCHR - jnz L(match_case2_prolog1) -- lea -16(%edx), %edx - /* Calculate the last acceptable address and check for possible - addition overflow by using satured math: - edx = ecx + edx -@@ -125,6 +124,7 @@ L(crosscache): - add %ecx, %edx - sbb %eax, %eax - or %eax, %edx -+ sub $16, %edx - jbe L(return_null) - lea 16(%edi), %edi - # else -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 -+++ b/sysdeps/i386/i686/multiarch/strcspn-c.c -@@ -1,2 +1,4 @@ --#define __strcspn_sse2 __strcspn_ia32 --#include -+#if IS_IN (libc) -+# define __strcspn_sse2 __strcspn_ia32 -+# include -+#endif -diff --git a/sysdeps/i386/i686/multiarch/varshift.c b/sysdeps/i386/i686/multiarch/varshift.c -index 7760b966e2..6742a35d41 100644 ---- a/sysdeps/i386/i686/multiarch/varshift.c -+++ b/sysdeps/i386/i686/multiarch/varshift.c -@@ -1 +1,3 @@ --#include -+#if IS_IN (libc) -+# include -+#endif -diff --git a/sysdeps/mips/bits/long-double.h b/sysdeps/mips/bits/long-double.h -deleted file mode 100644 -index 604188e181..0000000000 ---- a/sysdeps/mips/bits/long-double.h -+++ /dev/null -@@ -1,23 +0,0 @@ --/* Properties of long double type. MIPS version. -- Copyright (C) 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 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 -- . */ -- --#include -- --#if !defined __NO_LONG_DOUBLE_MATH && _MIPS_SIM == _ABIO32 --# define __NO_LONG_DOUBLE_MATH 1 --#endif -diff --git a/sysdeps/mips/ieee754/bits/long-double.h b/sysdeps/mips/ieee754/bits/long-double.h -new file mode 100644 -index 0000000000..604188e181 ---- /dev/null -+++ b/sysdeps/mips/ieee754/bits/long-double.h -@@ -0,0 +1,23 @@ -+/* Properties of long double type. MIPS version. -+ Copyright (C) 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 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 -+ . */ -+ -+#include -+ -+#if !defined __NO_LONG_DOUBLE_MATH && _MIPS_SIM == _ABIO32 -+# define __NO_LONG_DOUBLE_MATH 1 -+#endif -diff --git a/sysdeps/nptl/fork.c b/sysdeps/nptl/fork.c -index db6d721fce..4bb87e2331 100644 ---- a/sysdeps/nptl/fork.c -+++ b/sysdeps/nptl/fork.c -@@ -131,10 +131,6 @@ __libc_fork (void) - call_function_static_weak (__malloc_fork_lock_parent); - } - --#ifndef NDEBUG -- pid_t ppid = THREAD_GETMEM (THREAD_SELF, tid); --#endif -- - #ifdef ARCH_FORK - pid = ARCH_FORK (); - #else -@@ -147,8 +143,6 @@ __libc_fork (void) - { - struct pthread *self = THREAD_SELF; - -- assert (THREAD_GETMEM (self, tid) != ppid); -- - /* See __pthread_once. */ - if (__fork_generation_pointer != NULL) - *__fork_generation_pointer += __PTHREAD_ONCE_FORK_GEN_INCR; -@@ -230,8 +224,6 @@ __libc_fork (void) - } - else - { -- assert (THREAD_GETMEM (THREAD_SELF, tid) == ppid); -- - /* Release acquired locks in the multi-threaded case. */ - if (multiple_threads) - { -diff --git a/sysdeps/powerpc/power7/fpu/s_logbl.c b/sysdeps/powerpc/power7/fpu/s_logbl.c -index f7ecbd105a..3ae383a831 100644 ---- a/sysdeps/powerpc/power7/fpu/s_logbl.c -+++ b/sysdeps/powerpc/power7/fpu/s_logbl.c -@@ -35,14 +35,16 @@ static const union { - long double - __logbl (long double x) - { -- double xh; -+ double xh, xl; - double ret; -+ int64_t hx; - - if (__builtin_expect (x == 0.0L, 0)) - /* Raise FE_DIVBYZERO and return -HUGE_VAL[LF]. */ - return -1.0L / __builtin_fabsl (x); - -- xh = ldbl_high (x); -+ ldbl_unpack (x, &xh, &xl); -+ EXTRACT_WORDS64 (hx, xh); - /* ret = x & 0x7ff0000000000000; */ - asm ( - "xxland %x0,%x1,%x2\n" -@@ -58,10 +60,20 @@ __logbl (long double x) - { - /* POSIX specifies that denormal number is treated as - though it were normalized. */ -- int64_t hx; -- -- EXTRACT_WORDS64 (hx, xh); -- return (long double) (-1023 - (__builtin_clzll (hx) - 12)); -+ return (long double) (- (__builtin_clzll (hx & 0x7fffffffffffffffLL) \ -+ - 12) - 1023); -+ } -+ else if ((hx & 0x000fffffffffffffLL) == 0) -+ { -+ /* If the high part is a power of 2, and the low part is nonzero -+ with the opposite sign, the low part affects the -+ exponent. */ -+ int64_t lx, rhx; -+ EXTRACT_WORDS64 (lx, xl); -+ rhx = (hx & 0x7ff0000000000000LL) >> 52; -+ if ((hx ^ lx) < 0 && (lx & 0x7fffffffffffffffLL) != 0) -+ rhx--; -+ return (long double) (rhx - 1023); - } - /* Test to avoid logb_downward (0.0) == -0.0. */ - return ret == -0.0 ? 0.0 : ret; -diff --git a/sysdeps/powerpc/powerpc32/dl-machine.h b/sysdeps/powerpc/powerpc32/dl-machine.h -index 28eb50f92d..9b5a99fcc7 100644 ---- a/sysdeps/powerpc/powerpc32/dl-machine.h -+++ b/sysdeps/powerpc/powerpc32/dl-machine.h -@@ -309,7 +309,10 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc, - against local symbols. */ - if (__builtin_expect (ELF32_ST_BIND (sym->st_info) == STB_LOCAL, 0) - && sym->st_shndx != SHN_UNDEF) -- value = map->l_addr; -+ { -+ sym_map = map; -+ value = map->l_addr; -+ } - else - { - sym_map = RESOLVE_MAP (&sym, version, r_type); -diff --git a/sysdeps/sparc/sparc32/dl-machine.h b/sysdeps/sparc/sparc32/dl-machine.h -index cf7272f359..3e03fd091c 100644 ---- a/sysdeps/sparc/sparc32/dl-machine.h -+++ b/sysdeps/sparc/sparc32/dl-machine.h -@@ -375,6 +375,7 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc, - if (__builtin_expect (ELF32_ST_BIND (sym->st_info) == STB_LOCAL, 0) - && sym->st_shndx != SHN_UNDEF) - { -+ sym_map = map; - value = map->l_addr; - } - else -diff --git a/sysdeps/sparc/sparc64/dl-machine.h b/sysdeps/sparc/sparc64/dl-machine.h -index 99c00f493d..0694ac1362 100644 ---- a/sysdeps/sparc/sparc64/dl-machine.h -+++ b/sysdeps/sparc/sparc64/dl-machine.h -@@ -402,6 +402,7 @@ elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc, - if (__builtin_expect (ELF64_ST_BIND (sym->st_info) == STB_LOCAL, 0) - && sym->st_shndx != SHN_UNDEF) - { -+ sym_map = map; - value = map->l_addr; - } - else -diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile -index b3d68665f9..beb1c29111 100644 ---- a/sysdeps/unix/sysv/linux/Makefile -+++ b/sysdeps/unix/sysv/linux/Makefile -@@ -141,7 +141,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/alpha/glob.c b/sysdeps/unix/sysv/linux/alpha/glob.c -index 2d7d287a25..1b813c1cfd 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 -+ . */ -+ -+#define globfree64 __no_globfree64_decl -+#include -+#include -+#include -+ -+#define globfree(pglob) \ -+ __new_globfree (pglob) -+ -+extern void __new_globfree (glob_t *__pglob); -+ -+#include -+ -+#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/localplt.data b/sysdeps/unix/sysv/linux/alpha/localplt.data -index cca17f1e34..1f0e3b494e 100644 ---- a/sysdeps/unix/sysv/linux/alpha/localplt.data -+++ b/sysdeps/unix/sysv/linux/alpha/localplt.data -@@ -20,7 +20,7 @@ libc.so: free + RELA R_ALPHA_GLOB_DAT - libc.so: malloc + RELA R_ALPHA_GLOB_DAT - libc.so: memalign + RELA R_ALPHA_GLOB_DAT - libc.so: realloc + RELA R_ALPHA_GLOB_DAT --libm.so: matherr -+libm.so: matherr + RELA R_ALPHA_GLOB_DAT - # We used to offer inline functions that used this, so it must be exported. - # Ought to reorg things such that carg isn't thus forced to use a plt. - libm.so: __atan2 -diff --git a/sysdeps/unix/sysv/linux/hppa/bits/shm.h b/sysdeps/unix/sysv/linux/hppa/bits/shm.h -index 794f0ab2da..495dae8afc 100644 ---- a/sysdeps/unix/sysv/linux/hppa/bits/shm.h -+++ b/sysdeps/unix/sysv/linux/hppa/bits/shm.h -@@ -37,7 +37,7 @@ - #define SHM_UNLOCK 12 /* unlock segment (root only) */ - - /* Segment low boundary address multiple. */ --#define SHMLBA 0x00400000 /* address needs to be 4 Mb aligned */ -+#define SHMLBA 0x1000 - - /* Type to count number of attaches. */ - typedef unsigned long int shmatt_t; -diff --git a/sysdeps/unix/sysv/linux/hppa/clone.S b/sysdeps/unix/sysv/linux/hppa/clone.S -index d36b302199..f6b4e3eea8 100644 ---- a/sysdeps/unix/sysv/linux/hppa/clone.S -+++ b/sysdeps/unix/sysv/linux/hppa/clone.S -@@ -64,9 +64,12 @@ - ENTRY(__clone) - /* Prologue */ - stwm %r4, 64(%sp) -+ .cfi_def_cfa_offset -64 -+ .cfi_offset 4, 0 - stw %sp, -4(%sp) - #ifdef PIC - stw %r19, -32(%sp) -+ .cfi_offset 19, 32 - #endif - - /* Sanity check arguments. */ -@@ -147,9 +150,9 @@ ENTRY(__clone) - #ifdef PIC - copy %r4, %r19 - #endif -- /* The call to _exit needs saved r19. */ -- bl _exit, %rp -- copy %ret0, %arg0 -+ copy %r28, %r26 -+ ble 0x100(%sr2, %r0) -+ ldi __NR_exit, %r20 - - /* We should not return from _exit. - We do not restore r4, or the stack state. */ -diff --git a/sysdeps/unix/sysv/linux/hppa/getcontext.S b/sysdeps/unix/sysv/linux/hppa/getcontext.S -index 6f52f2149d..68a74a0b7e 100644 ---- a/sysdeps/unix/sysv/linux/hppa/getcontext.S -+++ b/sysdeps/unix/sysv/linux/hppa/getcontext.S -@@ -130,8 +130,11 @@ ENTRY(__getcontext) - - /* Prologue */ - stwm %r4, 64(%sp) -+ .cfi_def_cfa_offset -64 -+ .cfi_offset 4, 0 - #ifdef PIC - stw %r19, -32(%sp) -+ .cfi_offset 19, 32 - #endif - - /* Set up the trampoline registers. -@@ -156,7 +159,7 @@ ENTRY(__getcontext) - /* Epilogue */ - ldw -84(%sp), %r2 - #ifdef PIC -- ldw -96(%sp), %r19 -+ ldw -32(%sp), %r19 - #endif - bv %r0(%r2) - ldwm -64(%sp), %r4 -diff --git a/sysdeps/unix/sysv/linux/hppa/internaltypes.h b/sysdeps/unix/sysv/linux/hppa/internaltypes.h -deleted file mode 100644 -index d6496579da..0000000000 ---- a/sysdeps/unix/sysv/linux/hppa/internaltypes.h -+++ /dev/null -@@ -1,84 +0,0 @@ --#include_next --#ifndef _INTERNAL_TYPES_H_HPPA_ --#define _INTERNAL_TYPES_H_HPPA_ 1 --#include -- --/* In GLIBC 2.10 HPPA switched from Linuxthreads to NPTL, and in order --to maintain ABI compatibility with pthread_cond_t, some care had to be --taken. -- --The NPTL pthread_cond_t grew in size. When HPPA switched to NPTL, we --dropped the use of ldcw, and switched to the kernel helper routine for --compare-and-swap. This allowed HPPA to use the 4-word 16-byte aligned --lock words, and alignment words to store the additional pthread_cond_t --data. Once organized properly the new NPTL pthread_cond_t was 1 word --smaller than the Linuxthreads version. -- --However, we were faced with the case that users may have initialized the --pthread_cond_t with PTHREAD_COND_INITIALIZER. In this case, the first --four words were set to one, and must be cleared before any NPTL code --used these words. -- --We didn't want to use LDCW, because it continues to be a source of bugs --when applications memset pthread_cond_t to all zeroes by accident. This --works on all other architectures where lock words are unlocked at zero. --Remember that because of the semantics of LDCW, a locked word is set to --zero, and an unlocked word is set to 1. -- --Instead we used atomic_compare_and_exchange_val_acq, but we couldn't use --this on any of the pthread_cond_t words, otherwise it might interfere --with the current operation of the structure. To solve this problem we --used the left over word. -- --If the stucture was initialized by a legacy Linuxthread --PTHREAD_COND_INITIALIZER it contained a 1, and this indicates that the --structure requires zeroing for NPTL. The first thread to come upon a --pthread_cond_t with a 1 in the __initializer field, will --compare-and-swap the value, placing a 2 there which will cause all other --threads using the same pthread_cond_t to wait for the completion of the --initialization. Lastly, we use a store (with memory barrier) to change --__initializer from 2 to 0. Note that the store is strongly ordered, but --we use the PA 1.1 compatible form which is ",ma" with zero offset. -- --In the future, when the application is recompiled with NPTL --PTHREAD_COND_INITIALIZER it will be a quick compare-and-swap, which --fails because __initializer is zero, and the structure will be used as --is correctly. */ -- --#define cond_compat_clear(var) \ --({ \ -- int tmp = 0; \ -- var->__data.__wseq = 0; \ -- var->__data.__signals_sent = 0; \ -- var->__data.__confirmed = 0; \ -- var->__data.__generation = 0; \ -- var->__data.__mutex = NULL; \ -- var->__data.__quiescence_waiters = 0; \ -- var->__data.__clockid = 0; \ -- /* Clear __initializer last, to indicate initialization is done. */ \ -- /* This synchronizes-with the acquire load below. */ \ -- atomic_store_release (&var->__data.__initializer, 0); \ --}) -- --#define cond_compat_check_and_clear(var) \ --({ \ -- int v; \ -- int *value = &var->__data.__initializer; \ -- /* This synchronizes-with the release store above. */ \ -- while ((v = atomic_load_acquire (value)) != 0) \ -- { \ -- if (v == 1 \ -- /* Relaxed MO is fine; it only matters who's first. */ \ -- && atomic_compare_exchange_acquire_weak_relaxed (value, 1, 2)) \ -- { \ -- /* We're first; initialize structure. */ \ -- cond_compat_clear (var); \ -- break; \ -- } \ -- else \ -- /* Yield before we re-check initialization status. */ \ -- sched_yield (); \ -- } \ --}) -- --#endif -diff --git a/sysdeps/unix/sysv/linux/hppa/ipc_priv.h b/sysdeps/unix/sysv/linux/hppa/ipc_priv.h -new file mode 100644 -index 0000000000..d880f5029a ---- /dev/null -+++ b/sysdeps/unix/sysv/linux/hppa/ipc_priv.h -@@ -0,0 +1,21 @@ -+/* Old SysV permission definition for Linux. Hppa 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 -+ . */ -+ -+#include /* For __key_t */ -+ -+#define __IPC_64 0x0 -diff --git a/sysdeps/unix/sysv/linux/hppa/localplt.data b/sysdeps/unix/sysv/linux/hppa/localplt.data -index 9dd81b47c8..db9e24b090 100644 ---- a/sysdeps/unix/sysv/linux/hppa/localplt.data -+++ b/sysdeps/unix/sysv/linux/hppa/localplt.data -@@ -6,7 +6,6 @@ libc.so: free - libc.so: malloc - libc.so: memalign - libc.so: realloc --libc.so: _exit - libc.so: __sigsetjmp - libc.so: _IO_funlockfile - libc.so: sigprocmask -diff --git a/sysdeps/unix/sysv/linux/hppa/pt-vfork.S b/sysdeps/unix/sysv/linux/hppa/pt-vfork.S -index fc4573c86b..8b7d7df2fe 100644 ---- a/sysdeps/unix/sysv/linux/hppa/pt-vfork.S -+++ b/sysdeps/unix/sysv/linux/hppa/pt-vfork.S -@@ -58,7 +58,10 @@ ENTRY(__vfork) - that there is no child now, so it's safe to create - a frame. */ - stw %rp, -20(%sp) -+ .cfi_offset 2, -20 - stwm %r3, 64(%sp) -+ .cfi_def_cfa_offset -64 -+ .cfi_offset 3, 0 - stw %sp, -4(%sp) - - sub %r0,%ret0,%r3 -diff --git a/sysdeps/unix/sysv/linux/hppa/pthread.h b/sysdeps/unix/sysv/linux/hppa/pthread.h -index ac617201d2..806072cde4 100644 ---- a/sysdeps/unix/sysv/linux/hppa/pthread.h -+++ b/sysdeps/unix/sysv/linux/hppa/pthread.h -@@ -26,6 +26,7 @@ - #include - #include - #include -+#include - - - /* Detach state. */ -@@ -82,32 +83,18 @@ enum - #endif - - --#ifdef __PTHREAD_MUTEX_HAVE_PREV --# define PTHREAD_MUTEX_INITIALIZER \ -- { { 0, 0, 0, 0, 0, __PTHREAD_SPINS, { 0, 0 } } } --# ifdef __USE_GNU --# define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP \ -- { { 0, 0, 0, 0, PTHREAD_MUTEX_RECURSIVE_NP, __PTHREAD_SPINS, { 0, 0 } } } --# define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP \ -- { { 0, 0, 0, 0, PTHREAD_MUTEX_ERRORCHECK_NP, __PTHREAD_SPINS, { 0, 0 } } } --# define PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP \ -- { { 0, 0, 0, 0, PTHREAD_MUTEX_ADAPTIVE_NP, __PTHREAD_SPINS, { 0, 0 } } } --# define PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP \ -- { { 0, 0, 0, 0, PTHREAD_MUTEX_ADAPTIVE_NP, __PTHREAD_SPINS, { 0, 0 } } } -- --# endif --#else --# define PTHREAD_MUTEX_INITIALIZER \ -- { { 0, 0, 0, 0, 0, { __PTHREAD_SPINS } } } --# ifdef __USE_GNU --# define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP \ -- { { 0, 0, 0, PTHREAD_MUTEX_RECURSIVE_NP, 0, { __PTHREAD_SPINS } } } --# define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP \ -- { { 0, 0, 0, PTHREAD_MUTEX_ERRORCHECK_NP, 0, { __PTHREAD_SPINS } } } --# define PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP \ -- { { 0, 0, 0, PTHREAD_MUTEX_ADAPTIVE_NP, 0, { __PTHREAD_SPINS } } } -- --# endif -+#define PTHREAD_MUTEX_INITIALIZER \ -+ { { 0, 0, 0, 0, { 0, 0, 0, 0 }, 0, { __PTHREAD_SPINS }, 0, 0 } } -+#ifdef __USE_GNU -+# define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP \ -+ { { 0, 0, 0, PTHREAD_MUTEX_RECURSIVE_NP, { 0, 0, 0, 0 }, 0, \ -+ { __PTHREAD_SPINS }, 0, 0 } } -+# define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP \ -+ { { 0, 0, 0, PTHREAD_MUTEX_ERRORCHECK_NP, { 0, 0, 0, 0 }, 0, \ -+ { __PTHREAD_SPINS }, 0, 0 } } -+# define PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP \ -+ { { 0, 0, 0, PTHREAD_MUTEX_ADAPTIVE_NP, { 0, 0, 0, 0 }, 0, \ -+ { __PTHREAD_SPINS }, 0, 0 } } - #endif - - -@@ -130,25 +117,14 @@ enum - # endif - #endif - -+ - /* Read-write lock initializers. */ - # define PTHREAD_RWLOCK_INITIALIZER \ -- { { 0, 0, 0, 0, 0, 0, 0, 0, __PTHREAD_RWLOCK_ELISION_EXTRA, 0, 0 } } -+ { { { 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } - # ifdef __USE_GNU --# ifdef __PTHREAD_RWLOCK_INT_FLAGS_SHARED --# define PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP \ -- { { 0, 0, 0, 0, 0, 0, 0, 0, __PTHREAD_RWLOCK_ELISION_EXTRA, 0, \ -- PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP } } --# else --# if __BYTE_ORDER == __LITTLE_ENDIAN --# define PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP \ -- { { 0, 0, 0, 0, 0, 0, PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP, \ -- 0, __PTHREAD_RWLOCK_ELISION_EXTRA, 0, 0 } } --# else --# define PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP \ -- { { 0, 0, 0, 0, 0, 0, 0, 0, 0, PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP,\ -- 0 } } --# endif --# endif -+# define PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP \ -+ { { { 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ -+ PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP, 0, 0, 0 } } - # endif - #endif /* Unix98 or XOpen2K */ - -@@ -183,9 +159,8 @@ enum - }; - - -- - /* Conditional variable handling. */ --#define PTHREAD_COND_INITIALIZER { { 0, 0, 0, 0, 0, (void *) 0, 0, 0 } } -+#define PTHREAD_COND_INITIALIZER { { {0}, {0}, {0, 0}, {0, 0}, 0, 0, {0, 0} } } - - - /* Cleanup buffers */ -@@ -1161,43 +1136,3 @@ __NTH (pthread_equal (pthread_t __thread1, pthread_t __thread2)) - __END_DECLS - - #endif /* pthread.h */ -- --#ifndef _PTHREAD_H_HPPA_ --#define _PTHREAD_H_HPPA_ 1 -- --/* The pthread_cond_t initializer is compatible only with NPTL. We do not -- want to be forwards compatible, we eventually want to drop the code -- that has to clear the old LT initializer. */ --#undef PTHREAD_COND_INITIALIZER --#define PTHREAD_COND_INITIALIZER { { 0, 0, 0, (void *) 0, 0, 0, 0, 0, 0 } } -- --/* The pthread_mutex_t and pthread_rwlock_t initializers are compatible -- only with NPTL. NPTL assumes pthread_rwlock_t is all zero. */ --#undef PTHREAD_MUTEX_INITIALIZER --#undef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP --#undef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP --#undef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP --/* Mutex initializers. */ --#define PTHREAD_MUTEX_INITIALIZER \ -- { { 0, 0, 0, 0, { 0, 0, 0, 0 }, 0, { 0 }, 0, 0 } } --#ifdef __USE_GNU --# define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP \ -- { { 0, 0, 0, PTHREAD_MUTEX_RECURSIVE_NP, { 0, 0, 0, 0 }, 0, { 0 }, 0, 0 } } --# define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP \ -- { { 0, 0, 0, PTHREAD_MUTEX_ERRORCHECK_NP, { 0, 0, 0, 0 }, 0, { 0 }, 0, 0 } } --# define PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP \ -- { { 0, 0, 0, PTHREAD_MUTEX_ADAPTIVE_NP, { 0, 0, 0, 0 }, 0, { 0 }, 0, 0 } } --#endif -- --#undef PTHREAD_RWLOCK_INITIALIZER --#undef PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP --/* Read-write lock initializers. */ --#define PTHREAD_RWLOCK_INITIALIZER \ -- { { { 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } --#ifdef __USE_GNU --# define PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP \ -- { { { 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP,\ -- 0, 0, 0 } } --#endif /* Unix98 or XOpen2K */ -- --#endif -diff --git a/sysdeps/unix/sysv/linux/hppa/pthread_cond_broadcast.c b/sysdeps/unix/sysv/linux/hppa/pthread_cond_broadcast.c -deleted file mode 100644 -index a6f9f5d433..0000000000 ---- a/sysdeps/unix/sysv/linux/hppa/pthread_cond_broadcast.c -+++ /dev/null -@@ -1,40 +0,0 @@ --/* Copyright (C) 2009-2017 Free Software Foundation, Inc. -- This file is part of the GNU C Library. -- Contributed by Carlos O'Donell , 2009. -- -- 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 -- . */ -- --#ifndef INCLUDED_SELF --# define INCLUDED_SELF --# include --#else --# include --# include --# include --# include --int --__pthread_cond_broadcast (pthread_cond_t *cond) --{ -- cond_compat_check_and_clear (cond); -- return __pthread_cond_broadcast_internal (cond); --} --versioned_symbol (libpthread, __pthread_cond_broadcast, pthread_cond_broadcast, -- GLIBC_2_3_2); --# undef versioned_symbol --# define versioned_symbol(lib, local, symbol, version) --# undef __pthread_cond_broadcast --# define __pthread_cond_broadcast __pthread_cond_broadcast_internal --# include_next --#endif -diff --git a/sysdeps/unix/sysv/linux/hppa/pthread_cond_destroy.c b/sysdeps/unix/sysv/linux/hppa/pthread_cond_destroy.c -deleted file mode 100644 -index 49af087bb4..0000000000 ---- a/sysdeps/unix/sysv/linux/hppa/pthread_cond_destroy.c -+++ /dev/null -@@ -1,40 +0,0 @@ --/* Copyright (C) 2009-2017 Free Software Foundation, Inc. -- This file is part of the GNU C Library. -- Contributed by Carlos O'Donell , 2009. -- -- 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 -- . */ -- --#ifndef INCLUDED_SELF --# define INCLUDED_SELF --# include --#else --# include --# include --# include --# include --int --__pthread_cond_destroy (pthread_cond_t *cond) --{ -- cond_compat_check_and_clear (cond); -- return __pthread_cond_destroy_internal (cond); --} --versioned_symbol (libpthread, __pthread_cond_destroy, pthread_cond_destroy, -- GLIBC_2_3_2); --# undef versioned_symbol --# define versioned_symbol(lib, local, symbol, version) --# undef __pthread_cond_destroy --# define __pthread_cond_destroy __pthread_cond_destroy_internal --# include_next --#endif -diff --git a/sysdeps/unix/sysv/linux/hppa/pthread_cond_init.c b/sysdeps/unix/sysv/linux/hppa/pthread_cond_init.c -deleted file mode 100644 -index ccb3de07ff..0000000000 ---- a/sysdeps/unix/sysv/linux/hppa/pthread_cond_init.c -+++ /dev/null -@@ -1,40 +0,0 @@ --/* Copyright (C) 2009-2017 Free Software Foundation, Inc. -- This file is part of the GNU C Library. -- Contributed by Carlos O'Donell , 2009. -- -- 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 -- . */ -- --#ifndef INCLUDED_SELF --# define INCLUDED_SELF --# include --#else --# include --# include --# include --# include --int --__pthread_cond_init (pthread_cond_t *cond, const pthread_condattr_t *cond_attr) --{ -- cond_compat_clear (cond); -- return __pthread_cond_init_internal (cond, cond_attr); --} --versioned_symbol (libpthread, __pthread_cond_init, pthread_cond_init, -- GLIBC_2_3_2); --# undef versioned_symbol --# define versioned_symbol(lib, local, symbol, version) --# undef __pthread_cond_init --# define __pthread_cond_init __pthread_cond_init_internal --# include_next --#endif -diff --git a/sysdeps/unix/sysv/linux/hppa/pthread_cond_signal.c b/sysdeps/unix/sysv/linux/hppa/pthread_cond_signal.c -deleted file mode 100644 -index 2bf32af933..0000000000 ---- a/sysdeps/unix/sysv/linux/hppa/pthread_cond_signal.c -+++ /dev/null -@@ -1,40 +0,0 @@ --/* Copyright (C) 2009-2017 Free Software Foundation, Inc. -- This file is part of the GNU C Library. -- Contributed by Carlos O'Donell , 2009. -- -- 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 -- . */ -- --#ifndef INCLUDED_SELF --# define INCLUDED_SELF --# include --#else --# include --# include --# include --# include --int --__pthread_cond_signal (pthread_cond_t *cond) --{ -- cond_compat_check_and_clear (cond); -- return __pthread_cond_signal_internal (cond); --} --versioned_symbol (libpthread, __pthread_cond_signal, pthread_cond_signal, -- GLIBC_2_3_2); --# undef versioned_symbol --# define versioned_symbol(lib, local, symbol, version) --# undef __pthread_cond_signal --# define __pthread_cond_signal __pthread_cond_signal_internal --# include_next --#endif -diff --git a/sysdeps/unix/sysv/linux/hppa/pthread_cond_wait.c b/sysdeps/unix/sysv/linux/hppa/pthread_cond_wait.c -deleted file mode 100644 -index 1cc2fc15d4..0000000000 ---- a/sysdeps/unix/sysv/linux/hppa/pthread_cond_wait.c -+++ /dev/null -@@ -1,53 +0,0 @@ --/* Copyright (C) 2009-2017 Free Software Foundation, Inc. -- This file is part of the GNU C Library. -- Contributed by Carlos O'Donell , 2009. -- -- 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 -- . */ -- --#ifndef INCLUDED_SELF --# define INCLUDED_SELF --# include --#else --# include --# include --# include --# include --int --__pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex) --{ -- cond_compat_check_and_clear (cond); -- return __pthread_cond_wait_internal (cond, mutex); --} --versioned_symbol (libpthread, __pthread_cond_wait, pthread_cond_wait, -- GLIBC_2_3_2); --int --__pthread_cond_timedwait (cond, mutex, abstime) -- pthread_cond_t *cond; -- pthread_mutex_t *mutex; -- const struct timespec *abstime; --{ -- cond_compat_check_and_clear (cond); -- return __pthread_cond_timedwait_internal (cond, mutex, abstime); --} --versioned_symbol (libpthread, __pthread_cond_timedwait, pthread_cond_timedwait, -- GLIBC_2_3_2); --# undef versioned_symbol --# define versioned_symbol(lib, local, symbol, version) --# undef __pthread_cond_wait --# define __pthread_cond_wait __pthread_cond_wait_internal --# undef __pthread_cond_timedwait --# define __pthread_cond_timedwait __pthread_cond_timedwait_internal --# include_next --#endif -diff --git a/sysdeps/unix/sysv/linux/hppa/setcontext.S b/sysdeps/unix/sysv/linux/hppa/setcontext.S -index 3f4da7938f..92cb204f8d 100644 ---- a/sysdeps/unix/sysv/linux/hppa/setcontext.S -+++ b/sysdeps/unix/sysv/linux/hppa/setcontext.S -@@ -26,8 +26,11 @@ - ENTRY(__setcontext) - /* Prologue */ - stwm %r3, 64(%sp) -+ .cfi_def_cfa_offset -64 -+ .cfi_offset 3, 0 - #ifdef PIC - stw %r19, -32(%sp) -+ .cfi_offset 19, 32 - #endif - - /* Save ucp. */ -@@ -141,7 +144,7 @@ ENTRY(__setcontext) - - /* No further context available. Exit now. */ - bl HIDDEN_JUMPTARGET(exit), %r2 -- ldi -1, %r26 -+ ldi 0, %r26 - - - .Lerror: -diff --git a/sysdeps/unix/sysv/linux/hppa/sysdep-cancel.h b/sysdeps/unix/sysv/linux/hppa/sysdep-cancel.h -index 5ea297267f..8b7f2b2095 100644 ---- a/sysdeps/unix/sysv/linux/hppa/sysdep-cancel.h -+++ b/sysdeps/unix/sysv/linux/hppa/sysdep-cancel.h -@@ -62,12 +62,11 @@ - ENTRY (__##syscall_name##_nocancel) \ - DOARGS_##args ASM_LINE_SEP \ - stwm TREG, 64(%sp) ASM_LINE_SEP \ -+ .cfi_def_cfa_offset -64 ASM_LINE_SEP \ - .cfi_offset TREG, 0 ASM_LINE_SEP \ -- .cfi_adjust_cfa_offset 64 ASM_LINE_SEP \ - stw %sp, -4(%sp) ASM_LINE_SEP \ -- .cfi_offset 30, -4 ASM_LINE_SEP \ - stw %r19, -32(%sp) ASM_LINE_SEP \ -- .cfi_offset 19, -32 ASM_LINE_SEP \ -+ .cfi_offset 19, 32 ASM_LINE_SEP \ - /* Save r19 */ ASM_LINE_SEP \ - SAVE_PIC(TREG) ASM_LINE_SEP \ - /* Do syscall, delay loads # */ ASM_LINE_SEP \ -@@ -91,21 +90,19 @@ L(pre_nc_end): ASM_LINE_SEP \ - /* No need to LOAD_PIC */ ASM_LINE_SEP \ - /* Undo frame */ ASM_LINE_SEP \ - ldwm -64(%sp),TREG ASM_LINE_SEP \ -- .cfi_adjust_cfa_offset -64 ASM_LINE_SEP \ - /* Restore rp before exit */ ASM_LINE_SEP \ - ldw -20(%sp), %rp ASM_LINE_SEP \ -- .cfi_restore 2 ASM_LINE_SEP \ - ret ASM_LINE_SEP \ - END(__##syscall_name##_nocancel) ASM_LINE_SEP \ - /**********************************************/ASM_LINE_SEP \ - ENTRY (name) \ - DOARGS_##args ASM_LINE_SEP \ - stwm TREG, 64(%sp) ASM_LINE_SEP \ -- .cfi_adjust_cfa_offset 64 ASM_LINE_SEP \ -+ .cfi_def_cfa_offset -64 ASM_LINE_SEP \ -+ .cfi_offset TREG, 0 ASM_LINE_SEP \ - stw %sp, -4(%sp) ASM_LINE_SEP \ -- .cfi_offset 30, -4 ASM_LINE_SEP \ - stw %r19, -32(%sp) ASM_LINE_SEP \ -- .cfi_offset 19, -32 ASM_LINE_SEP \ -+ .cfi_offset 19, 32 ASM_LINE_SEP \ - /* Done setting up frame, continue... */ ASM_LINE_SEP \ - SINGLE_THREAD_P ASM_LINE_SEP \ - cmpib,<>,n 0,%ret0,L(pseudo_cancel) ASM_LINE_SEP \ -@@ -168,40 +165,32 @@ L(pre_end): ASM_LINE_SEP \ - /* No need to LOAD_PIC */ ASM_LINE_SEP \ - /* Undo frame */ ASM_LINE_SEP \ - ldwm -64(%sp),TREG ASM_LINE_SEP \ -- .cfi_adjust_cfa_offset -64 ASM_LINE_SEP \ - /* Restore rp before exit */ ASM_LINE_SEP \ -- ldw -20(%sp), %rp ASM_LINE_SEP \ -- .cfi_restore 2 ASM_LINE_SEP -+ ldw -20(%sp), %rp ASM_LINE_SEP - - /* Save arguments into our frame */ - # define PUSHARGS_0 /* nothing to do */ - # define PUSHARGS_1 PUSHARGS_0 stw %r26, -36(%sr0,%sp) ASM_LINE_SEP \ -- .cfi_offset 26, -36 ASM_LINE_SEP -+ .cfi_offset 26, 28 ASM_LINE_SEP - # define PUSHARGS_2 PUSHARGS_1 stw %r25, -40(%sr0,%sp) ASM_LINE_SEP \ -- .cfi_offset 25, -40 ASM_LINE_SEP -+ .cfi_offset 25, 24 ASM_LINE_SEP - # define PUSHARGS_3 PUSHARGS_2 stw %r24, -44(%sr0,%sp) ASM_LINE_SEP \ -- .cfi_offset 24, -44 ASM_LINE_SEP -+ .cfi_offset 24, 20 ASM_LINE_SEP - # define PUSHARGS_4 PUSHARGS_3 stw %r23, -48(%sr0,%sp) ASM_LINE_SEP \ -- .cfi_offset 23, -48 ASM_LINE_SEP -+ .cfi_offset 23, 16 ASM_LINE_SEP - # define PUSHARGS_5 PUSHARGS_4 stw %r22, -52(%sr0,%sp) ASM_LINE_SEP \ -- .cfi_offset 22, -52 ASM_LINE_SEP -+ .cfi_offset 22, 12 ASM_LINE_SEP - # define PUSHARGS_6 PUSHARGS_5 stw %r21, -56(%sr0,%sp) ASM_LINE_SEP \ -- .cfi_offset 21, -56 ASM_LINE_SEP -+ .cfi_offset 21, 8 ASM_LINE_SEP - - /* Bring them back from the stack */ - # define POPARGS_0 /* nothing to do */ --# define POPARGS_1 POPARGS_0 ldw -36(%sr0,%sp), %r26 ASM_LINE_SEP \ -- .cfi_restore 26 ASM_LINE_SEP --# define POPARGS_2 POPARGS_1 ldw -40(%sr0,%sp), %r25 ASM_LINE_SEP \ -- .cfi_restore 25 ASM_LINE_SEP --# define POPARGS_3 POPARGS_2 ldw -44(%sr0,%sp), %r24 ASM_LINE_SEP \ -- .cfi_restore 24 ASM_LINE_SEP --# define POPARGS_4 POPARGS_3 ldw -48(%sr0,%sp), %r23 ASM_LINE_SEP \ -- .cfi_restore 23 ASM_LINE_SEP --# define POPARGS_5 POPARGS_4 ldw -52(%sr0,%sp), %r22 ASM_LINE_SEP \ -- .cfi_restore 22 ASM_LINE_SEP --# define POPARGS_6 POPARGS_5 ldw -56(%sr0,%sp), %r21 ASM_LINE_SEP \ -- .cfi_restore 21 ASM_LINE_SEP -+# define POPARGS_1 POPARGS_0 ldw -36(%sr0,%sp), %r26 ASM_LINE_SEP -+# define POPARGS_2 POPARGS_1 ldw -40(%sr0,%sp), %r25 ASM_LINE_SEP -+# define POPARGS_3 POPARGS_2 ldw -44(%sr0,%sp), %r24 ASM_LINE_SEP -+# define POPARGS_4 POPARGS_3 ldw -48(%sr0,%sp), %r23 ASM_LINE_SEP -+# define POPARGS_5 POPARGS_4 ldw -52(%sr0,%sp), %r22 ASM_LINE_SEP -+# define POPARGS_6 POPARGS_5 ldw -56(%sr0,%sp), %r21 ASM_LINE_SEP - - # if IS_IN (libpthread) - # ifdef PIC -diff --git a/sysdeps/unix/sysv/linux/hppa/sysdep.h b/sysdeps/unix/sysv/linux/hppa/sysdep.h -index d8dd0431a4..c0cd59e9f5 100644 ---- a/sysdeps/unix/sysv/linux/hppa/sysdep.h -+++ b/sysdeps/unix/sysv/linux/hppa/sysdep.h -@@ -49,11 +49,9 @@ - to another function */ - #define TREG 4 - #define SAVE_PIC(SREG) \ -- copy %r19, SREG ASM_LINE_SEP \ -- .cfi_register 19, SREG -+ copy %r19, SREG - #define LOAD_PIC(LREG) \ -- copy LREG , %r19 ASM_LINE_SEP \ -- .cfi_restore 19 -+ copy LREG , %r19 - /* Inline assembly defines */ - #define TREG_ASM "%r4" /* Cant clobber r3, it holds framemarker */ - #define SAVE_ASM_PIC " copy %%r19, %" TREG_ASM "\n" -@@ -292,12 +290,11 @@ - #define DO_CALL(syscall_name, args) \ - /* Create a frame */ ASM_LINE_SEP \ - stwm TREG, 64(%sp) ASM_LINE_SEP \ -+ .cfi_def_cfa_offset -64 ASM_LINE_SEP \ - .cfi_offset TREG, 0 ASM_LINE_SEP \ -- .cfi_adjust_cfa_offset 64 ASM_LINE_SEP \ - stw %sp, -4(%sp) ASM_LINE_SEP \ -- .cfi_offset 30, -4 ASM_LINE_SEP \ - stw %r19, -32(%sp) ASM_LINE_SEP \ -- .cfi_offset 19, -32 ASM_LINE_SEP \ -+ .cfi_offset 19, 32 ASM_LINE_SEP \ - /* Save r19 */ ASM_LINE_SEP \ - SAVE_PIC(TREG) ASM_LINE_SEP \ - /* Do syscall, delay loads # */ ASM_LINE_SEP \ -@@ -320,10 +317,8 @@ - L(pre_end): ASM_LINE_SEP \ - /* Restore our frame, restoring TREG */ ASM_LINE_SEP \ - ldwm -64(%sp), TREG ASM_LINE_SEP \ -- .cfi_adjust_cfa_offset -64 ASM_LINE_SEP \ - /* Restore return pointer */ ASM_LINE_SEP \ -- ldw -20(%sp),%rp ASM_LINE_SEP \ -- .cfi_restore 2 ASM_LINE_SEP -+ ldw -20(%sp),%rp ASM_LINE_SEP - - /* We do nothing with the return, except hand it back to someone else */ - #undef DO_CALL_NOERRNO -diff --git a/sysdeps/unix/sysv/linux/i386/glob64.c b/sysdeps/unix/sysv/linux/i386/glob64.c -index f68195137e..230f9fc037 100644 ---- a/sysdeps/unix/sysv/linux/i386/glob64.c -+++ b/sysdeps/unix/sysv/linux/i386/glob64.c -@@ -19,6 +19,7 @@ - #include - #include - #include -+#include - - #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 - --#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 -- --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 -- --compat_symbol (libc, __old_glob64, glob64, GLIBC_2_1); --#endif -diff --git a/sysdeps/unix/sysv/linux/i386/localplt.data b/sysdeps/unix/sysv/linux/i386/localplt.data -index 2c2584956d..8ea4333846 100644 ---- a/sysdeps/unix/sysv/linux/i386/localplt.data -+++ b/sysdeps/unix/sysv/linux/i386/localplt.data -@@ -6,7 +6,7 @@ libc.so: free + REL R_386_GLOB_DAT - libc.so: malloc + REL R_386_GLOB_DAT - libc.so: memalign + REL R_386_GLOB_DAT - libc.so: realloc + REL R_386_GLOB_DAT --libm.so: matherr -+libm.so: matherr + REL R_386_GLOB_DAT - # The main malloc is interposed into the dynamic linker, for - # allocations after the initial link (when dlopen is used). - ld.so: malloc + REL R_386_GLOB_DAT -diff --git a/sysdeps/unix/sysv/linux/ia64/ipc_priv.h b/sysdeps/unix/sysv/linux/ia64/ipc_priv.h -new file mode 100644 -index 0000000000..e602eea455 ---- /dev/null -+++ b/sysdeps/unix/sysv/linux/ia64/ipc_priv.h -@@ -0,0 +1,21 @@ -+/* Old SysV permission definition for Linux. IA64 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 -+ . */ -+ -+#include /* For __key_t */ -+ -+#define __IPC_64 0x0 -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/posix_fadvise64.c b/sysdeps/unix/sysv/linux/mips/mips64/n64/posix_fadvise64.c -index 9776ee96e5..5a6379613b 100644 ---- a/sysdeps/unix/sysv/linux/mips/mips64/n64/posix_fadvise64.c -+++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/posix_fadvise64.c -@@ -29,5 +29,7 @@ - _strong_alias (__posix_fadvise64_l64, __posix_fadvise64_l32); - compat_symbol (libc, __posix_fadvise64_l32, posix_fadvise64, GLIBC_2_2); - versioned_symbol (libc, __posix_fadvise64_l64, posix_fadvise64, GLIBC_2_3_3); -+#else -+_weak_alias (posix_fadvise, posix_fadvise64); - #endif - _strong_alias (__posix_fadvise64_l64, posix_fadvise); -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 -+ -+#if SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_2) -+ -+#include -+#include -+#include -+ -+#include -+ -+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 -+ -+libc_hidden_def (__old_glob64); -+ -+compat_symbol (libc, __old_glob64, glob64, GLIBC_2_1); -+#endif -diff --git a/sysdeps/unix/sysv/linux/s390/pt-longjmp.c b/sysdeps/unix/sysv/linux/s390/pt-longjmp.c -index d324237edd..0221ac2cf5 100644 ---- a/sysdeps/unix/sysv/linux/s390/pt-longjmp.c -+++ b/sysdeps/unix/sysv/linux/s390/pt-longjmp.c -@@ -26,8 +26,8 @@ - /* In glibc release 2.19 new versions of longjmp-functions were introduced, - but were reverted before 2.20. Thus both versions are the same function. */ - --strong_alias (longjmp_ifunc, __v2longjmp) -+strong_alias (longjmp_alias, __v2longjmp) - compat_symbol (libpthread, __v2longjmp, longjmp, GLIBC_2_19); --strong_alias (siglongjmp_ifunc, __v2siglongjmp) -+strong_alias (siglongjmp_alias, __v2siglongjmp) - compat_symbol (libpthread, __v2siglongjmp, siglongjmp, GLIBC_2_19); - #endif /* SHLIB_COMPAT (libpthread, GLIBC_2_19, GLIBC_2_20)) */ -diff --git a/sysdeps/unix/sysv/linux/sparc/bits/long-double.h b/sysdeps/unix/sysv/linux/sparc/bits/long-double.h -deleted file mode 100644 -index 094e05124b..0000000000 ---- a/sysdeps/unix/sysv/linux/sparc/bits/long-double.h -+++ /dev/null -@@ -1,26 +0,0 @@ --/* Properties of long double type. SPARC version. -- Copyright (C) 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 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 -- . */ -- --#include -- --#if !defined __NO_LONG_DOUBLE_MATH && __WORDSIZE == 32 --# define __LONG_DOUBLE_MATH_OPTIONAL 1 --# ifndef __LONG_DOUBLE_128__ --# define __NO_LONG_DOUBLE_MATH 1 --# endif --#endif -diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/bits/long-double.h b/sysdeps/unix/sysv/linux/sparc/sparc32/bits/long-double.h -new file mode 100644 -index 0000000000..094e05124b ---- /dev/null -+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/bits/long-double.h -@@ -0,0 +1,26 @@ -+/* Properties of long double type. SPARC version. -+ Copyright (C) 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 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 -+ . */ -+ -+#include -+ -+#if !defined __NO_LONG_DOUBLE_MATH && __WORDSIZE == 32 -+# define __LONG_DOUBLE_MATH_OPTIONAL 1 -+# ifndef __LONG_DOUBLE_128__ -+# define __NO_LONG_DOUBLE_MATH 1 -+# endif -+#endif -diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/bits/long-double.h b/sysdeps/unix/sysv/linux/sparc/sparc64/bits/long-double.h -new file mode 100644 -index 0000000000..094e05124b ---- /dev/null -+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/bits/long-double.h -@@ -0,0 +1,26 @@ -+/* Properties of long double type. SPARC version. -+ Copyright (C) 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 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 -+ . */ -+ -+#include -+ -+#if !defined __NO_LONG_DOUBLE_MATH && __WORDSIZE == 32 -+# define __LONG_DOUBLE_MATH_OPTIONAL 1 -+# ifndef __LONG_DOUBLE_128__ -+# define __NO_LONG_DOUBLE_MATH 1 -+# endif -+#endif -diff --git a/sysdeps/unix/sysv/linux/spawni.c b/sysdeps/unix/sysv/linux/spawni.c -index 2daf0c5ef0..ee09fb762b 100644 ---- a/sysdeps/unix/sysv/linux/spawni.c -+++ b/sysdeps/unix/sysv/linux/spawni.c -@@ -17,7 +17,6 @@ - . */ - - #include --#include - #include - #include - #include -@@ -61,17 +60,18 @@ - #define SPAWN_ERROR 127 - - #ifdef __ia64__ --# define CLONE(__fn, __stack, __stacksize, __flags, __args) \ -- __clone2 (__fn, __stack, __stacksize, __flags, __args, 0, 0, 0) -+# define CLONE(__fn, __stackbase, __stacksize, __flags, __args) \ -+ __clone2 (__fn, __stackbase, __stacksize, __flags, __args, 0, 0, 0) - #else - # define CLONE(__fn, __stack, __stacksize, __flags, __args) \ - __clone (__fn, __stack, __flags, __args) - #endif - --#if _STACK_GROWS_DOWN --# define STACK(__stack, __stack_size) (__stack + __stack_size) --#elif _STACK_GROWS_UP -+/* Since ia64 wants the stackbase w/clone2, re-use the grows-up macro. */ -+#if _STACK_GROWS_UP || defined (__ia64__) - # define STACK(__stack, __stack_size) (__stack) -+#elif _STACK_GROWS_DOWN -+# define STACK(__stack, __stack_size) (__stack + __stack_size) - #endif - - -@@ -265,7 +265,6 @@ __spawni_child (void *arguments) - __sigprocmask (SIG_SETMASK, (attr->__flags & POSIX_SPAWN_SETSIGMASK) - ? &attr->__ss : &args->oldmask, 0); - -- args->err = 0; - args->exec (args->file, args->argv, args->envp); - - /* This is compatibility function required to enable posix_spawn run -@@ -318,6 +317,11 @@ __spawnix (pid_t * pid, const char *file, - - /* Add a slack area for child's stack. */ - size_t argv_size = (argc * sizeof (void *)) + 512; -+ /* We need at least a few pages in case the compiler's stack checking is -+ enabled. In some configs, it is known to use at least 24KiB. We use -+ 32KiB to be "safe" from anything the compiler might do. Besides, the -+ extra pages won't actually be allocated unless they get used. */ -+ argv_size += (32 * 1024); - size_t stack_size = ALIGN_UP (argv_size, GLRO(dl_pagesize)); - void *stack = __mmap (NULL, stack_size, prot, - MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0); -@@ -331,7 +335,7 @@ __spawnix (pid_t * pid, const char *file, - - /* Child must set args.err to something non-negative - we rely on - the parent and child sharing VM. */ -- args.err = -1; -+ args.err = 0; - args.file = file; - args.exec = exec; - args.fa = file_actions; -@@ -354,12 +358,26 @@ __spawnix (pid_t * pid, const char *file, - new_pid = CLONE (__spawni_child, STACK (stack, stack_size), stack_size, - CLONE_VM | CLONE_VFORK | SIGCHLD, &args); - -+ /* It needs to collect the case where the auxiliary process was created -+ but failed to execute the file (due either any preparation step or -+ for execve itself). */ - if (new_pid > 0) - { -+ /* Also, it handles the unlikely case where the auxiliary process was -+ terminated before calling execve as if it was successfully. The -+ args.err is set to 0 as default and changed to a positive value -+ only in case of failure, so in case of premature termination -+ due a signal args.err will remain zeroed and it will be up to -+ caller to actually collect it. */ - ec = args.err; -- assert (ec >= 0); -- if (ec != 0) -- __waitpid (new_pid, NULL, 0); -+ if (ec > 0) -+ /* There still an unlikely case where the child is cancelled after -+ setting args.err, due to a positive error value. Also there is -+ possible pid reuse race (where the kernel allocated the same pid -+ to an unrelated process). Unfortunately due synchronization -+ issues where the kernel might not have the process collected -+ the waitpid below can not use WNOHANG. */ -+ __waitpid (new_pid, NULL, 0); - } - else - ec = -new_pid; -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 -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 -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 -+#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 -+++ b/sysdeps/x86/cpu-features-offsets.sym -@@ -15,6 +15,7 @@ CPUID_ECX_OFFSET offsetof (struct cpuid_registers, ecx) - CPUID_EDX_OFFSET offsetof (struct cpuid_registers, edx) - FAMILY_OFFSET offsetof (struct cpu_features, family) - MODEL_OFFSET offsetof (struct cpu_features, model) -+XSAVE_STATE_SIZE_OFFSET offsetof (struct cpu_features, xsave_state_size) - FEATURE_OFFSET offsetof (struct cpu_features, feature) - FEATURE_SIZE sizeof (unsigned int) - -diff --git a/sysdeps/x86/cpu-features.c b/sysdeps/x86/cpu-features.c -index 1c714a4017..38012912be 100644 ---- a/sysdeps/x86/cpu-features.c -+++ b/sysdeps/x86/cpu-features.c -@@ -18,6 +18,7 @@ - - #include - #include -+#include - - static void - get_common_indeces (struct cpu_features *cpu_features, -@@ -93,6 +94,71 @@ get_common_indeces (struct cpu_features *cpu_features, - } - } - } -+ -+ /* For _dl_runtime_resolve, set xsave_state_size to xsave area -+ size + integer register save size and align it to 64 bytes. */ -+ if (cpu_features->max_cpuid >= 0xd) -+ { -+ unsigned int eax, ebx, ecx, edx; -+ -+ __cpuid_count (0xd, 0, eax, ebx, ecx, edx); -+ if (ebx != 0) -+ { -+ cpu_features->xsave_state_size -+ = ALIGN_UP (ebx + STATE_SAVE_OFFSET, 64); -+ -+ __cpuid_count (0xd, 1, eax, ebx, ecx, edx); -+ -+ /* Check if XSAVEC is available. */ -+ if ((eax & (1 << 1)) != 0) -+ { -+ unsigned int xstate_comp_offsets[32]; -+ unsigned int xstate_comp_sizes[32]; -+ unsigned int i; -+ -+ xstate_comp_offsets[0] = 0; -+ xstate_comp_offsets[1] = 160; -+ xstate_comp_offsets[2] = 576; -+ xstate_comp_sizes[0] = 160; -+ xstate_comp_sizes[1] = 256; -+ -+ for (i = 2; i < 32; i++) -+ { -+ if ((STATE_SAVE_MASK & (1 << i)) != 0) -+ { -+ __cpuid_count (0xd, i, eax, ebx, ecx, edx); -+ xstate_comp_sizes[i] = eax; -+ } -+ else -+ { -+ ecx = 0; -+ xstate_comp_sizes[i] = 0; -+ } -+ -+ if (i > 2) -+ { -+ xstate_comp_offsets[i] -+ = (xstate_comp_offsets[i - 1] -+ + xstate_comp_sizes[i -1]); -+ if ((ecx & (1 << 1)) != 0) -+ xstate_comp_offsets[i] -+ = ALIGN_UP (xstate_comp_offsets[i], 64); -+ } -+ } -+ -+ /* Use XSAVEC. */ -+ unsigned int size -+ = xstate_comp_offsets[31] + xstate_comp_sizes[31]; -+ if (size) -+ { -+ cpu_features->xsave_state_size -+ = ALIGN_UP (size + STATE_SAVE_OFFSET, 64); -+ cpu_features->feature[index_arch_XSAVEC_Usable] -+ |= bit_arch_XSAVEC_Usable; -+ } -+ } -+ } -+ } - } - } - -@@ -139,8 +205,6 @@ init_cpu_features (struct cpu_features *cpu_features) - - case 0x57: - /* Knights Landing. Enable Silvermont optimizations. */ -- cpu_features->feature[index_arch_Prefer_No_VZEROUPPER] -- |= bit_arch_Prefer_No_VZEROUPPER; - - case 0x5c: - case 0x5f: -@@ -226,19 +290,15 @@ init_cpu_features (struct cpu_features *cpu_features) - cpu_features->feature[index_arch_AVX_Fast_Unaligned_Load] - |= bit_arch_AVX_Fast_Unaligned_Load; - -- /* To avoid SSE transition penalty, use _dl_runtime_resolve_slow. -- If XGETBV suports ECX == 1, use _dl_runtime_resolve_opt. */ -- cpu_features->feature[index_arch_Use_dl_runtime_resolve_slow] -- |= bit_arch_Use_dl_runtime_resolve_slow; -- if (cpu_features->max_cpuid >= 0xd) -- { -- unsigned int eax; -- -- __cpuid_count (0xd, 1, eax, ebx, ecx, edx); -- if ((eax & (1 << 2)) != 0) -- cpu_features->feature[index_arch_Use_dl_runtime_resolve_opt] -- |= bit_arch_Use_dl_runtime_resolve_opt; -- } -+ /* Since AVX512ER is unique to Xeon Phi, set Prefer_No_VZEROUPPER -+ if AVX512ER is available. Don't use AVX512 to avoid lower CPU -+ frequency if AVX512ER isn't available. */ -+ if (CPU_FEATURES_CPU_P (cpu_features, AVX512ER)) -+ cpu_features->feature[index_arch_Prefer_No_VZEROUPPER] -+ |= bit_arch_Prefer_No_VZEROUPPER; -+ else -+ cpu_features->feature[index_arch_Prefer_No_AVX512] -+ |= bit_arch_Prefer_No_AVX512; - } - /* This spells out "AuthenticAMD". */ - else if (ebx == 0x68747541 && ecx == 0x444d4163 && edx == 0x69746e65) -diff --git a/sysdeps/x86/cpu-features.h b/sysdeps/x86/cpu-features.h -index 95f0fcff87..af83a28512 100644 ---- a/sysdeps/x86/cpu-features.h -+++ b/sysdeps/x86/cpu-features.h -@@ -37,8 +37,8 @@ - #define bit_arch_Prefer_No_VZEROUPPER (1 << 17) - #define bit_arch_Fast_Unaligned_Copy (1 << 18) - #define bit_arch_Prefer_ERMS (1 << 19) --#define bit_arch_Use_dl_runtime_resolve_opt (1 << 20) --#define bit_arch_Use_dl_runtime_resolve_slow (1 << 21) -+#define bit_arch_Prefer_No_AVX512 (1 << 20) -+#define bit_arch_XSAVEC_Usable (1 << 21) - - /* CPUID Feature flags. */ - -@@ -62,6 +62,11 @@ - #define bit_cpu_AVX2 (1 << 5) - #define bit_cpu_AVX512F (1 << 16) - #define bit_cpu_AVX512DQ (1 << 17) -+#define bit_cpu_AVX512PF (1 << 26) -+#define bit_cpu_AVX512ER (1 << 27) -+#define bit_cpu_AVX512CD (1 << 28) -+#define bit_cpu_AVX512BW (1 << 30) -+#define bit_cpu_AVX512VL (1u << 31) - - /* XCR0 Feature flags. */ - #define bit_XMM_state (1 << 1) -@@ -76,6 +81,15 @@ - /* The current maximum size of the feature integer bit array. */ - #define FEATURE_INDEX_MAX 1 - -+/* Offset for fxsave/xsave area used by _dl_runtime_resolve. Also need -+ space to preserve RCX, RDX, RSI, RDI, R8, R9 and RAX. It must be -+ aligned to 16 bytes for fxsave and 64 bytes for xsave. */ -+#define STATE_SAVE_OFFSET (8 * 7 + 8) -+ -+/* Save SSE, AVX, AVX512, mask and bound registers. */ -+#define STATE_SAVE_MASK \ -+ ((1 << 1) | (1 << 2) | (1 << 3) | (1 << 5) | (1 << 6) | (1 << 7)) -+ - #ifdef __ASSEMBLER__ - - # include -@@ -111,6 +125,7 @@ - # define index_arch_Prefer_ERMS FEATURE_INDEX_1*FEATURE_SIZE - # define index_arch_Use_dl_runtime_resolve_opt FEATURE_INDEX_1*FEATURE_SIZE - # define index_arch_Use_dl_runtime_resolve_slow FEATURE_INDEX_1*FEATURE_SIZE -+# define index_arch_Prefer_No_AVX512 FEATURE_INDEX_1*FEATURE_SIZE - - - # if defined (_LIBC) && !IS_IN (nonlib) -@@ -199,6 +214,12 @@ struct cpu_features - } cpuid[COMMON_CPUID_INDEX_MAX]; - unsigned int family; - unsigned int model; -+ /* The type must be unsigned long int so that we use -+ -+ sub xsave_state_size_offset(%rip) %RSP_LP -+ -+ in _dl_runtime_resolve. */ -+ unsigned long int xsave_state_size; - unsigned int feature[FEATURE_INDEX_MAX]; - }; - -@@ -236,6 +257,11 @@ extern const struct cpu_features *__get_cpu_features (void) - # define index_cpu_AVX2 COMMON_CPUID_INDEX_7 - # define index_cpu_AVX512F COMMON_CPUID_INDEX_7 - # define index_cpu_AVX512DQ COMMON_CPUID_INDEX_7 -+# define index_cpu_AVX512PF COMMON_CPUID_INDEX_7 -+# define index_cpu_AVX512ER COMMON_CPUID_INDEX_7 -+# define index_cpu_AVX512CD COMMON_CPUID_INDEX_7 -+# define index_cpu_AVX512BW COMMON_CPUID_INDEX_7 -+# define index_cpu_AVX512VL COMMON_CPUID_INDEX_7 - # define index_cpu_ERMS COMMON_CPUID_INDEX_7 - # define index_cpu_RTM COMMON_CPUID_INDEX_7 - # define index_cpu_FMA COMMON_CPUID_INDEX_1 -@@ -254,6 +280,11 @@ extern const struct cpu_features *__get_cpu_features (void) - # define reg_AVX2 ebx - # define reg_AVX512F ebx - # define reg_AVX512DQ ebx -+# define reg_AVX512PF ebx -+# define reg_AVX512ER ebx -+# define reg_AVX512CD ebx -+# define reg_AVX512BW ebx -+# define reg_AVX512VL ebx - # define reg_ERMS ebx - # define reg_RTM ebx - # define reg_FMA ecx -@@ -281,8 +312,8 @@ extern const struct cpu_features *__get_cpu_features (void) - # define index_arch_Prefer_No_VZEROUPPER FEATURE_INDEX_1 - # define index_arch_Fast_Unaligned_Copy FEATURE_INDEX_1 - # define index_arch_Prefer_ERMS FEATURE_INDEX_1 --# define index_arch_Use_dl_runtime_resolve_opt FEATURE_INDEX_1 --# define index_arch_Use_dl_runtime_resolve_slow FEATURE_INDEX_1 -+# define index_arch_Prefer_No_AVX512 FEATURE_INDEX_1 -+# define index_arch_XSAVEC_Usable FEATURE_INDEX_1 - - #endif /* !__ASSEMBLER__ */ - -diff --git a/sysdeps/x86/fpu/test-math-vector-sincos.h b/sysdeps/x86/fpu/test-math-vector-sincos.h -index 5043b32563..95282a3ac7 100644 ---- a/sysdeps/x86/fpu/test-math-vector-sincos.h -+++ b/sysdeps/x86/fpu/test-math-vector-sincos.h -@@ -17,14 +17,14 @@ - License along with the GNU C Library; if not, see - . */ - --#define INIT_VEC_PTRS_LOOP(vec, val, len) \ -- do \ -- { \ -- for (i = 0; i < len; i++) \ -- { \ -- vec[i] = &val[i]; \ -- } \ -- } \ -+#define INIT_VEC_PTRS_LOOP(vec, val, len) \ -+ do \ -+ { \ -+ union { VEC_INT_TYPE v; __typeof__ ((val)[0]) *a[(len)]; } u; \ -+ for (i = 0; i < len; i++) \ -+ u.a[i] = &(val)[i]; \ -+ (vec) = u.v; \ -+ } \ - while (0) - - /* Wrapper for vector sincos/sincosf compatible with x86_64 and x32 variants -@@ -40,8 +40,8 @@ void scalar_func (FLOAT x, FLOAT * r, FLOAT * r1) \ - VEC_TYPE mx; \ - VEC_INT_TYPE mr, mr1; \ - INIT_VEC_LOOP (mx, x, VEC_LEN); \ -- INIT_VEC_PTRS_LOOP (((FLOAT **) &mr), r_loc, VEC_LEN); \ -- INIT_VEC_PTRS_LOOP (((FLOAT **) &mr1), r1_loc, VEC_LEN); \ -+ INIT_VEC_PTRS_LOOP (mr, r_loc, VEC_LEN); \ -+ INIT_VEC_PTRS_LOOP (mr1, r1_loc, VEC_LEN); \ - vector_func (mx, mr, mr1); \ - TEST_VEC_LOOP (r_loc, VEC_LEN); \ - TEST_VEC_LOOP (r1_loc, VEC_LEN); \ -@@ -63,8 +63,8 @@ void scalar_func (FLOAT x, FLOAT * r, FLOAT * r1) \ - VEC_TYPE mx; \ - VEC_INT_TYPE mr, mr1; \ - INIT_VEC_LOOP (mx, x, VEC_LEN); \ -- INIT_VEC_PTRS_LOOP (((FLOAT **) &mr), r_loc, VEC_LEN/2); \ -- INIT_VEC_PTRS_LOOP (((FLOAT **) &mr1), r1_loc, VEC_LEN/2); \ -+ INIT_VEC_PTRS_LOOP (mr, r_loc, VEC_LEN/2); \ -+ INIT_VEC_PTRS_LOOP (mr1, r1_loc, VEC_LEN/2); \ - vector_func (mx, mr, mr, mr1, mr1); \ - TEST_VEC_LOOP (r_loc, VEC_LEN/2); \ - TEST_VEC_LOOP (r1_loc, VEC_LEN/2); \ -@@ -87,8 +87,8 @@ void scalar_func (FLOAT x, FLOAT * r, FLOAT * r1) \ - VEC_TYPE mx; \ - VEC_INT_TYPE mr, mr1; \ - INIT_VEC_LOOP (mx, x, VEC_LEN); \ -- INIT_VEC_PTRS_LOOP (((FLOAT **) &mr), r_loc, VEC_LEN/4); \ -- INIT_VEC_PTRS_LOOP (((FLOAT **) &mr1), r1_loc, VEC_LEN/4); \ -+ INIT_VEC_PTRS_LOOP (mr, r_loc, VEC_LEN/4); \ -+ INIT_VEC_PTRS_LOOP (mr1, r1_loc, VEC_LEN/4); \ - vector_func (mx, mr, mr, mr, mr, mr1, mr1, mr1, mr1); \ - TEST_VEC_LOOP (r_loc, VEC_LEN/4); \ - TEST_VEC_LOOP (r1_loc, VEC_LEN/4); \ -diff --git a/sysdeps/x86_64/Makefile b/sysdeps/x86_64/Makefile -index 5f25893dc9..132470d9cb 100644 ---- a/sysdeps/x86_64/Makefile -+++ b/sysdeps/x86_64/Makefile -@@ -27,7 +27,7 @@ ifeq ($(subdir),elf) - CFLAGS-.os += $(if $(filter $(@F),$(patsubst %,%.os,$(all-rtld-routines))),\ - -mno-mmx) - --sysdep-dl-routines += tlsdesc dl-tlsdesc -+sysdep-dl-routines += tlsdesc dl-tlsdesc tls_get_addr - - tests += ifuncmain8 - modules-names += ifuncmod8 -@@ -52,9 +52,12 @@ $(objpfx)tst-quad2pie: $(objpfx)tst-quadmod2pie.o - CFLAGS-tst-quad1pie.c = $(PIE-ccflag) - CFLAGS-tst-quad2pie.c = $(PIE-ccflag) - --tests += tst-audit3 tst-audit4 tst-audit5 tst-audit6 tst-audit7 tst-audit10 --test-extras += tst-audit4-aux tst-audit10-aux --extra-test-objs += tst-audit4-aux.o tst-audit10-aux.o -+tests += tst-audit3 tst-audit4 tst-audit5 tst-audit6 tst-audit7 \ -+ tst-audit10 tst-sse tst-avx tst-avx512 -+test-extras += tst-audit4-aux tst-audit10-aux \ -+ tst-avx-aux tst-avx512-aux -+extra-test-objs += tst-audit4-aux.o tst-audit10-aux.o \ -+ tst-avx-aux.o tst-avx512-aux.o - - tests += tst-split-dynreloc - LDFLAGS-tst-split-dynreloc = -Wl,-T,$(..)sysdeps/x86_64/tst-split-dynreloc.lds -@@ -65,7 +68,8 @@ modules-names += tst-auditmod3a tst-auditmod3b \ - tst-auditmod5a tst-auditmod5b \ - tst-auditmod6a tst-auditmod6b tst-auditmod6c \ - tst-auditmod7a tst-auditmod7b \ -- tst-auditmod10a tst-auditmod10b -+ tst-auditmod10a tst-auditmod10b \ -+ tst-ssemod tst-avxmod tst-avx512mod - - $(objpfx)tst-audit3: $(objpfx)tst-auditmod3a.so - $(objpfx)tst-audit3.out: $(objpfx)tst-auditmod3b.so -@@ -92,6 +96,10 @@ $(objpfx)tst-audit10: $(objpfx)tst-audit10-aux.o $(objpfx)tst-auditmod10a.so - $(objpfx)tst-audit10.out: $(objpfx)tst-auditmod10b.so - tst-audit10-ENV = LD_AUDIT=$(objpfx)tst-auditmod10b.so - -+$(objpfx)tst-sse: $(objpfx)tst-ssemod.so -+$(objpfx)tst-avx: $(objpfx)tst-avx-aux.o $(objpfx)tst-avxmod.so -+$(objpfx)tst-avx512: $(objpfx)tst-avx512-aux.o $(objpfx)tst-avx512mod.so -+ - AVX-CFLAGS=-mavx -mno-vzeroupper - CFLAGS-tst-audit4-aux.c += $(AVX-CFLAGS) - CFLAGS-tst-auditmod4a.c += $(AVX-CFLAGS) -@@ -99,14 +107,18 @@ CFLAGS-tst-auditmod4b.c += $(AVX-CFLAGS) - CFLAGS-tst-auditmod6b.c += $(AVX-CFLAGS) - CFLAGS-tst-auditmod6c.c += $(AVX-CFLAGS) - CFLAGS-tst-auditmod7b.c += $(AVX-CFLAGS) -+CFLAGS-tst-avx-aux.c += $(AVX-CFLAGS) -+CFLAGS-tst-avxmod.c += $(AVX-CFLAGS) - ifeq (yes,$(config-cflags-avx512)) - AVX512-CFLAGS = -mavx512f - CFLAGS-tst-audit10-aux.c += $(AVX512-CFLAGS) - CFLAGS-tst-auditmod10a.c += $(AVX512-CFLAGS) - CFLAGS-tst-auditmod10b.c += $(AVX512-CFLAGS) -+CFLAGS-tst-avx512-aux.c += $(AVX512-CFLAGS) -+CFLAGS-tst-avx512mod.c += $(AVX512-CFLAGS) - endif - endif - - ifeq ($(subdir),csu) --gen-as-const-headers += tlsdesc.sym -+gen-as-const-headers += tlsdesc.sym rtld-offsets.sym - endif -diff --git a/sysdeps/x86_64/dl-machine.h b/sysdeps/x86_64/dl-machine.h -index daf4d8c070..be0b8616ea 100644 ---- a/sysdeps/x86_64/dl-machine.h -+++ b/sysdeps/x86_64/dl-machine.h -@@ -66,12 +66,9 @@ static inline int __attribute__ ((unused, always_inline)) - elf_machine_runtime_setup (struct link_map *l, int lazy, int profile) - { - Elf64_Addr *got; -- extern void _dl_runtime_resolve_sse (ElfW(Word)) attribute_hidden; -- extern void _dl_runtime_resolve_avx (ElfW(Word)) attribute_hidden; -- extern void _dl_runtime_resolve_avx_slow (ElfW(Word)) attribute_hidden; -- extern void _dl_runtime_resolve_avx_opt (ElfW(Word)) attribute_hidden; -- extern void _dl_runtime_resolve_avx512 (ElfW(Word)) attribute_hidden; -- extern void _dl_runtime_resolve_avx512_opt (ElfW(Word)) attribute_hidden; -+ extern void _dl_runtime_resolve_fxsave (ElfW(Word)) attribute_hidden; -+ extern void _dl_runtime_resolve_xsave (ElfW(Word)) attribute_hidden; -+ extern void _dl_runtime_resolve_xsavec (ElfW(Word)) attribute_hidden; - extern void _dl_runtime_profile_sse (ElfW(Word)) attribute_hidden; - extern void _dl_runtime_profile_avx (ElfW(Word)) attribute_hidden; - extern void _dl_runtime_profile_avx512 (ElfW(Word)) attribute_hidden; -@@ -120,29 +117,14 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile) - /* This function will get called to fix up the GOT entry - indicated by the offset on the stack, and then jump to - the resolved address. */ -- if (HAS_ARCH_FEATURE (AVX512F_Usable)) -- { -- if (HAS_ARCH_FEATURE (Use_dl_runtime_resolve_opt)) -- *(ElfW(Addr) *) (got + 2) -- = (ElfW(Addr)) &_dl_runtime_resolve_avx512_opt; -- else -- *(ElfW(Addr) *) (got + 2) -- = (ElfW(Addr)) &_dl_runtime_resolve_avx512; -- } -- else if (HAS_ARCH_FEATURE (AVX_Usable)) -- { -- if (HAS_ARCH_FEATURE (Use_dl_runtime_resolve_opt)) -- *(ElfW(Addr) *) (got + 2) -- = (ElfW(Addr)) &_dl_runtime_resolve_avx_opt; -- else if (HAS_ARCH_FEATURE (Use_dl_runtime_resolve_slow)) -- *(ElfW(Addr) *) (got + 2) -- = (ElfW(Addr)) &_dl_runtime_resolve_avx_slow; -- else -- *(ElfW(Addr) *) (got + 2) -- = (ElfW(Addr)) &_dl_runtime_resolve_avx; -- } -+ if (GLRO(dl_x86_cpu_features).xsave_state_size != 0) -+ *(ElfW(Addr) *) (got + 2) -+ = (HAS_ARCH_FEATURE (XSAVEC_Usable) -+ ? (ElfW(Addr)) &_dl_runtime_resolve_xsavec -+ : (ElfW(Addr)) &_dl_runtime_resolve_xsave); - else -- *(ElfW(Addr) *) (got + 2) = (ElfW(Addr)) &_dl_runtime_resolve_sse; -+ *(ElfW(Addr) *) (got + 2) -+ = (ElfW(Addr)) &_dl_runtime_resolve_fxsave; - } - } - -diff --git a/sysdeps/x86_64/dl-tls.c b/sysdeps/x86_64/dl-tls.c -new file mode 100644 -index 0000000000..3584805c8e ---- /dev/null -+++ b/sysdeps/x86_64/dl-tls.c -@@ -0,0 +1,53 @@ -+/* Thread-local storage handling in the ELF dynamic linker. x86-64 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 -+ . */ -+ -+#ifdef SHARED -+/* Work around GCC PR58066, due to which __tls_get_addr may be called -+ with an unaligned stack. The compat implementation is in -+ tls_get_addr-compat.S. */ -+ -+# include -+ -+/* Define __tls_get_addr within elf/dl-tls.c under a different -+ name. */ -+extern __typeof__ (__tls_get_addr) ___tls_get_addr; -+ -+# define __tls_get_addr ___tls_get_addr -+# include -+# undef __tls_get_addr -+ -+hidden_ver (___tls_get_addr, __tls_get_addr) -+ -+/* Only handle slow paths for __tls_get_addr. */ -+attribute_hidden -+void * -+__tls_get_addr_slow (GET_ADDR_ARGS) -+{ -+ dtv_t *dtv = THREAD_DTV (); -+ -+ if (__glibc_unlikely (dtv[0].counter != GL(dl_tls_generation))) -+ return update_get_addr (GET_ADDR_PARAM); -+ -+ return tls_get_addr_tail (GET_ADDR_PARAM, dtv, NULL); -+} -+#else -+ -+/* No compatibility symbol needed. */ -+# include -+ -+#endif -diff --git a/sysdeps/x86_64/dl-tls.h b/sysdeps/x86_64/dl-tls.h -index 4a59d2a924..c2fb56c0a1 100644 ---- a/sysdeps/x86_64/dl-tls.h -+++ b/sysdeps/x86_64/dl-tls.h -@@ -16,6 +16,9 @@ - License along with the GNU C Library; if not, see - . */ - -+#ifndef _X86_64_DL_TLS_H -+#define _X86_64_DL_TLS_H -+ - #include - - /* Type used for the representation of TLS information in the GOT. */ -@@ -27,3 +30,5 @@ typedef struct dl_tls_index - - - extern void *__tls_get_addr (tls_index *ti); -+ -+#endif /* _X86_64_DL_TLS_H */ -diff --git a/sysdeps/x86_64/dl-trampoline.S b/sysdeps/x86_64/dl-trampoline.S -index 33d7fcf7d0..a645572e44 100644 ---- a/sysdeps/x86_64/dl-trampoline.S -+++ b/sysdeps/x86_64/dl-trampoline.S -@@ -34,41 +34,24 @@ - # define DL_STACK_ALIGNMENT 8 - #endif - --#ifndef DL_RUNTIME_UNALIGNED_VEC_SIZE --/* The maximum size in bytes of unaligned vector load and store in the -- dynamic linker. Since SSE optimized memory/string functions with -- aligned SSE register load and store are used in the dynamic linker, -- we must set this to 8 so that _dl_runtime_resolve_sse will align the -- stack before calling _dl_fixup. */ --# define DL_RUNTIME_UNALIGNED_VEC_SIZE 8 --#endif -- --/* True if _dl_runtime_resolve should align stack to VEC_SIZE bytes. */ -+/* True if _dl_runtime_resolve should align stack for STATE_SAVE or align -+ stack to 16 bytes before calling _dl_fixup. */ - #define DL_RUNTIME_RESOLVE_REALIGN_STACK \ -- (VEC_SIZE > DL_STACK_ALIGNMENT \ -- && VEC_SIZE > DL_RUNTIME_UNALIGNED_VEC_SIZE) -- --/* Align vector register save area to 16 bytes. */ --#define REGISTER_SAVE_VEC_OFF 0 -+ (STATE_SAVE_ALIGNMENT > DL_STACK_ALIGNMENT \ -+ || 16 > DL_STACK_ALIGNMENT) - - /* Area on stack to save and restore registers used for parameter - passing when calling _dl_fixup. */ - #ifdef __ILP32__ --# define REGISTER_SAVE_RAX (REGISTER_SAVE_VEC_OFF + VEC_SIZE * 8) - # define PRESERVE_BND_REGS_PREFIX - #else --/* Align bound register save area to 16 bytes. */ --# define REGISTER_SAVE_BND0 (REGISTER_SAVE_VEC_OFF + VEC_SIZE * 8) --# define REGISTER_SAVE_BND1 (REGISTER_SAVE_BND0 + 16) --# define REGISTER_SAVE_BND2 (REGISTER_SAVE_BND1 + 16) --# define REGISTER_SAVE_BND3 (REGISTER_SAVE_BND2 + 16) --# define REGISTER_SAVE_RAX (REGISTER_SAVE_BND3 + 16) - # ifdef HAVE_MPX_SUPPORT - # define PRESERVE_BND_REGS_PREFIX bnd - # else - # define PRESERVE_BND_REGS_PREFIX .byte 0xf2 - # endif - #endif -+#define REGISTER_SAVE_RAX 0 - #define REGISTER_SAVE_RCX (REGISTER_SAVE_RAX + 8) - #define REGISTER_SAVE_RDX (REGISTER_SAVE_RCX + 8) - #define REGISTER_SAVE_RSI (REGISTER_SAVE_RDX + 8) -@@ -80,69 +63,56 @@ - - #define VEC_SIZE 64 - #define VMOVA vmovdqa64 --#if DL_RUNTIME_RESOLVE_REALIGN_STACK || VEC_SIZE <= DL_STACK_ALIGNMENT --# define VMOV vmovdqa64 --#else --# define VMOV vmovdqu64 --#endif - #define VEC(i) zmm##i --#define _dl_runtime_resolve _dl_runtime_resolve_avx512 --#define _dl_runtime_resolve_opt _dl_runtime_resolve_avx512_opt - #define _dl_runtime_profile _dl_runtime_profile_avx512 - #include "dl-trampoline.h" --#undef _dl_runtime_resolve --#undef _dl_runtime_resolve_opt - #undef _dl_runtime_profile - #undef VEC --#undef VMOV - #undef VMOVA - #undef VEC_SIZE - - #define VEC_SIZE 32 - #define VMOVA vmovdqa --#if DL_RUNTIME_RESOLVE_REALIGN_STACK || VEC_SIZE <= DL_STACK_ALIGNMENT --# define VMOV vmovdqa --#else --# define VMOV vmovdqu --#endif - #define VEC(i) ymm##i --#define _dl_runtime_resolve _dl_runtime_resolve_avx --#define _dl_runtime_resolve_opt _dl_runtime_resolve_avx_opt - #define _dl_runtime_profile _dl_runtime_profile_avx - #include "dl-trampoline.h" --#undef _dl_runtime_resolve --#undef _dl_runtime_resolve_opt - #undef _dl_runtime_profile - #undef VEC --#undef VMOV - #undef VMOVA - #undef VEC_SIZE - - /* movaps/movups is 1-byte shorter. */ - #define VEC_SIZE 16 - #define VMOVA movaps --#if DL_RUNTIME_RESOLVE_REALIGN_STACK || VEC_SIZE <= DL_STACK_ALIGNMENT --# define VMOV movaps --#else --# define VMOV movups --#endif - #define VEC(i) xmm##i --#define _dl_runtime_resolve _dl_runtime_resolve_sse - #define _dl_runtime_profile _dl_runtime_profile_sse - #undef RESTORE_AVX - #include "dl-trampoline.h" --#undef _dl_runtime_resolve - #undef _dl_runtime_profile --#undef VMOV -+#undef VEC - #undef VMOVA -+#undef VEC_SIZE - --/* Used by _dl_runtime_resolve_avx_opt/_dl_runtime_resolve_avx512_opt -- to preserve the full vector registers with zero upper bits. */ --#define VMOVA vmovdqa --#if DL_RUNTIME_RESOLVE_REALIGN_STACK || VEC_SIZE <= DL_STACK_ALIGNMENT --# define VMOV vmovdqa --#else --# define VMOV vmovdqu --#endif --#define _dl_runtime_resolve _dl_runtime_resolve_sse_vex -+#define USE_FXSAVE -+#define STATE_SAVE_ALIGNMENT 16 -+#define _dl_runtime_resolve _dl_runtime_resolve_fxsave -+#include "dl-trampoline.h" -+#undef _dl_runtime_resolve -+#undef USE_FXSAVE -+#undef STATE_SAVE_ALIGNMENT -+ -+#define USE_XSAVE -+#define STATE_SAVE_ALIGNMENT 64 -+#define _dl_runtime_resolve _dl_runtime_resolve_xsave -+#include "dl-trampoline.h" -+#undef _dl_runtime_resolve -+#undef USE_XSAVE -+#undef STATE_SAVE_ALIGNMENT -+ -+#define USE_XSAVEC -+#define STATE_SAVE_ALIGNMENT 64 -+#define _dl_runtime_resolve _dl_runtime_resolve_xsavec - #include "dl-trampoline.h" -+#undef _dl_runtime_resolve -+#undef USE_XSAVEC -+#undef STATE_SAVE_ALIGNMENT -diff --git a/sysdeps/x86_64/dl-trampoline.h b/sysdeps/x86_64/dl-trampoline.h -index b27fa06974..9ddaafee17 100644 ---- a/sysdeps/x86_64/dl-trampoline.h -+++ b/sysdeps/x86_64/dl-trampoline.h -@@ -16,139 +16,47 @@ - License along with the GNU C Library; if not, see - . */ - --#undef REGISTER_SAVE_AREA_RAW --#ifdef __ILP32__ --/* X32 saves RCX, RDX, RSI, RDI, R8 and R9 plus RAX as well as VEC0 to -- VEC7. */ --# define REGISTER_SAVE_AREA_RAW (8 * 7 + VEC_SIZE * 8) --#else --/* X86-64 saves RCX, RDX, RSI, RDI, R8 and R9 plus RAX as well as -- BND0, BND1, BND2, BND3 and VEC0 to VEC7. */ --# define REGISTER_SAVE_AREA_RAW (8 * 7 + 16 * 4 + VEC_SIZE * 8) --#endif -+ .text -+#ifdef _dl_runtime_resolve - --#undef REGISTER_SAVE_AREA --#undef LOCAL_STORAGE_AREA --#undef BASE --#if DL_RUNTIME_RESOLVE_REALIGN_STACK --# define REGISTER_SAVE_AREA (REGISTER_SAVE_AREA_RAW + 8) --/* Local stack area before jumping to function address: RBX. */ --# define LOCAL_STORAGE_AREA 8 --# define BASE rbx --# if (REGISTER_SAVE_AREA % VEC_SIZE) != 0 --# error REGISTER_SAVE_AREA must be multples of VEC_SIZE --# endif --#else --# define REGISTER_SAVE_AREA REGISTER_SAVE_AREA_RAW --/* Local stack area before jumping to function address: All saved -- registers. */ --# define LOCAL_STORAGE_AREA REGISTER_SAVE_AREA --# define BASE rsp --# if (REGISTER_SAVE_AREA % 16) != 8 --# error REGISTER_SAVE_AREA must be odd multples of 8 -+# undef REGISTER_SAVE_AREA -+# undef LOCAL_STORAGE_AREA -+# undef BASE -+ -+# if (STATE_SAVE_ALIGNMENT % 16) != 0 -+# error STATE_SAVE_ALIGNMENT must be multples of 16 - # endif --#endif - -- .text --#ifdef _dl_runtime_resolve_opt --/* Use the smallest vector registers to preserve the full YMM/ZMM -- registers to avoid SSE transition penalty. */ -- --# if VEC_SIZE == 32 --/* Check if the upper 128 bits in %ymm0 - %ymm7 registers are non-zero -- and preserve %xmm0 - %xmm7 registers with the zero upper bits. Since -- there is no SSE transition penalty on AVX512 processors which don't -- support XGETBV with ECX == 1, _dl_runtime_resolve_avx512_slow isn't -- provided. */ -- .globl _dl_runtime_resolve_avx_slow -- .hidden _dl_runtime_resolve_avx_slow -- .type _dl_runtime_resolve_avx_slow, @function -- .align 16 --_dl_runtime_resolve_avx_slow: -- cfi_startproc -- cfi_adjust_cfa_offset(16) # Incorporate PLT -- vorpd %ymm0, %ymm1, %ymm8 -- vorpd %ymm2, %ymm3, %ymm9 -- vorpd %ymm4, %ymm5, %ymm10 -- vorpd %ymm6, %ymm7, %ymm11 -- vorpd %ymm8, %ymm9, %ymm9 -- vorpd %ymm10, %ymm11, %ymm10 -- vpcmpeqd %xmm8, %xmm8, %xmm8 -- vorpd %ymm9, %ymm10, %ymm10 -- vptest %ymm10, %ymm8 -- # Preserve %ymm0 - %ymm7 registers if the upper 128 bits of any -- # %ymm0 - %ymm7 registers aren't zero. -- PRESERVE_BND_REGS_PREFIX -- jnc _dl_runtime_resolve_avx -- # Use vzeroupper to avoid SSE transition penalty. -- vzeroupper -- # Preserve %xmm0 - %xmm7 registers with the zero upper 128 bits -- # when the upper 128 bits of %ymm0 - %ymm7 registers are zero. -- PRESERVE_BND_REGS_PREFIX -- jmp _dl_runtime_resolve_sse_vex -- cfi_adjust_cfa_offset(-16) # Restore PLT adjustment -- cfi_endproc -- .size _dl_runtime_resolve_avx_slow, .-_dl_runtime_resolve_avx_slow -+# if (STATE_SAVE_OFFSET % STATE_SAVE_ALIGNMENT) != 0 -+# error STATE_SAVE_OFFSET must be multples of STATE_SAVE_ALIGNMENT - # endif - --/* Use XGETBV with ECX == 1 to check which bits in vector registers are -- non-zero and only preserve the non-zero lower bits with zero upper -- bits. */ -- .globl _dl_runtime_resolve_opt -- .hidden _dl_runtime_resolve_opt -- .type _dl_runtime_resolve_opt, @function -- .align 16 --_dl_runtime_resolve_opt: -- cfi_startproc -- cfi_adjust_cfa_offset(16) # Incorporate PLT -- pushq %rax -- cfi_adjust_cfa_offset(8) -- cfi_rel_offset(%rax, 0) -- pushq %rcx -- cfi_adjust_cfa_offset(8) -- cfi_rel_offset(%rcx, 0) -- pushq %rdx -- cfi_adjust_cfa_offset(8) -- cfi_rel_offset(%rdx, 0) -- movl $1, %ecx -- xgetbv -- movl %eax, %r11d -- popq %rdx -- cfi_adjust_cfa_offset(-8) -- cfi_restore (%rdx) -- popq %rcx -- cfi_adjust_cfa_offset(-8) -- cfi_restore (%rcx) -- popq %rax -- cfi_adjust_cfa_offset(-8) -- cfi_restore (%rax) --# if VEC_SIZE == 32 -- # For YMM registers, check if YMM state is in use. -- andl $bit_YMM_state, %r11d -- # Preserve %xmm0 - %xmm7 registers with the zero upper 128 bits if -- # YMM state isn't in use. -- PRESERVE_BND_REGS_PREFIX -- jz _dl_runtime_resolve_sse_vex --# elif VEC_SIZE == 64 -- # For ZMM registers, check if YMM state and ZMM state are in -- # use. -- andl $(bit_YMM_state | bit_ZMM0_15_state), %r11d -- cmpl $bit_YMM_state, %r11d -- # Preserve %xmm0 - %xmm7 registers with the zero upper 384 bits if -- # neither YMM state nor ZMM state are in use. -- PRESERVE_BND_REGS_PREFIX -- jl _dl_runtime_resolve_sse_vex -- # Preserve %ymm0 - %ymm7 registers with the zero upper 256 bits if -- # ZMM state isn't in use. -- PRESERVE_BND_REGS_PREFIX -- je _dl_runtime_resolve_avx -+# if DL_RUNTIME_RESOLVE_REALIGN_STACK -+/* Local stack area before jumping to function address: RBX. */ -+# define LOCAL_STORAGE_AREA 8 -+# define BASE rbx -+# ifdef USE_FXSAVE -+/* Use fxsave to save XMM registers. */ -+# define REGISTER_SAVE_AREA (512 + STATE_SAVE_OFFSET) -+# if (REGISTER_SAVE_AREA % 16) != 0 -+# error REGISTER_SAVE_AREA must be multples of 16 -+# endif -+# endif - # else --# error Unsupported VEC_SIZE! -+# ifndef USE_FXSAVE -+# error USE_FXSAVE must be defined -+# endif -+/* Use fxsave to save XMM registers. */ -+# define REGISTER_SAVE_AREA (512 + STATE_SAVE_OFFSET + 8) -+/* Local stack area before jumping to function address: All saved -+ registers. */ -+# define LOCAL_STORAGE_AREA REGISTER_SAVE_AREA -+# define BASE rsp -+# if (REGISTER_SAVE_AREA % 16) != 8 -+# error REGISTER_SAVE_AREA must be odd multples of 8 -+# endif - # endif -- cfi_adjust_cfa_offset(-16) # Restore PLT adjustment -- cfi_endproc -- .size _dl_runtime_resolve_opt, .-_dl_runtime_resolve_opt --#endif -+ - .globl _dl_runtime_resolve - .hidden _dl_runtime_resolve - .type _dl_runtime_resolve, @function -@@ -156,21 +64,30 @@ _dl_runtime_resolve_opt: - cfi_startproc - _dl_runtime_resolve: - cfi_adjust_cfa_offset(16) # Incorporate PLT --#if DL_RUNTIME_RESOLVE_REALIGN_STACK --# if LOCAL_STORAGE_AREA != 8 --# error LOCAL_STORAGE_AREA must be 8 --# endif -+# if DL_RUNTIME_RESOLVE_REALIGN_STACK -+# if LOCAL_STORAGE_AREA != 8 -+# error LOCAL_STORAGE_AREA must be 8 -+# endif - pushq %rbx # push subtracts stack by 8. - cfi_adjust_cfa_offset(8) - cfi_rel_offset(%rbx, 0) - mov %RSP_LP, %RBX_LP - cfi_def_cfa_register(%rbx) -- and $-VEC_SIZE, %RSP_LP --#endif -+ and $-STATE_SAVE_ALIGNMENT, %RSP_LP -+# endif -+# ifdef REGISTER_SAVE_AREA - sub $REGISTER_SAVE_AREA, %RSP_LP --#if !DL_RUNTIME_RESOLVE_REALIGN_STACK -+# if !DL_RUNTIME_RESOLVE_REALIGN_STACK - cfi_adjust_cfa_offset(REGISTER_SAVE_AREA) --#endif -+# endif -+# else -+ # Allocate stack space of the required size to save the state. -+# if IS_IN (rtld) -+ sub _rtld_local_ro+RTLD_GLOBAL_RO_DL_X86_CPU_FEATURES_OFFSET+XSAVE_STATE_SIZE_OFFSET(%rip), %RSP_LP -+# else -+ sub _dl_x86_cpu_features+XSAVE_STATE_SIZE_OFFSET(%rip), %RSP_LP -+# endif -+# endif - # Preserve registers otherwise clobbered. - movq %rax, REGISTER_SAVE_RAX(%rsp) - movq %rcx, REGISTER_SAVE_RCX(%rsp) -@@ -179,59 +96,42 @@ _dl_runtime_resolve: - movq %rdi, REGISTER_SAVE_RDI(%rsp) - movq %r8, REGISTER_SAVE_R8(%rsp) - movq %r9, REGISTER_SAVE_R9(%rsp) -- VMOV %VEC(0), (REGISTER_SAVE_VEC_OFF)(%rsp) -- VMOV %VEC(1), (REGISTER_SAVE_VEC_OFF + VEC_SIZE)(%rsp) -- VMOV %VEC(2), (REGISTER_SAVE_VEC_OFF + VEC_SIZE * 2)(%rsp) -- VMOV %VEC(3), (REGISTER_SAVE_VEC_OFF + VEC_SIZE * 3)(%rsp) -- VMOV %VEC(4), (REGISTER_SAVE_VEC_OFF + VEC_SIZE * 4)(%rsp) -- VMOV %VEC(5), (REGISTER_SAVE_VEC_OFF + VEC_SIZE * 5)(%rsp) -- VMOV %VEC(6), (REGISTER_SAVE_VEC_OFF + VEC_SIZE * 6)(%rsp) -- VMOV %VEC(7), (REGISTER_SAVE_VEC_OFF + VEC_SIZE * 7)(%rsp) --#ifndef __ILP32__ -- # We also have to preserve bound registers. These are nops if -- # Intel MPX isn't available or disabled. --# ifdef HAVE_MPX_SUPPORT -- bndmov %bnd0, REGISTER_SAVE_BND0(%rsp) -- bndmov %bnd1, REGISTER_SAVE_BND1(%rsp) -- bndmov %bnd2, REGISTER_SAVE_BND2(%rsp) -- bndmov %bnd3, REGISTER_SAVE_BND3(%rsp) -+# ifdef USE_FXSAVE -+ fxsave STATE_SAVE_OFFSET(%rsp) - # else --# if REGISTER_SAVE_BND0 == 0 -- .byte 0x66,0x0f,0x1b,0x04,0x24 -+ movl $STATE_SAVE_MASK, %eax -+ xorl %edx, %edx -+ # Clear the XSAVE Header. -+# ifdef USE_XSAVE -+ movq %rdx, (STATE_SAVE_OFFSET + 512)(%rsp) -+ movq %rdx, (STATE_SAVE_OFFSET + 512 + 8)(%rsp) -+# endif -+ movq %rdx, (STATE_SAVE_OFFSET + 512 + 8 * 2)(%rsp) -+ movq %rdx, (STATE_SAVE_OFFSET + 512 + 8 * 3)(%rsp) -+ movq %rdx, (STATE_SAVE_OFFSET + 512 + 8 * 4)(%rsp) -+ movq %rdx, (STATE_SAVE_OFFSET + 512 + 8 * 5)(%rsp) -+ movq %rdx, (STATE_SAVE_OFFSET + 512 + 8 * 6)(%rsp) -+ movq %rdx, (STATE_SAVE_OFFSET + 512 + 8 * 7)(%rsp) -+# ifdef USE_XSAVE -+ xsave STATE_SAVE_OFFSET(%rsp) - # else -- .byte 0x66,0x0f,0x1b,0x44,0x24,REGISTER_SAVE_BND0 -+ xsavec STATE_SAVE_OFFSET(%rsp) - # endif -- .byte 0x66,0x0f,0x1b,0x4c,0x24,REGISTER_SAVE_BND1 -- .byte 0x66,0x0f,0x1b,0x54,0x24,REGISTER_SAVE_BND2 -- .byte 0x66,0x0f,0x1b,0x5c,0x24,REGISTER_SAVE_BND3 - # endif --#endif - # Copy args pushed by PLT in register. - # %rdi: link_map, %rsi: reloc_index - mov (LOCAL_STORAGE_AREA + 8)(%BASE), %RSI_LP - mov LOCAL_STORAGE_AREA(%BASE), %RDI_LP - call _dl_fixup # Call resolver. - mov %RAX_LP, %R11_LP # Save return value --#ifndef __ILP32__ -- # Restore bound registers. These are nops if Intel MPX isn't -- # avaiable or disabled. --# ifdef HAVE_MPX_SUPPORT -- bndmov REGISTER_SAVE_BND3(%rsp), %bnd3 -- bndmov REGISTER_SAVE_BND2(%rsp), %bnd2 -- bndmov REGISTER_SAVE_BND1(%rsp), %bnd1 -- bndmov REGISTER_SAVE_BND0(%rsp), %bnd0 -+ # Get register content back. -+# ifdef USE_FXSAVE -+ fxrstor STATE_SAVE_OFFSET(%rsp) - # else -- .byte 0x66,0x0f,0x1a,0x5c,0x24,REGISTER_SAVE_BND3 -- .byte 0x66,0x0f,0x1a,0x54,0x24,REGISTER_SAVE_BND2 -- .byte 0x66,0x0f,0x1a,0x4c,0x24,REGISTER_SAVE_BND1 --# if REGISTER_SAVE_BND0 == 0 -- .byte 0x66,0x0f,0x1a,0x04,0x24 --# else -- .byte 0x66,0x0f,0x1a,0x44,0x24,REGISTER_SAVE_BND0 --# endif -+ movl $STATE_SAVE_MASK, %eax -+ xorl %edx, %edx -+ xrstor STATE_SAVE_OFFSET(%rsp) - # endif --#endif -- # Get register content back. - movq REGISTER_SAVE_R9(%rsp), %r9 - movq REGISTER_SAVE_R8(%rsp), %r8 - movq REGISTER_SAVE_RDI(%rsp), %rdi -@@ -239,20 +139,12 @@ _dl_runtime_resolve: - movq REGISTER_SAVE_RDX(%rsp), %rdx - movq REGISTER_SAVE_RCX(%rsp), %rcx - movq REGISTER_SAVE_RAX(%rsp), %rax -- VMOV (REGISTER_SAVE_VEC_OFF)(%rsp), %VEC(0) -- VMOV (REGISTER_SAVE_VEC_OFF + VEC_SIZE)(%rsp), %VEC(1) -- VMOV (REGISTER_SAVE_VEC_OFF + VEC_SIZE * 2)(%rsp), %VEC(2) -- VMOV (REGISTER_SAVE_VEC_OFF + VEC_SIZE * 3)(%rsp), %VEC(3) -- VMOV (REGISTER_SAVE_VEC_OFF + VEC_SIZE * 4)(%rsp), %VEC(4) -- VMOV (REGISTER_SAVE_VEC_OFF + VEC_SIZE * 5)(%rsp), %VEC(5) -- VMOV (REGISTER_SAVE_VEC_OFF + VEC_SIZE * 6)(%rsp), %VEC(6) -- VMOV (REGISTER_SAVE_VEC_OFF + VEC_SIZE * 7)(%rsp), %VEC(7) --#if DL_RUNTIME_RESOLVE_REALIGN_STACK -+# if DL_RUNTIME_RESOLVE_REALIGN_STACK - mov %RBX_LP, %RSP_LP - cfi_def_cfa_register(%rsp) - movq (%rsp), %rbx - cfi_restore(%rbx) --#endif -+# endif - # Adjust stack(PLT did 2 pushes) - add $(LOCAL_STORAGE_AREA + 16), %RSP_LP - cfi_adjust_cfa_offset(-(LOCAL_STORAGE_AREA + 16)) -@@ -261,11 +153,9 @@ _dl_runtime_resolve: - jmp *%r11 # Jump to function address. - cfi_endproc - .size _dl_runtime_resolve, .-_dl_runtime_resolve -+#endif - - --/* To preserve %xmm0 - %xmm7 registers, dl-trampoline.h is included -- twice, for _dl_runtime_resolve_sse and _dl_runtime_resolve_sse_vex. -- But we don't need another _dl_runtime_profile for XMM registers. */ - #if !defined PROF && defined _dl_runtime_profile - # if (LR_VECTOR_OFFSET % VEC_SIZE) != 0 - # error LR_VECTOR_OFFSET must be multples of VEC_SIZE -diff --git a/sysdeps/x86_64/localplt.data b/sysdeps/x86_64/localplt.data -index 014a9f4554..a1840cff31 100644 ---- a/sysdeps/x86_64/localplt.data -+++ b/sysdeps/x86_64/localplt.data -@@ -8,7 +8,7 @@ libc.so: free + RELA R_X86_64_GLOB_DAT - libc.so: malloc + RELA R_X86_64_GLOB_DAT - libc.so: memalign + RELA R_X86_64_GLOB_DAT - libc.so: realloc + RELA R_X86_64_GLOB_DAT --libm.so: matherr -+libm.so: matherr + RELA R_X86_64_GLOB_DAT - # The main malloc is interposed into the dynamic linker, for - # allocations after the initial link (when dlopen is used). - ld.so: malloc + RELA R_X86_64_GLOB_DAT -diff --git a/sysdeps/x86_64/mempcpy_chk.S b/sysdeps/x86_64/mempcpy_chk.S -index f8a9260e6e..f912291576 100644 ---- a/sysdeps/x86_64/mempcpy_chk.S -+++ b/sysdeps/x86_64/mempcpy_chk.S -@@ -19,7 +19,7 @@ - #include - #include "asm-syntax.h" - --#ifndef PIC -+#ifndef SHARED - /* For libc.so this is defined in memcpy.S. - For libc.a, this is a separate source to avoid - mempcpy bringing in __chk_fail and all routines -diff --git a/sysdeps/x86_64/multiarch/memcpy.S b/sysdeps/x86_64/multiarch/memcpy.S -index 1f83ee3e84..af2770397c 100644 ---- a/sysdeps/x86_64/multiarch/memcpy.S -+++ b/sysdeps/x86_64/multiarch/memcpy.S -@@ -32,6 +32,8 @@ ENTRY(__new_memcpy) - lea __memcpy_erms(%rip), %RAX_LP - HAS_ARCH_FEATURE (Prefer_ERMS) - jnz 2f -+ HAS_ARCH_FEATURE (Prefer_No_AVX512) -+ jnz 1f - HAS_ARCH_FEATURE (AVX512F_Usable) - jz 1f - lea __memcpy_avx512_no_vzeroupper(%rip), %RAX_LP -diff --git a/sysdeps/x86_64/multiarch/memcpy_chk.S b/sysdeps/x86_64/multiarch/memcpy_chk.S -index 54923420f1..8737fb9755 100644 ---- a/sysdeps/x86_64/multiarch/memcpy_chk.S -+++ b/sysdeps/x86_64/multiarch/memcpy_chk.S -@@ -30,6 +30,8 @@ - ENTRY(__memcpy_chk) - .type __memcpy_chk, @gnu_indirect_function - LOAD_RTLD_GLOBAL_RO_RDX -+ HAS_ARCH_FEATURE (Prefer_No_AVX512) -+ jnz 1f - HAS_ARCH_FEATURE (AVX512F_Usable) - jz 1f - lea __memcpy_chk_avx512_no_vzeroupper(%rip), %RAX_LP -diff --git a/sysdeps/x86_64/multiarch/memmove.S b/sysdeps/x86_64/multiarch/memmove.S -index 2021bfc30c..8c534e83e0 100644 ---- a/sysdeps/x86_64/multiarch/memmove.S -+++ b/sysdeps/x86_64/multiarch/memmove.S -@@ -30,6 +30,8 @@ ENTRY(__libc_memmove) - lea __memmove_erms(%rip), %RAX_LP - HAS_ARCH_FEATURE (Prefer_ERMS) - jnz 2f -+ HAS_ARCH_FEATURE (Prefer_No_AVX512) -+ jnz 1f - HAS_ARCH_FEATURE (AVX512F_Usable) - jz 1f - lea __memmove_avx512_no_vzeroupper(%rip), %RAX_LP -diff --git a/sysdeps/x86_64/multiarch/memmove_chk.S b/sysdeps/x86_64/multiarch/memmove_chk.S -index 8a252adcae..7870dd0247 100644 ---- a/sysdeps/x86_64/multiarch/memmove_chk.S -+++ b/sysdeps/x86_64/multiarch/memmove_chk.S -@@ -29,6 +29,8 @@ - ENTRY(__memmove_chk) - .type __memmove_chk, @gnu_indirect_function - LOAD_RTLD_GLOBAL_RO_RDX -+ HAS_ARCH_FEATURE (Prefer_No_AVX512) -+ jnz 1f - HAS_ARCH_FEATURE (AVX512F_Usable) - jz 1f - lea __memmove_chk_avx512_no_vzeroupper(%rip), %RAX_LP -diff --git a/sysdeps/x86_64/multiarch/mempcpy.S b/sysdeps/x86_64/multiarch/mempcpy.S -index 79c840d075..b8b2b28094 100644 ---- a/sysdeps/x86_64/multiarch/mempcpy.S -+++ b/sysdeps/x86_64/multiarch/mempcpy.S -@@ -32,6 +32,8 @@ ENTRY(__mempcpy) - lea __mempcpy_erms(%rip), %RAX_LP - HAS_ARCH_FEATURE (Prefer_ERMS) - jnz 2f -+ HAS_ARCH_FEATURE (Prefer_No_AVX512) -+ jnz 1f - HAS_ARCH_FEATURE (AVX512F_Usable) - jz 1f - lea __mempcpy_avx512_no_vzeroupper(%rip), %RAX_LP -diff --git a/sysdeps/x86_64/multiarch/mempcpy_chk.S b/sysdeps/x86_64/multiarch/mempcpy_chk.S -index 6927962e81..072b22c49f 100644 ---- a/sysdeps/x86_64/multiarch/mempcpy_chk.S -+++ b/sysdeps/x86_64/multiarch/mempcpy_chk.S -@@ -30,6 +30,8 @@ - ENTRY(__mempcpy_chk) - .type __mempcpy_chk, @gnu_indirect_function - LOAD_RTLD_GLOBAL_RO_RDX -+ HAS_ARCH_FEATURE (Prefer_No_AVX512) -+ jnz 1f - HAS_ARCH_FEATURE (AVX512F_Usable) - jz 1f - lea __mempcpy_chk_avx512_no_vzeroupper(%rip), %RAX_LP -diff --git a/sysdeps/x86_64/multiarch/memset.S b/sysdeps/x86_64/multiarch/memset.S -index c958b2f49f..9d33118cf8 100644 ---- a/sysdeps/x86_64/multiarch/memset.S -+++ b/sysdeps/x86_64/multiarch/memset.S -@@ -41,6 +41,8 @@ ENTRY(memset) - jnz L(AVX512F) - lea __memset_avx2_unaligned(%rip), %RAX_LP - L(AVX512F): -+ HAS_ARCH_FEATURE (Prefer_No_AVX512) -+ jnz 2f - HAS_ARCH_FEATURE (AVX512F_Usable) - jz 2f - lea __memset_avx512_no_vzeroupper(%rip), %RAX_LP -diff --git a/sysdeps/x86_64/multiarch/memset_chk.S b/sysdeps/x86_64/multiarch/memset_chk.S -index 79eaa37bb6..7e08311cdf 100644 ---- a/sysdeps/x86_64/multiarch/memset_chk.S -+++ b/sysdeps/x86_64/multiarch/memset_chk.S -@@ -38,6 +38,8 @@ ENTRY(__memset_chk) - jnz L(AVX512F) - lea __memset_chk_avx2_unaligned(%rip), %RAX_LP - L(AVX512F): -+ HAS_ARCH_FEATURE (Prefer_No_AVX512) -+ jnz 2f - HAS_ARCH_FEATURE (AVX512F_Usable) - jz 2f - lea __memset_chk_avx512_no_vzeroupper(%rip), %RAX_LP -diff --git a/sysdeps/x86_64/rtld-offsets.sym b/sysdeps/x86_64/rtld-offsets.sym -new file mode 100644 -index 0000000000..fd41b51521 ---- /dev/null -+++ b/sysdeps/x86_64/rtld-offsets.sym -@@ -0,0 +1,6 @@ -+#define SHARED -+#include -+ -+-- -+ -+GL_TLS_GENERATION_OFFSET offsetof (struct rtld_global, _dl_tls_generation) -diff --git a/sysdeps/x86_64/tls_get_addr.S b/sysdeps/x86_64/tls_get_addr.S -new file mode 100644 -index 0000000000..9d38fb3be5 ---- /dev/null -+++ b/sysdeps/x86_64/tls_get_addr.S -@@ -0,0 +1,61 @@ -+/* Stack-aligning implementation of __tls_get_addr. x86-64 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 -+ . */ -+ -+#ifdef SHARED -+ -+# include -+# include "tlsdesc.h" -+# include "rtld-offsets.h" -+ -+/* See __tls_get_addr and __tls_get_addr_slow in dl-tls.c. This function -+ call __tls_get_addr_slow on both slow paths. It realigns the stack -+ before the call to work around GCC PR58066. */ -+ -+ENTRY (__tls_get_addr) -+ mov %fs:DTV_OFFSET, %RDX_LP -+ mov GL_TLS_GENERATION_OFFSET+_rtld_local(%rip), %RAX_LP -+ /* GL(dl_tls_generation) == dtv[0].counter */ -+ cmp %RAX_LP, (%rdx) -+ jne 1f -+ mov TI_MODULE_OFFSET(%rdi), %RAX_LP -+ /* dtv[ti->ti_module] */ -+# ifdef __LP64__ -+ salq $4, %rax -+ movq (%rdx,%rax), %rax -+# else -+ movl (%rdx,%rax, 8), %eax -+# endif -+ cmp $-1, %RAX_LP -+ je 1f -+ add TI_OFFSET_OFFSET(%rdi), %RAX_LP -+ ret -+1: -+ /* On the slow path, align the stack. */ -+ pushq %rbp -+ cfi_def_cfa_offset (16) -+ cfi_offset (%rbp, -16) -+ mov %RSP_LP, %RBP_LP -+ cfi_def_cfa_register (%rbp) -+ and $-16, %RSP_LP -+ call __tls_get_addr_slow -+ mov %RBP_LP, %RSP_LP -+ popq %rbp -+ cfi_def_cfa (%rsp, 8) -+ ret -+END (__tls_get_addr) -+#endif /* SHARED */ -diff --git a/sysdeps/x86_64/tlsdesc.sym b/sysdeps/x86_64/tlsdesc.sym -index 33854975d0..fc897ab4b5 100644 ---- a/sysdeps/x86_64/tlsdesc.sym -+++ b/sysdeps/x86_64/tlsdesc.sym -@@ -15,3 +15,6 @@ TLSDESC_ARG offsetof(struct tlsdesc, arg) - TLSDESC_GEN_COUNT offsetof(struct tlsdesc_dynamic_arg, gen_count) - TLSDESC_MODID offsetof(struct tlsdesc_dynamic_arg, tlsinfo.ti_module) - TLSDESC_MODOFF offsetof(struct tlsdesc_dynamic_arg, tlsinfo.ti_offset) -+ -+TI_MODULE_OFFSET offsetof(tls_index, ti_module) -+TI_OFFSET_OFFSET offsetof(tls_index, ti_offset) -diff --git a/sysdeps/x86_64/tst-avx-aux.c b/sysdeps/x86_64/tst-avx-aux.c -new file mode 100644 -index 0000000000..e3807de7bb ---- /dev/null -+++ b/sysdeps/x86_64/tst-avx-aux.c -@@ -0,0 +1,47 @@ -+/* Test case for preserved AVX registers in dynamic linker, -mavx part. -+ 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 -+ . */ -+ -+#include -+#include -+#include -+ -+int -+tst_avx_aux (void) -+{ -+#ifdef __AVX__ -+ extern __m256i avx_test (__m256i, __m256i, __m256i, __m256i, -+ __m256i, __m256i, __m256i, __m256i); -+ -+ __m256i ymm0 = _mm256_set1_epi32 (0); -+ __m256i ymm1 = _mm256_set1_epi32 (1); -+ __m256i ymm2 = _mm256_set1_epi32 (2); -+ __m256i ymm3 = _mm256_set1_epi32 (3); -+ __m256i ymm4 = _mm256_set1_epi32 (4); -+ __m256i ymm5 = _mm256_set1_epi32 (5); -+ __m256i ymm6 = _mm256_set1_epi32 (6); -+ __m256i ymm7 = _mm256_set1_epi32 (7); -+ __m256i ret = avx_test (ymm0, ymm1, ymm2, ymm3, -+ ymm4, ymm5, ymm6, ymm7); -+ ymm0 = _mm256_set1_epi32 (0x12349876); -+ if (memcmp (&ymm0, &ret, sizeof (ret))) -+ abort (); -+ return 0; -+#else /* __AVX__ */ -+ return 77; -+#endif /* __AVX__ */ -+} -diff --git a/sysdeps/x86_64/tst-avx.c b/sysdeps/x86_64/tst-avx.c -new file mode 100644 -index 0000000000..ec2e3a79ff ---- /dev/null -+++ b/sysdeps/x86_64/tst-avx.c -@@ -0,0 +1,49 @@ -+/* Test case for preserved AVX registers in dynamic linker. -+ 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 -+ . */ -+ -+#include -+ -+int tst_avx_aux (void); -+ -+static int -+avx_enabled (void) -+{ -+ unsigned int eax, ebx, ecx, edx; -+ -+ if (__get_cpuid (1, &eax, &ebx, &ecx, &edx) == 0 -+ || (ecx & (bit_AVX | bit_OSXSAVE)) != (bit_AVX | bit_OSXSAVE)) -+ return 0; -+ -+ /* Check the OS has AVX and SSE saving enabled. */ -+ asm ("xgetbv" : "=a" (eax), "=d" (edx) : "c" (0)); -+ -+ return (eax & 6) == 6; -+} -+ -+static int -+do_test (void) -+{ -+ /* Run AVX test only if AVX is supported. */ -+ if (avx_enabled ()) -+ return tst_avx_aux (); -+ else -+ return 77; -+} -+ -+#define TEST_FUNCTION do_test () -+#include "../../test-skeleton.c" -diff --git a/sysdeps/x86_64/tst-avx512-aux.c b/sysdeps/x86_64/tst-avx512-aux.c -new file mode 100644 -index 0000000000..6cebc523f2 ---- /dev/null -+++ b/sysdeps/x86_64/tst-avx512-aux.c -@@ -0,0 +1,48 @@ -+/* Test case for preserved AVX512 registers in dynamic linker, -+ -mavx512 part. -+ 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 -+ . */ -+ -+#include -+#include -+#include -+ -+int -+tst_avx512_aux (void) -+{ -+#ifdef __AVX512F__ -+ extern __m512i avx512_test (__m512i, __m512i, __m512i, __m512i, -+ __m512i, __m512i, __m512i, __m512i); -+ -+ __m512i zmm0 = _mm512_set1_epi32 (0); -+ __m512i zmm1 = _mm512_set1_epi32 (1); -+ __m512i zmm2 = _mm512_set1_epi32 (2); -+ __m512i zmm3 = _mm512_set1_epi32 (3); -+ __m512i zmm4 = _mm512_set1_epi32 (4); -+ __m512i zmm5 = _mm512_set1_epi32 (5); -+ __m512i zmm6 = _mm512_set1_epi32 (6); -+ __m512i zmm7 = _mm512_set1_epi32 (7); -+ __m512i ret = avx512_test (zmm0, zmm1, zmm2, zmm3, -+ zmm4, zmm5, zmm6, zmm7); -+ zmm0 = _mm512_set1_epi32 (0x12349876); -+ if (memcmp (&zmm0, &ret, sizeof (ret))) -+ abort (); -+ return 0; -+#else /* __AVX512F__ */ -+ return 77; -+#endif /* __AVX512F__ */ -+} -diff --git a/sysdeps/x86_64/tst-avx512.c b/sysdeps/x86_64/tst-avx512.c -new file mode 100644 -index 0000000000..a8e42ef553 ---- /dev/null -+++ b/sysdeps/x86_64/tst-avx512.c -@@ -0,0 +1,57 @@ -+/* Test case for preserved AVX512 registers in dynamic linker. -+ 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 -+ . */ -+ -+#include -+ -+int tst_avx512_aux (void); -+ -+static int -+avx512_enabled (void) -+{ -+#ifdef bit_AVX512F -+ unsigned int eax, ebx, ecx, edx; -+ -+ if (__get_cpuid (1, &eax, &ebx, &ecx, &edx) == 0 -+ || (ecx & (bit_AVX | bit_OSXSAVE)) != (bit_AVX | bit_OSXSAVE)) -+ return 0; -+ -+ __cpuid_count (7, 0, eax, ebx, ecx, edx); -+ if (!(ebx & bit_AVX512F)) -+ return 0; -+ -+ asm ("xgetbv" : "=a" (eax), "=d" (edx) : "c" (0)); -+ -+ /* Verify that ZMM, YMM and XMM states are enabled. */ -+ return (eax & 0xe6) == 0xe6; -+#else -+ return 0; -+#endif -+} -+ -+static int -+do_test (void) -+{ -+ /* Run AVX512 test only if AVX512 is supported. */ -+ if (avx512_enabled ()) -+ return tst_avx512_aux (); -+ else -+ return 77; -+} -+ -+#define TEST_FUNCTION do_test () -+#include "../../test-skeleton.c" -diff --git a/sysdeps/x86_64/tst-avx512mod.c b/sysdeps/x86_64/tst-avx512mod.c -new file mode 100644 -index 0000000000..4cfb3a2c3d ---- /dev/null -+++ b/sysdeps/x86_64/tst-avx512mod.c -@@ -0,0 +1,48 @@ -+/* Test case for x86-64 preserved AVX512 registers in dynamic linker. */ -+ -+#ifdef __AVX512F__ -+#include -+#include -+#include -+ -+__m512i -+avx512_test (__m512i x0, __m512i x1, __m512i x2, __m512i x3, -+ __m512i x4, __m512i x5, __m512i x6, __m512i x7) -+{ -+ __m512i zmm; -+ -+ zmm = _mm512_set1_epi32 (0); -+ if (memcmp (&zmm, &x0, sizeof (zmm))) -+ abort (); -+ -+ zmm = _mm512_set1_epi32 (1); -+ if (memcmp (&zmm, &x1, sizeof (zmm))) -+ abort (); -+ -+ zmm = _mm512_set1_epi32 (2); -+ if (memcmp (&zmm, &x2, sizeof (zmm))) -+ abort (); -+ -+ zmm = _mm512_set1_epi32 (3); -+ if (memcmp (&zmm, &x3, sizeof (zmm))) -+ abort (); -+ -+ zmm = _mm512_set1_epi32 (4); -+ if (memcmp (&zmm, &x4, sizeof (zmm))) -+ abort (); -+ -+ zmm = _mm512_set1_epi32 (5); -+ if (memcmp (&zmm, &x5, sizeof (zmm))) -+ abort (); -+ -+ zmm = _mm512_set1_epi32 (6); -+ if (memcmp (&zmm, &x6, sizeof (zmm))) -+ abort (); -+ -+ zmm = _mm512_set1_epi32 (7); -+ if (memcmp (&zmm, &x7, sizeof (zmm))) -+ abort (); -+ -+ return _mm512_set1_epi32 (0x12349876); -+} -+#endif -diff --git a/sysdeps/x86_64/tst-avxmod.c b/sysdeps/x86_64/tst-avxmod.c -new file mode 100644 -index 0000000000..6e5b154997 ---- /dev/null -+++ b/sysdeps/x86_64/tst-avxmod.c -@@ -0,0 +1,48 @@ -+/* Test case for x86-64 preserved AVX registers in dynamic linker. */ -+ -+#ifdef __AVX__ -+#include -+#include -+#include -+ -+__m256i -+avx_test (__m256i x0, __m256i x1, __m256i x2, __m256i x3, -+ __m256i x4, __m256i x5, __m256i x6, __m256i x7) -+{ -+ __m256i ymm; -+ -+ ymm = _mm256_set1_epi32 (0); -+ if (memcmp (&ymm, &x0, sizeof (ymm))) -+ abort (); -+ -+ ymm = _mm256_set1_epi32 (1); -+ if (memcmp (&ymm, &x1, sizeof (ymm))) -+ abort (); -+ -+ ymm = _mm256_set1_epi32 (2); -+ if (memcmp (&ymm, &x2, sizeof (ymm))) -+ abort (); -+ -+ ymm = _mm256_set1_epi32 (3); -+ if (memcmp (&ymm, &x3, sizeof (ymm))) -+ abort (); -+ -+ ymm = _mm256_set1_epi32 (4); -+ if (memcmp (&ymm, &x4, sizeof (ymm))) -+ abort (); -+ -+ ymm = _mm256_set1_epi32 (5); -+ if (memcmp (&ymm, &x5, sizeof (ymm))) -+ abort (); -+ -+ ymm = _mm256_set1_epi32 (6); -+ if (memcmp (&ymm, &x6, sizeof (ymm))) -+ abort (); -+ -+ ymm = _mm256_set1_epi32 (7); -+ if (memcmp (&ymm, &x7, sizeof (ymm))) -+ abort (); -+ -+ return _mm256_set1_epi32 (0x12349876); -+} -+#endif -diff --git a/sysdeps/x86_64/tst-sse.c b/sysdeps/x86_64/tst-sse.c -new file mode 100644 -index 0000000000..dd1537cf27 ---- /dev/null -+++ b/sysdeps/x86_64/tst-sse.c -@@ -0,0 +1,46 @@ -+/* Test case for preserved SSE registers in dynamic linker. -+ 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 -+ . */ -+ -+#include -+#include -+#include -+ -+extern __m128i sse_test (__m128i, __m128i, __m128i, __m128i, -+ __m128i, __m128i, __m128i, __m128i); -+ -+static int -+do_test (void) -+{ -+ __m128i xmm0 = _mm_set1_epi32 (0); -+ __m128i xmm1 = _mm_set1_epi32 (1); -+ __m128i xmm2 = _mm_set1_epi32 (2); -+ __m128i xmm3 = _mm_set1_epi32 (3); -+ __m128i xmm4 = _mm_set1_epi32 (4); -+ __m128i xmm5 = _mm_set1_epi32 (5); -+ __m128i xmm6 = _mm_set1_epi32 (6); -+ __m128i xmm7 = _mm_set1_epi32 (7); -+ __m128i ret = sse_test (xmm0, xmm1, xmm2, xmm3, -+ xmm4, xmm5, xmm6, xmm7); -+ xmm0 = _mm_set1_epi32 (0x12349876); -+ if (memcmp (&xmm0, &ret, sizeof (ret))) -+ abort (); -+ return 0; -+} -+ -+#define TEST_FUNCTION do_test () -+#include "../../test-skeleton.c" -diff --git a/sysdeps/x86_64/tst-ssemod.c b/sysdeps/x86_64/tst-ssemod.c -new file mode 100644 -index 0000000000..907a64c69e ---- /dev/null -+++ b/sysdeps/x86_64/tst-ssemod.c -@@ -0,0 +1,46 @@ -+/* Test case for x86-64 preserved SSE registers in dynamic linker. */ -+ -+#include -+#include -+#include -+ -+__m128i -+sse_test (__m128i x0, __m128i x1, __m128i x2, __m128i x3, -+ __m128i x4, __m128i x5, __m128i x6, __m128i x7) -+{ -+ __m128i xmm; -+ -+ xmm = _mm_set1_epi32 (0); -+ if (memcmp (&xmm, &x0, sizeof (xmm))) -+ abort (); -+ -+ xmm = _mm_set1_epi32 (1); -+ if (memcmp (&xmm, &x1, sizeof (xmm))) -+ abort (); -+ -+ xmm = _mm_set1_epi32 (2); -+ if (memcmp (&xmm, &x2, sizeof (xmm))) -+ abort (); -+ -+ xmm = _mm_set1_epi32 (3); -+ if (memcmp (&xmm, &x3, sizeof (xmm))) -+ abort (); -+ -+ xmm = _mm_set1_epi32 (4); -+ if (memcmp (&xmm, &x4, sizeof (xmm))) -+ abort (); -+ -+ xmm = _mm_set1_epi32 (5); -+ if (memcmp (&xmm, &x5, sizeof (xmm))) -+ abort (); -+ -+ xmm = _mm_set1_epi32 (6); -+ if (memcmp (&xmm, &x6, sizeof (xmm))) -+ abort (); -+ -+ xmm = _mm_set1_epi32 (7); -+ if (memcmp (&xmm, &x7, sizeof (xmm))) -+ abort (); -+ -+ return _mm_set1_epi32 (0x12349876); -+}