diff --git a/git-updates.diff b/git-updates.diff deleted file mode 100644 index 034b6ae..0000000 --- a/git-updates.diff +++ /dev/null @@ -1,11266 +0,0 @@ -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..63917cc15d 100644 ---- a/ChangeLog -+++ b/ChangeLog -@@ -1,3 +1,822 @@ -+2019-04-23 Adhemerval Zanella -+ -+ [BZ #18035] -+ * elf/pldd-xx.c: Use _Static_assert in of pldd_assert. -+ (E(find_maps)): Avoid use alloca, use default read file operations -+ instead of explicit LFS names, and fix infinite loop. -+ * elf/pldd.c: Explicit set _FILE_OFFSET_BITS, cleanup headers. -+ (get_process_info): Use _Static_assert instead of assert, use default -+ directory operations instead of explicit LFS names, and free some -+ leadek pointers. -+ -+2019-04-03 TAMUKI Shoichi -+ -+ [BZ #22964] -+ * localedata/locales/ja_JP (LC_TIME): Add entry for the new Japanese -+ era. -+ -+2019-03-21 Stefan Liebler -+ -+ * sysdeps/s390/dl-procinfo.h (HWCAP_IMPORTANT): -+ Add HWCAP_S390_VX and HWCAP_S390_VXE. -+ -+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..9c2c37652f 100644 ---- a/NEWS -+++ b/NEWS -@@ -5,6 +5,87 @@ See the end for copying conditions. - Please send GNU C library bug reports via - using `glibc' in the "product" field. - -+Version 2.28.1 -+ -+Major new features: -+ -+* The entry for the new Japanese era has been added for ja_JP locale. -+ -+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: -+ -+ [18035] Fix pldd hang -+ [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 +503,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/pldd-xx.c b/elf/pldd-xx.c -index 2823dea662..f818d98582 100644 ---- a/elf/pldd-xx.c -+++ b/elf/pldd-xx.c -@@ -23,10 +23,6 @@ - #define EW_(e, w, t) EW__(e, w, _##t) - #define EW__(e, w, t) e##w##t - --#define pldd_assert(name, exp) \ -- typedef int __assert_##name[((exp) != 0) - 1] -- -- - struct E(link_map) - { - EW(Addr) l_addr; -@@ -39,12 +35,12 @@ struct E(link_map) - EW(Addr) l_libname; - }; - #if CLASS == __ELF_NATIVE_CLASS --pldd_assert (l_addr, (offsetof (struct link_map, l_addr) -- == offsetof (struct E(link_map), l_addr))); --pldd_assert (l_name, (offsetof (struct link_map, l_name) -- == offsetof (struct E(link_map), l_name))); --pldd_assert (l_next, (offsetof (struct link_map, l_next) -- == offsetof (struct E(link_map), l_next))); -+_Static_assert (offsetof (struct link_map, l_addr) -+ == offsetof (struct E(link_map), l_addr), "l_addr"); -+_Static_assert (offsetof (struct link_map, l_name) -+ == offsetof (struct E(link_map), l_name), "l_name"); -+_Static_assert (offsetof (struct link_map, l_next) -+ == offsetof (struct E(link_map), l_next), "l_next"); - #endif - - -@@ -54,10 +50,10 @@ struct E(libname_list) - EW(Addr) next; - }; - #if CLASS == __ELF_NATIVE_CLASS --pldd_assert (name, (offsetof (struct libname_list, name) -- == offsetof (struct E(libname_list), name))); --pldd_assert (next, (offsetof (struct libname_list, next) -- == offsetof (struct E(libname_list), next))); -+_Static_assert (offsetof (struct libname_list, name) -+ == offsetof (struct E(libname_list), name), "name"); -+_Static_assert (offsetof (struct libname_list, next) -+ == offsetof (struct E(libname_list), next), "next"); - #endif - - struct E(r_debug) -@@ -69,16 +65,17 @@ struct E(r_debug) - EW(Addr) r_map; - }; - #if CLASS == __ELF_NATIVE_CLASS --pldd_assert (r_version, (offsetof (struct r_debug, r_version) -- == offsetof (struct E(r_debug), r_version))); --pldd_assert (r_map, (offsetof (struct r_debug, r_map) -- == offsetof (struct E(r_debug), r_map))); -+_Static_assert (offsetof (struct r_debug, r_version) -+ == offsetof (struct E(r_debug), r_version), "r_version"); -+_Static_assert (offsetof (struct r_debug, r_map) -+ == offsetof (struct E(r_debug), r_map), "r_map"); - #endif - - - static int - --E(find_maps) (pid_t pid, void *auxv, size_t auxv_size) -+E(find_maps) (const char *exe, int memfd, pid_t pid, void *auxv, -+ size_t auxv_size) - { - EW(Addr) phdr = 0; - unsigned int phnum = 0; -@@ -104,12 +101,9 @@ E(find_maps) (pid_t pid, void *auxv, size_t auxv_size) - if (phdr == 0 || phnum == 0 || phent == 0) - error (EXIT_FAILURE, 0, gettext ("cannot find program header of process")); - -- EW(Phdr) *p = alloca (phnum * phent); -- if (pread64 (memfd, p, phnum * phent, phdr) != phnum * phent) -- { -- error (0, 0, gettext ("cannot read program header")); -- return EXIT_FAILURE; -- } -+ EW(Phdr) *p = xmalloc (phnum * phent); -+ if (pread (memfd, p, phnum * phent, phdr) != phnum * phent) -+ error (EXIT_FAILURE, 0, gettext ("cannot read program header")); - - /* Determine the load offset. We need this for interpreting the - other program header entries so we do this in a separate loop. -@@ -129,24 +123,18 @@ E(find_maps) (pid_t pid, void *auxv, size_t auxv_size) - if (p[i].p_type == PT_DYNAMIC) - { - EW(Dyn) *dyn = xmalloc (p[i].p_filesz); -- if (pread64 (memfd, dyn, p[i].p_filesz, offset + p[i].p_vaddr) -+ if (pread (memfd, dyn, p[i].p_filesz, offset + p[i].p_vaddr) - != p[i].p_filesz) -- { -- error (0, 0, gettext ("cannot read dynamic section")); -- return EXIT_FAILURE; -- } -+ error (EXIT_FAILURE, 0, gettext ("cannot read dynamic section")); - - /* Search for the DT_DEBUG entry. */ - for (unsigned int j = 0; j < p[i].p_filesz / sizeof (EW(Dyn)); ++j) - if (dyn[j].d_tag == DT_DEBUG && dyn[j].d_un.d_ptr != 0) - { - struct E(r_debug) r; -- if (pread64 (memfd, &r, sizeof (r), dyn[j].d_un.d_ptr) -+ if (pread (memfd, &r, sizeof (r), dyn[j].d_un.d_ptr) - != sizeof (r)) -- { -- error (0, 0, gettext ("cannot read r_debug")); -- return EXIT_FAILURE; -- } -+ error (EXIT_FAILURE, 0, gettext ("cannot read r_debug")); - - if (r.r_map != 0) - { -@@ -160,13 +148,10 @@ E(find_maps) (pid_t pid, void *auxv, size_t auxv_size) - } - else if (p[i].p_type == PT_INTERP) - { -- interp = alloca (p[i].p_filesz); -- if (pread64 (memfd, interp, p[i].p_filesz, offset + p[i].p_vaddr) -+ interp = xmalloc (p[i].p_filesz); -+ if (pread (memfd, interp, p[i].p_filesz, offset + p[i].p_vaddr) - != p[i].p_filesz) -- { -- error (0, 0, gettext ("cannot read program interpreter")); -- return EXIT_FAILURE; -- } -+ error (EXIT_FAILURE, 0, gettext ("cannot read program interpreter")); - } - - if (list == 0) -@@ -174,14 +159,16 @@ E(find_maps) (pid_t pid, void *auxv, size_t auxv_size) - if (interp == NULL) - { - // XXX check whether the executable itself is the loader -- return EXIT_FAILURE; -+ exit (EXIT_FAILURE); - } - - // XXX perhaps try finding ld.so and _r_debug in it -- -- return EXIT_FAILURE; -+ exit (EXIT_FAILURE); - } - -+ free (p); -+ free (interp); -+ - /* Print the PID and program name first. */ - printf ("%lu:\t%s\n", (unsigned long int) pid, exe); - -@@ -192,47 +179,27 @@ E(find_maps) (pid_t pid, void *auxv, size_t auxv_size) - do - { - struct E(link_map) m; -- if (pread64 (memfd, &m, sizeof (m), list) != sizeof (m)) -- { -- error (0, 0, gettext ("cannot read link map")); -- status = EXIT_FAILURE; -- goto out; -- } -+ if (pread (memfd, &m, sizeof (m), list) != sizeof (m)) -+ error (EXIT_FAILURE, 0, gettext ("cannot read link map")); - - EW(Addr) name_offset = m.l_name; -- again: - while (1) - { -- ssize_t n = pread64 (memfd, tmpbuf.data, tmpbuf.length, name_offset); -+ ssize_t n = pread (memfd, tmpbuf.data, tmpbuf.length, name_offset); - if (n == -1) -- { -- error (0, 0, gettext ("cannot read object name")); -- status = EXIT_FAILURE; -- goto out; -- } -+ error (EXIT_FAILURE, 0, gettext ("cannot read object name")); - - if (memchr (tmpbuf.data, '\0', n) != NULL) - break; - - if (!scratch_buffer_grow (&tmpbuf)) -- { -- error (0, 0, gettext ("cannot allocate buffer for object name")); -- status = EXIT_FAILURE; -- goto out; -- } -+ error (EXIT_FAILURE, 0, -+ gettext ("cannot allocate buffer for object name")); - } - -- if (((char *)tmpbuf.data)[0] == '\0' && name_offset == m.l_name -- && m.l_libname != 0) -- { -- /* Try the l_libname element. */ -- struct E(libname_list) ln; -- if (pread64 (memfd, &ln, sizeof (ln), m.l_libname) == sizeof (ln)) -- { -- name_offset = ln.name; -- goto again; -- } -- } -+ /* The m.l_name and m.l_libname.name for loader linkmap points to same -+ values (since BZ#387 fix). Trying to use l_libname name as the -+ shared object name might lead to an infinite loop (BZ#18035). */ - - /* Skip over the executable. */ - if (((char *)tmpbuf.data)[0] != '\0') -@@ -242,7 +209,6 @@ E(find_maps) (pid_t pid, void *auxv, size_t auxv_size) - } - while (list != 0); - -- out: - scratch_buffer_free (&tmpbuf); - return status; - } -diff --git a/elf/pldd.c b/elf/pldd.c -index b8106fdc33..0bdfff450a 100644 ---- a/elf/pldd.c -+++ b/elf/pldd.c -@@ -17,23 +17,17 @@ - License along with the GNU C Library; if not, see - . */ - --#include -+#define _FILE_OFFSET_BITS 64 -+ - #include --#include - #include --#include --#include - #include - #include - #include --#include --#include - #include - #include --#include - #include - #include --#include - #include - #include - -@@ -76,14 +70,9 @@ static struct argp argp = - options, parse_opt, args_doc, doc, NULL, more_help, NULL - }; - --// File descriptor of /proc/*/mem file. --static int memfd; -- --/* Name of the executable */ --static char *exe; - - /* Local functions. */ --static int get_process_info (int dfd, long int pid); -+static int get_process_info (const char *exe, int dfd, long int pid); - static void wait_for_ptrace_stop (long int pid); - - -@@ -102,8 +91,10 @@ main (int argc, char *argv[]) - return 1; - } - -- assert (sizeof (pid_t) == sizeof (int) -- || sizeof (pid_t) == sizeof (long int)); -+ _Static_assert (sizeof (pid_t) == sizeof (int) -+ || sizeof (pid_t) == sizeof (long int), -+ "sizeof (pid_t) != sizeof (int) or sizeof (long int)"); -+ - char *endp; - errno = 0; - long int pid = strtol (argv[remaining], &endp, 10); -@@ -119,25 +110,24 @@ main (int argc, char *argv[]) - if (dfd == -1) - error (EXIT_FAILURE, errno, gettext ("cannot open %s"), buf); - -- struct scratch_buffer exebuf; -- scratch_buffer_init (&exebuf); -+ /* Name of the executable */ -+ struct scratch_buffer exe; -+ scratch_buffer_init (&exe); - ssize_t nexe; - while ((nexe = readlinkat (dfd, "exe", -- exebuf.data, exebuf.length)) == exebuf.length) -+ exe.data, exe.length)) == exe.length) - { -- if (!scratch_buffer_grow (&exebuf)) -+ if (!scratch_buffer_grow (&exe)) - { - nexe = -1; - break; - } - } - if (nexe == -1) -- exe = (char *) ""; -+ /* Default stack allocation is at least 1024. */ -+ snprintf (exe.data, exe.length, ""); - else -- { -- exe = exebuf.data; -- exe[nexe] = '\0'; -- } -+ ((char*)exe.data)[nexe] = '\0'; - - /* Stop all threads since otherwise the list of loaded modules might - change while we are reading it. */ -@@ -155,8 +145,8 @@ main (int argc, char *argv[]) - error (EXIT_FAILURE, errno, gettext ("cannot prepare reading %s/task"), - buf); - -- struct dirent64 *d; -- while ((d = readdir64 (dir)) != NULL) -+ struct dirent *d; -+ while ((d = readdir (dir)) != NULL) - { - if (! isdigit (d->d_name[0])) - continue; -@@ -182,7 +172,7 @@ main (int argc, char *argv[]) - - wait_for_ptrace_stop (tid); - -- struct thread_list *newp = alloca (sizeof (*newp)); -+ struct thread_list *newp = xmalloc (sizeof (*newp)); - newp->tid = tid; - newp->next = thread_list; - thread_list = newp; -@@ -190,17 +180,22 @@ main (int argc, char *argv[]) - - closedir (dir); - -- int status = get_process_info (dfd, pid); -+ if (thread_list == NULL) -+ error (EXIT_FAILURE, 0, gettext ("no valid %s/task entries"), buf); -+ -+ int status = get_process_info (exe.data, dfd, pid); - -- assert (thread_list != NULL); - do - { - ptrace (PTRACE_DETACH, thread_list->tid, NULL, NULL); -+ struct thread_list *prev = thread_list; - thread_list = thread_list->next; -+ free (prev); - } - while (thread_list != NULL); - - close (dfd); -+ scratch_buffer_free (&exe); - - return status; - } -@@ -281,9 +276,10 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\ - - - static int --get_process_info (int dfd, long int pid) -+get_process_info (const char *exe, int dfd, long int pid) - { -- memfd = openat (dfd, "mem", O_RDONLY); -+ /* File descriptor of /proc//mem file. */ -+ int memfd = openat (dfd, "mem", O_RDONLY); - if (memfd == -1) - goto no_info; - -@@ -333,9 +329,9 @@ get_process_info (int dfd, long int pid) - - int retval; - if (e_ident[EI_CLASS] == ELFCLASS32) -- retval = find_maps32 (pid, auxv, auxv_size); -+ retval = find_maps32 (exe, memfd, pid, auxv, auxv_size); - else -- retval = find_maps64 (pid, auxv, auxv_size); -+ retval = find_maps64 (exe, memfd, pid, auxv, auxv_size); - - free (auxv); - close (memfd); -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/ja_JP b/localedata/locales/ja_JP -index 1fd2fee44b..30190b6248 100644 ---- a/localedata/locales/ja_JP -+++ b/localedata/locales/ja_JP -@@ -14946,7 +14946,9 @@ am_pm "";"" - - t_fmt_ampm "%p%I%M%S" - --era "+:2:1990//01//01:+*::%EC%Ey";/ -+era "+:2:2020//01//01:+*::%EC%Ey";/ -+ "+:1:2019//05//01:2019//12//31::%EC";/ -+ "+:2:1990//01//01:2019//04//30::%EC%Ey";/ - "+:1:1989//01//08:1989//12//31::%EC";/ - "+:2:1927//01//01:1989//01//07::%EC%Ey";/ - "+:1:1926//12//25:1926//12//31::%EC";/ -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/pthreadP.h b/nptl/pthreadP.h -index 13bdb11133..19efe1e35f 100644 ---- a/nptl/pthreadP.h -+++ b/nptl/pthreadP.h -@@ -110,19 +110,23 @@ enum - }; - #define PTHREAD_MUTEX_PSHARED_BIT 128 - -+/* See concurrency notes regarding __kind in struct __pthread_mutex_s -+ in sysdeps/nptl/bits/thread-shared-types.h. */ - #define PTHREAD_MUTEX_TYPE(m) \ -- ((m)->__data.__kind & 127) -+ (atomic_load_relaxed (&((m)->__data.__kind)) & 127) - /* Don't include NO_ELISION, as that type is always the same - as the underlying lock type. */ - #define PTHREAD_MUTEX_TYPE_ELISION(m) \ -- ((m)->__data.__kind & (127|PTHREAD_MUTEX_ELISION_NP)) -+ (atomic_load_relaxed (&((m)->__data.__kind)) \ -+ & (127 | PTHREAD_MUTEX_ELISION_NP)) - - #if LLL_PRIVATE == 0 && LLL_SHARED == 128 - # define PTHREAD_MUTEX_PSHARED(m) \ -- ((m)->__data.__kind & 128) -+ (atomic_load_relaxed (&((m)->__data.__kind)) & 128) - #else - # define PTHREAD_MUTEX_PSHARED(m) \ -- (((m)->__data.__kind & 128) ? LLL_SHARED : LLL_PRIVATE) -+ ((atomic_load_relaxed (&((m)->__data.__kind)) & 128) \ -+ ? LLL_SHARED : LLL_PRIVATE) - #endif - - /* The kernel when waking robust mutexes on exit never uses -diff --git a/nptl/pthread_cond_common.c b/nptl/pthread_cond_common.c -index 8e425eb01e..479e54febb 100644 ---- a/nptl/pthread_cond_common.c -+++ b/nptl/pthread_cond_common.c -@@ -405,8 +405,12 @@ __condvar_quiesce_and_switch_g1 (pthread_cond_t *cond, uint64_t wseq, - { - /* There is still a waiter after spinning. Set the wake-request - flag and block. Relaxed MO is fine because this is just about -- this futex word. */ -- r = atomic_fetch_or_relaxed (cond->__data.__g_refs + g1, 1); -+ this futex word. -+ -+ Update r to include the set wake-request flag so that the upcoming -+ futex_wait only blocks if the flag is still set (otherwise, we'd -+ violate the basic client-side futex protocol). */ -+ r = atomic_fetch_or_relaxed (cond->__data.__g_refs + g1, 1) | 1; - - if ((r >> 1) > 0) - futex_wait_simple (cond->__data.__g_refs + g1, r, private); -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/pthread_mutex_consistent.c b/nptl/pthread_mutex_consistent.c -index 85b8e1a6cb..4fbd875430 100644 ---- a/nptl/pthread_mutex_consistent.c -+++ b/nptl/pthread_mutex_consistent.c -@@ -23,8 +23,11 @@ - int - pthread_mutex_consistent (pthread_mutex_t *mutex) - { -- /* Test whether this is a robust mutex with a dead owner. */ -- if ((mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP) == 0 -+ /* Test whether this is a robust mutex with a dead owner. -+ See concurrency notes regarding __kind in struct __pthread_mutex_s -+ in sysdeps/nptl/bits/thread-shared-types.h. */ -+ if ((atomic_load_relaxed (&(mutex->__data.__kind)) -+ & PTHREAD_MUTEX_ROBUST_NORMAL_NP) == 0 - || mutex->__data.__owner != PTHREAD_MUTEX_INCONSISTENT) - return EINVAL; - -diff --git a/nptl/pthread_mutex_destroy.c b/nptl/pthread_mutex_destroy.c -index 5a22611541..713ea68496 100644 ---- a/nptl/pthread_mutex_destroy.c -+++ b/nptl/pthread_mutex_destroy.c -@@ -27,12 +27,17 @@ __pthread_mutex_destroy (pthread_mutex_t *mutex) - { - LIBC_PROBE (mutex_destroy, 1, mutex); - -- if ((mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP) == 0 -+ /* See concurrency notes regarding __kind in struct __pthread_mutex_s -+ in sysdeps/nptl/bits/thread-shared-types.h. */ -+ if ((atomic_load_relaxed (&(mutex->__data.__kind)) -+ & PTHREAD_MUTEX_ROBUST_NORMAL_NP) == 0 - && mutex->__data.__nusers != 0) - return EBUSY; - -- /* Set to an invalid value. */ -- mutex->__data.__kind = -1; -+ /* Set to an invalid value. Relaxed MO is enough as it is undefined behavior -+ if the mutex is used after it has been destroyed. But you can reinitialize -+ it with pthread_mutex_init. */ -+ atomic_store_relaxed (&(mutex->__data.__kind), -1); - - return 0; - } -diff --git a/nptl/pthread_mutex_init.c b/nptl/pthread_mutex_init.c -index d8fe473728..5cf290c272 100644 ---- a/nptl/pthread_mutex_init.c -+++ b/nptl/pthread_mutex_init.c -@@ -101,7 +101,7 @@ __pthread_mutex_init (pthread_mutex_t *mutex, - memset (mutex, '\0', __SIZEOF_PTHREAD_MUTEX_T); - - /* Copy the values from the attribute. */ -- mutex->__data.__kind = imutexattr->mutexkind & ~PTHREAD_MUTEXATTR_FLAG_BITS; -+ int mutex_kind = imutexattr->mutexkind & ~PTHREAD_MUTEXATTR_FLAG_BITS; - - if ((imutexattr->mutexkind & PTHREAD_MUTEXATTR_FLAG_ROBUST) != 0) - { -@@ -111,17 +111,17 @@ __pthread_mutex_init (pthread_mutex_t *mutex, - return ENOTSUP; - #endif - -- mutex->__data.__kind |= PTHREAD_MUTEX_ROBUST_NORMAL_NP; -+ mutex_kind |= PTHREAD_MUTEX_ROBUST_NORMAL_NP; - } - - switch (imutexattr->mutexkind & PTHREAD_MUTEXATTR_PROTOCOL_MASK) - { - case PTHREAD_PRIO_INHERIT << PTHREAD_MUTEXATTR_PROTOCOL_SHIFT: -- mutex->__data.__kind |= PTHREAD_MUTEX_PRIO_INHERIT_NP; -+ mutex_kind |= PTHREAD_MUTEX_PRIO_INHERIT_NP; - break; - - case PTHREAD_PRIO_PROTECT << PTHREAD_MUTEXATTR_PROTOCOL_SHIFT: -- mutex->__data.__kind |= PTHREAD_MUTEX_PRIO_PROTECT_NP; -+ mutex_kind |= PTHREAD_MUTEX_PRIO_PROTECT_NP; - - int ceiling = (imutexattr->mutexkind - & PTHREAD_MUTEXATTR_PRIO_CEILING_MASK) -@@ -145,7 +145,11 @@ __pthread_mutex_init (pthread_mutex_t *mutex, - FUTEX_PRIVATE_FLAG FUTEX_WAKE. */ - if ((imutexattr->mutexkind & (PTHREAD_MUTEXATTR_FLAG_PSHARED - | PTHREAD_MUTEXATTR_FLAG_ROBUST)) != 0) -- mutex->__data.__kind |= PTHREAD_MUTEX_PSHARED_BIT; -+ mutex_kind |= PTHREAD_MUTEX_PSHARED_BIT; -+ -+ /* See concurrency notes regarding __kind in struct __pthread_mutex_s -+ in sysdeps/nptl/bits/thread-shared-types.h. */ -+ atomic_store_relaxed (&(mutex->__data.__kind), mutex_kind); - - /* Default values: mutex not used yet. */ - // mutex->__count = 0; already done by memset -diff --git a/nptl/pthread_mutex_lock.c b/nptl/pthread_mutex_lock.c -index 1519c142bd..29cc143e6c 100644 ---- a/nptl/pthread_mutex_lock.c -+++ b/nptl/pthread_mutex_lock.c -@@ -62,6 +62,8 @@ static int __pthread_mutex_lock_full (pthread_mutex_t *mutex) - int - __pthread_mutex_lock (pthread_mutex_t *mutex) - { -+ /* See concurrency notes regarding mutex type which is loaded from __kind -+ in struct __pthread_mutex_s in sysdeps/nptl/bits/thread-shared-types.h. */ - unsigned int type = PTHREAD_MUTEX_TYPE_ELISION (mutex); - - LIBC_PROBE (mutex_entry, 1, mutex); -@@ -350,8 +352,14 @@ __pthread_mutex_lock_full (pthread_mutex_t *mutex) - case PTHREAD_MUTEX_PI_ROBUST_NORMAL_NP: - case PTHREAD_MUTEX_PI_ROBUST_ADAPTIVE_NP: - { -- int kind = mutex->__data.__kind & PTHREAD_MUTEX_KIND_MASK_NP; -- int robust = mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP; -+ int kind, robust; -+ { -+ /* See concurrency notes regarding __kind in struct __pthread_mutex_s -+ in sysdeps/nptl/bits/thread-shared-types.h. */ -+ int mutex_kind = atomic_load_relaxed (&(mutex->__data.__kind)); -+ kind = mutex_kind & PTHREAD_MUTEX_KIND_MASK_NP; -+ robust = mutex_kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP; -+ } - - if (robust) - { -@@ -502,7 +510,10 @@ __pthread_mutex_lock_full (pthread_mutex_t *mutex) - case PTHREAD_MUTEX_PP_NORMAL_NP: - case PTHREAD_MUTEX_PP_ADAPTIVE_NP: - { -- int kind = mutex->__data.__kind & PTHREAD_MUTEX_KIND_MASK_NP; -+ /* See concurrency notes regarding __kind in struct __pthread_mutex_s -+ in sysdeps/nptl/bits/thread-shared-types.h. */ -+ int kind = atomic_load_relaxed (&(mutex->__data.__kind)) -+ & PTHREAD_MUTEX_KIND_MASK_NP; - - oldval = mutex->__data.__lock; - -@@ -607,15 +618,18 @@ hidden_def (__pthread_mutex_lock) - void - __pthread_mutex_cond_lock_adjust (pthread_mutex_t *mutex) - { -- assert ((mutex->__data.__kind & PTHREAD_MUTEX_PRIO_INHERIT_NP) != 0); -- assert ((mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP) == 0); -- assert ((mutex->__data.__kind & PTHREAD_MUTEX_PSHARED_BIT) == 0); -+ /* See concurrency notes regarding __kind in struct __pthread_mutex_s -+ in sysdeps/nptl/bits/thread-shared-types.h. */ -+ int mutex_kind = atomic_load_relaxed (&(mutex->__data.__kind)); -+ assert ((mutex_kind & PTHREAD_MUTEX_PRIO_INHERIT_NP) != 0); -+ assert ((mutex_kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP) == 0); -+ assert ((mutex_kind & PTHREAD_MUTEX_PSHARED_BIT) == 0); - - /* Record the ownership. */ - pid_t id = THREAD_GETMEM (THREAD_SELF, tid); - mutex->__data.__owner = id; - -- if (mutex->__data.__kind == PTHREAD_MUTEX_PI_RECURSIVE_NP) -+ if (mutex_kind == PTHREAD_MUTEX_PI_RECURSIVE_NP) - ++mutex->__data.__count; - } - #endif -diff --git a/nptl/pthread_mutex_setprioceiling.c b/nptl/pthread_mutex_setprioceiling.c -index 8594874f85..8306cabcf4 100644 ---- a/nptl/pthread_mutex_setprioceiling.c -+++ b/nptl/pthread_mutex_setprioceiling.c -@@ -27,9 +27,10 @@ int - pthread_mutex_setprioceiling (pthread_mutex_t *mutex, int prioceiling, - int *old_ceiling) - { -- /* The low bits of __kind aren't ever changed after pthread_mutex_init, -- so we don't need a lock yet. */ -- if ((mutex->__data.__kind & PTHREAD_MUTEX_PRIO_PROTECT_NP) == 0) -+ /* See concurrency notes regarding __kind in struct __pthread_mutex_s -+ in sysdeps/nptl/bits/thread-shared-types.h. */ -+ if ((atomic_load_relaxed (&(mutex->__data.__kind)) -+ & PTHREAD_MUTEX_PRIO_PROTECT_NP) == 0) - return EINVAL; - - /* See __init_sched_fifo_prio. */ -diff --git a/nptl/pthread_mutex_timedlock.c b/nptl/pthread_mutex_timedlock.c -index 28237b0e58..888c12fe28 100644 ---- a/nptl/pthread_mutex_timedlock.c -+++ b/nptl/pthread_mutex_timedlock.c -@@ -53,6 +53,8 @@ __pthread_mutex_timedlock (pthread_mutex_t *mutex, - /* We must not check ABSTIME here. If the thread does not block - abstime must not be checked for a valid value. */ - -+ /* See concurrency notes regarding mutex type which is loaded from __kind -+ in struct __pthread_mutex_s in sysdeps/nptl/bits/thread-shared-types.h. */ - switch (__builtin_expect (PTHREAD_MUTEX_TYPE_ELISION (mutex), - PTHREAD_MUTEX_TIMED_NP)) - { -@@ -338,8 +340,14 @@ __pthread_mutex_timedlock (pthread_mutex_t *mutex, - case PTHREAD_MUTEX_PI_ROBUST_NORMAL_NP: - case PTHREAD_MUTEX_PI_ROBUST_ADAPTIVE_NP: - { -- int kind = mutex->__data.__kind & PTHREAD_MUTEX_KIND_MASK_NP; -- int robust = mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP; -+ int kind, robust; -+ { -+ /* See concurrency notes regarding __kind in struct __pthread_mutex_s -+ in sysdeps/nptl/bits/thread-shared-types.h. */ -+ int mutex_kind = atomic_load_relaxed (&(mutex->__data.__kind)); -+ kind = mutex_kind & PTHREAD_MUTEX_KIND_MASK_NP; -+ robust = mutex_kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP; -+ } - - if (robust) - { -@@ -509,7 +517,10 @@ __pthread_mutex_timedlock (pthread_mutex_t *mutex, - case PTHREAD_MUTEX_PP_NORMAL_NP: - case PTHREAD_MUTEX_PP_ADAPTIVE_NP: - { -- int kind = mutex->__data.__kind & PTHREAD_MUTEX_KIND_MASK_NP; -+ /* See concurrency notes regarding __kind in struct __pthread_mutex_s -+ in sysdeps/nptl/bits/thread-shared-types.h. */ -+ int kind = atomic_load_relaxed (&(mutex->__data.__kind)) -+ & PTHREAD_MUTEX_KIND_MASK_NP; - - oldval = mutex->__data.__lock; - -diff --git a/nptl/pthread_mutex_trylock.c b/nptl/pthread_mutex_trylock.c -index 7de61f4f68..8e01113b0f 100644 ---- a/nptl/pthread_mutex_trylock.c -+++ b/nptl/pthread_mutex_trylock.c -@@ -36,6 +36,8 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex) - int oldval; - pid_t id = THREAD_GETMEM (THREAD_SELF, tid); - -+ /* See concurrency notes regarding mutex type which is loaded from __kind -+ in struct __pthread_mutex_s in sysdeps/nptl/bits/thread-shared-types.h. */ - switch (__builtin_expect (PTHREAD_MUTEX_TYPE_ELISION (mutex), - PTHREAD_MUTEX_TIMED_NP)) - { -@@ -92,6 +94,9 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex) - case PTHREAD_MUTEX_ROBUST_ADAPTIVE_NP: - THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, - &mutex->__data.__list.__next); -+ /* We need to set op_pending before starting the operation. Also -+ see comments at ENQUEUE_MUTEX. */ -+ __asm ("" ::: "memory"); - - oldval = mutex->__data.__lock; - do -@@ -117,7 +122,12 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex) - /* But it is inconsistent unless marked otherwise. */ - mutex->__data.__owner = PTHREAD_MUTEX_INCONSISTENT; - -+ /* We must not enqueue the mutex before we have acquired it. -+ Also see comments at ENQUEUE_MUTEX. */ -+ __asm ("" ::: "memory"); - ENQUEUE_MUTEX (mutex); -+ /* We need to clear op_pending after we enqueue the mutex. */ -+ __asm ("" ::: "memory"); - THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); - - /* Note that we deliberately exist here. If we fall -@@ -133,6 +143,8 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex) - int kind = PTHREAD_MUTEX_TYPE (mutex); - if (kind == PTHREAD_MUTEX_ROBUST_ERRORCHECK_NP) - { -+ /* We do not need to ensure ordering wrt another memory -+ access. Also see comments at ENQUEUE_MUTEX. */ - THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, - NULL); - return EDEADLK; -@@ -140,6 +152,8 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex) - - if (kind == PTHREAD_MUTEX_ROBUST_RECURSIVE_NP) - { -+ /* We do not need to ensure ordering wrt another memory -+ access. */ - THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, - NULL); - -@@ -158,6 +172,9 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex) - id, 0); - if (oldval != 0 && (oldval & FUTEX_OWNER_DIED) == 0) - { -+ /* We haven't acquired the lock as it is already acquired by -+ another owner. We do not need to ensure ordering wrt another -+ memory access. */ - THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); - - return EBUSY; -@@ -171,13 +188,20 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex) - if (oldval == id) - lll_unlock (mutex->__data.__lock, - PTHREAD_ROBUST_MUTEX_PSHARED (mutex)); -+ /* FIXME This violates the mutex destruction requirements. See -+ __pthread_mutex_unlock_full. */ - THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); - return ENOTRECOVERABLE; - } - } - while ((oldval & FUTEX_OWNER_DIED) != 0); - -+ /* We must not enqueue the mutex before we have acquired it. -+ Also see comments at ENQUEUE_MUTEX. */ -+ __asm ("" ::: "memory"); - ENQUEUE_MUTEX (mutex); -+ /* We need to clear op_pending after we enqueue the mutex. */ -+ __asm ("" ::: "memory"); - THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); - - mutex->__data.__owner = id; -@@ -199,14 +223,25 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex) - case PTHREAD_MUTEX_PI_ROBUST_NORMAL_NP: - case PTHREAD_MUTEX_PI_ROBUST_ADAPTIVE_NP: - { -- int kind = mutex->__data.__kind & PTHREAD_MUTEX_KIND_MASK_NP; -- int robust = mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP; -+ int kind, robust; -+ { -+ /* See concurrency notes regarding __kind in struct __pthread_mutex_s -+ in sysdeps/nptl/bits/thread-shared-types.h. */ -+ int mutex_kind = atomic_load_relaxed (&(mutex->__data.__kind)); -+ kind = mutex_kind & PTHREAD_MUTEX_KIND_MASK_NP; -+ robust = mutex_kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP; -+ } - - if (robust) -- /* Note: robust PI futexes are signaled by setting bit 0. */ -- THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, -- (void *) (((uintptr_t) &mutex->__data.__list.__next) -- | 1)); -+ { -+ /* Note: robust PI futexes are signaled by setting bit 0. */ -+ THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, -+ (void *) (((uintptr_t) &mutex->__data.__list.__next) -+ | 1)); -+ /* We need to set op_pending before starting the operation. Also -+ see comments at ENQUEUE_MUTEX. */ -+ __asm ("" ::: "memory"); -+ } - - oldval = mutex->__data.__lock; - -@@ -215,12 +250,16 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex) - { - if (kind == PTHREAD_MUTEX_ERRORCHECK_NP) - { -+ /* We do not need to ensure ordering wrt another memory -+ access. */ - THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); - return EDEADLK; - } - - if (kind == PTHREAD_MUTEX_RECURSIVE_NP) - { -+ /* We do not need to ensure ordering wrt another memory -+ access. */ - THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); - - /* Just bump the counter. */ -@@ -242,6 +281,9 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex) - { - if ((oldval & FUTEX_OWNER_DIED) == 0) - { -+ /* We haven't acquired the lock as it is already acquired by -+ another owner. We do not need to ensure ordering wrt another -+ memory access. */ - THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); - - return EBUSY; -@@ -262,6 +304,9 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex) - if (INTERNAL_SYSCALL_ERROR_P (e, __err) - && INTERNAL_SYSCALL_ERRNO (e, __err) == EWOULDBLOCK) - { -+ /* The kernel has not yet finished the mutex owner death. -+ We do not need to ensure ordering wrt another memory -+ access. */ - THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); - - return EBUSY; -@@ -279,7 +324,12 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex) - /* But it is inconsistent unless marked otherwise. */ - mutex->__data.__owner = PTHREAD_MUTEX_INCONSISTENT; - -+ /* We must not enqueue the mutex before we have acquired it. -+ Also see comments at ENQUEUE_MUTEX. */ -+ __asm ("" ::: "memory"); - ENQUEUE_MUTEX (mutex); -+ /* We need to clear op_pending after we enqueue the mutex. */ -+ __asm ("" ::: "memory"); - THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); - - /* Note that we deliberately exit here. If we fall -@@ -302,13 +352,20 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex) - PTHREAD_ROBUST_MUTEX_PSHARED (mutex)), - 0, 0); - -+ /* To the kernel, this will be visible after the kernel has -+ acquired the mutex in the syscall. */ - THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); - return ENOTRECOVERABLE; - } - - if (robust) - { -+ /* We must not enqueue the mutex before we have acquired it. -+ Also see comments at ENQUEUE_MUTEX. */ -+ __asm ("" ::: "memory"); - ENQUEUE_MUTEX_PI (mutex); -+ /* We need to clear op_pending after we enqueue the mutex. */ -+ __asm ("" ::: "memory"); - THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); - } - -@@ -325,7 +382,10 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex) - case PTHREAD_MUTEX_PP_NORMAL_NP: - case PTHREAD_MUTEX_PP_ADAPTIVE_NP: - { -- int kind = mutex->__data.__kind & PTHREAD_MUTEX_KIND_MASK_NP; -+ /* See concurrency notes regarding __kind in struct __pthread_mutex_s -+ in sysdeps/nptl/bits/thread-shared-types.h. */ -+ int kind = atomic_load_relaxed (&(mutex->__data.__kind)) -+ & PTHREAD_MUTEX_KIND_MASK_NP; - - oldval = mutex->__data.__lock; - -diff --git a/nptl/pthread_mutex_unlock.c b/nptl/pthread_mutex_unlock.c -index 9ea62943b7..68d04d5395 100644 ---- a/nptl/pthread_mutex_unlock.c -+++ b/nptl/pthread_mutex_unlock.c -@@ -35,6 +35,8 @@ int - attribute_hidden - __pthread_mutex_unlock_usercnt (pthread_mutex_t *mutex, int decr) - { -+ /* See concurrency notes regarding mutex type which is loaded from __kind -+ in struct __pthread_mutex_s in sysdeps/nptl/bits/thread-shared-types.h. */ - int type = PTHREAD_MUTEX_TYPE_ELISION (mutex); - if (__builtin_expect (type & - ~(PTHREAD_MUTEX_KIND_MASK_NP|PTHREAD_MUTEX_ELISION_FLAGS_NP), 0)) -@@ -222,13 +224,19 @@ __pthread_mutex_unlock_full (pthread_mutex_t *mutex, int decr) - /* If the previous owner died and the caller did not succeed in - making the state consistent, mark the mutex as unrecoverable - and make all waiters. */ -- if ((mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP) != 0 -+ /* See concurrency notes regarding __kind in struct __pthread_mutex_s -+ in sysdeps/nptl/bits/thread-shared-types.h. */ -+ if ((atomic_load_relaxed (&(mutex->__data.__kind)) -+ & PTHREAD_MUTEX_ROBUST_NORMAL_NP) != 0 - && __builtin_expect (mutex->__data.__owner - == PTHREAD_MUTEX_INCONSISTENT, 0)) - pi_notrecoverable: - newowner = PTHREAD_MUTEX_NOTRECOVERABLE; - -- if ((mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP) != 0) -+ /* See concurrency notes regarding __kind in struct __pthread_mutex_s -+ in sysdeps/nptl/bits/thread-shared-types.h. */ -+ if ((atomic_load_relaxed (&(mutex->__data.__kind)) -+ & PTHREAD_MUTEX_ROBUST_NORMAL_NP) != 0) - { - continue_pi_robust: - /* Remove mutex from the list. -@@ -251,7 +259,10 @@ __pthread_mutex_unlock_full (pthread_mutex_t *mutex, int decr) - /* Unlock. Load all necessary mutex data before releasing the mutex - to not violate the mutex destruction requirements (see - lll_unlock). */ -- int robust = mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP; -+ /* See concurrency notes regarding __kind in struct __pthread_mutex_s -+ in sysdeps/nptl/bits/thread-shared-types.h. */ -+ int robust = atomic_load_relaxed (&(mutex->__data.__kind)) -+ & PTHREAD_MUTEX_ROBUST_NORMAL_NP; - private = (robust - ? PTHREAD_ROBUST_MUTEX_PSHARED (mutex) - : PTHREAD_MUTEX_PSHARED (mutex)); -diff --git a/nptl/pthread_rwlock_common.c b/nptl/pthread_rwlock_common.c -index a290d08332..9ce36d1026 100644 ---- a/nptl/pthread_rwlock_common.c -+++ b/nptl/pthread_rwlock_common.c -@@ -314,8 +314,8 @@ __pthread_rwlock_rdlock_full (pthread_rwlock_t *rwlock, - harmless because the flag is just about the state of - __readers, and all threads set the flag under the same - conditions. */ -- while ((atomic_load_relaxed (&rwlock->__data.__readers) -- & PTHREAD_RWLOCK_RWAITING) != 0) -+ while (((r = atomic_load_relaxed (&rwlock->__data.__readers)) -+ & PTHREAD_RWLOCK_RWAITING) != 0) - { - int private = __pthread_rwlock_get_private (rwlock); - int err = futex_abstimed_wait (&rwlock->__data.__readers, -diff --git a/nptl/pthread_rwlock_tryrdlock.c b/nptl/pthread_rwlock_tryrdlock.c -index 4aec1fc15a..31a88d33a6 100644 ---- a/nptl/pthread_rwlock_tryrdlock.c -+++ b/nptl/pthread_rwlock_tryrdlock.c -@@ -94,15 +94,22 @@ __pthread_rwlock_tryrdlock (pthread_rwlock_t *rwlock) - /* Same as in __pthread_rwlock_rdlock_full: - 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 use because other readers cannot distinguish between -+ us and the writer. -+ Note that __pthread_rwlock_tryrdlock callers will not have to be -+ woken up because they will either see the read phase started by us -+ or they will try to start it themselves; however, callers of -+ __pthread_rwlock_rdlock_full just increase the reader count and then -+ check what state the lock is in, so they cannot distinguish between -+ us and a writer that acquired and released the lock in the -+ meantime. */ -+ 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; -diff --git a/nptl/pthread_rwlock_trywrlock.c b/nptl/pthread_rwlock_trywrlock.c -index 5a73eba756..f2e3443466 100644 ---- a/nptl/pthread_rwlock_trywrlock.c -+++ b/nptl/pthread_rwlock_trywrlock.c -@@ -46,8 +46,15 @@ __pthread_rwlock_trywrlock (pthread_rwlock_t *rwlock) - &rwlock->__data.__readers, &r, - r | PTHREAD_RWLOCK_WRPHASE | PTHREAD_RWLOCK_WRLOCKED)) - { -+ /* We have become the primary writer and we cannot have shared -+ the PTHREAD_RWLOCK_FUTEX_USED flag with someone else, so we -+ can simply enable blocking (see full wrlock code). */ - atomic_store_relaxed (&rwlock->__data.__writers_futex, 1); -- atomic_store_relaxed (&rwlock->__data.__wrphase_futex, 1); -+ /* If we started a write phase, we need to enable readers to -+ wait. If we did not, we must not change it because other threads -+ may have set the PTHREAD_RWLOCK_FUTEX_USED in the meantime. */ -+ if ((r & PTHREAD_RWLOCK_WRPHASE) == 0) -+ atomic_store_relaxed (&rwlock->__data.__wrphase_futex, 1); - atomic_store_relaxed (&rwlock->__data.__cur_writer, - THREAD_GETMEM (THREAD_SELF, tid)); - return 0; -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/s390/dl-procinfo.h b/sysdeps/s390/dl-procinfo.h -index b0383bfb4c..f71d64c3ab 100644 ---- a/sysdeps/s390/dl-procinfo.h -+++ b/sysdeps/s390/dl-procinfo.h -@@ -57,7 +57,8 @@ enum - }; - - #define HWCAP_IMPORTANT (HWCAP_S390_ZARCH | HWCAP_S390_LDISP \ -- | HWCAP_S390_EIMM | HWCAP_S390_DFP) -+ | HWCAP_S390_EIMM | HWCAP_S390_DFP \ -+ | HWCAP_S390_VX | HWCAP_S390_VXE) - - /* We cannot provide a general printing function. */ - #define _dl_procinfo(type, word) -1 -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-elf-rtld.diff b/glibc-2.25-elf-rtld.diff index 93b4f88..3c66f34 100644 --- a/glibc-2.25-elf-rtld.diff +++ b/glibc-2.25-elf-rtld.diff @@ -27,9 +27,9 @@ diff -ur glibc-2.14.1-orig/elf/rtld.c glibc-2.14.1/elf/rtld.c @@ -1021,6 +1030,7 @@ variable LD_LIBRARY_PATH\n\ --inhibit-rpath LIST ignore RUNPATH and RPATH information in object names\n\ - in LIST\n\ + in LIST\n\ + --argv0 STRING use STRING as argv[0]\n\ - --audit LIST use objects named in LIST as auditors\n"); + --audit LIST use objects named in LIST as auditors\n\ ++_dl_skip_args; @@ -1073,6 +1083,8 @@ diff --git a/glibc-2.28.tar.xz b/glibc-2.30.tar.xz similarity index 64% rename from glibc-2.28.tar.xz rename to glibc-2.30.tar.xz index 6ae1e01..a30886e 100644 Binary files a/glibc-2.28.tar.xz and b/glibc-2.30.tar.xz differ diff --git a/glibc.changes b/glibc.changes index 460e71f..bbb5ae6 100644 --- a/glibc.changes +++ b/glibc.changes @@ -1,3 +1,6 @@ +* Thu Jan 27 2020 Marko Lemmetty - 2.30+git1 +- Update to 2.30 version. Fixes JB#48615 + * Thu Jan 02 2020 Niels Breet - 2.28+git7 - Remove hardcoded libdir for aarch64. Contributes to JB#47986 diff --git a/glibc.spec b/glibc.spec index 29d4553..aed5411 100644 --- a/glibc.spec +++ b/glibc.spec @@ -1,16 +1,15 @@ -%define glibcsrcdir glibc-2.28 +%define glibcsrcdir glibc-2.30 # Default: Always disable the benchtests. %bcond_with benchtests Name: glibc Summary: GNU C library shared libraries -Version: 2.28+git7 +Version: 2.30+git1 Release: 0 License: LGPLv2+ and LGPLv2+ with exceptions and GPLv2+ -Group: System/Libraries URL: http://www.gnu.org/software/libc/ -Source0: glibc-2.28.tar.xz +Source0: glibc-2.30.tar.xz Source1: build-locale-archive.c Patch1: glibc-arm-alignment-fix.patch @@ -24,7 +23,6 @@ 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.27-bits.patch -Patch13: git-updates.diff Provides: ldconfig # The dynamic linker supports DT_GNU_HASH @@ -74,6 +72,7 @@ BuildRequires: rpm >= 4.2-0.56 BuildRequires: bison >= 2.7 # GNU make 4.0 introduced the -O option. BuildRequires: make >= 4.0 +BuildRequires: python3-base %define __find_provides %{_builddir}/%{glibcsrcdir}/find_provides.sh %define _filter_GLIBC_PRIVATE 1 @@ -222,7 +221,6 @@ cd %{glibcsrcdir} %endif %patch11 -p1 %patch12 -p1 -%patch13 -p1 %build GCC=gcc