git-updates
authorGNU Libc Maintainers <debian-glibc@lists.debian.org>
Sat, 9 Feb 2019 17:34:27 +0000 (17:34 +0000)
committerSamuel Thibault <sthibault@debian.org>
Sat, 9 Feb 2019 17:34:27 +0000 (17:34 +0000)
GIT update of https://sourceware.org/git/glibc.git/release/2.28/master from glibc-2.28

Gbp-Pq: Name git-updates.diff

198 files changed:
ChangeLog
Makeconfig
NEWS
conform/data/signal.h-data
conform/data/sys/wait.h-data
dlfcn/dlerror.c
elf/Makefile
elf/dl-runtime.c
elf/tst-unwind-main.c [new file with mode: 0644]
grp/initgroups.c
htl/Versions
include/arpa/inet.h
include/link.h
include/stdio.h
inet/Makefile
inet/tst-if_index-long.c [new file with mode: 0644]
intl/dcigettext.c
libio/tst-readline.c
localedata/locales/kl_GL
malloc/Makefile
malloc/malloc.c
malloc/tst-tcfree1.c [new file with mode: 0644]
malloc/tst-tcfree2.c [new file with mode: 0644]
malloc/tst-tcfree3.c [new file with mode: 0644]
math/libm-test-fma.inc
misc/Makefile
misc/error.c
misc/tst-gethostid.c [new file with mode: 0644]
misc/tst-preadvwritev2-common.c
misc/tst-preadvwritev2.c
misc/tst-preadvwritev64v2.c
nptl/Makefile
nptl/pthreadP.h
nptl/pthread_cond_common.c
nptl/pthread_cond_wait.c
nptl/pthread_mutex_consistent.c
nptl/pthread_mutex_destroy.c
nptl/pthread_mutex_getprioceiling.c
nptl/pthread_mutex_init.c
nptl/pthread_mutex_lock.c
nptl/pthread_mutex_setprioceiling.c
nptl/pthread_mutex_timedlock.c
nptl/pthread_mutex_trylock.c
nptl/pthread_mutex_unlock.c
nptl/pthread_rwlock_common.c
nptl/tst-audit-threads-mod1.c [new file with mode: 0644]
nptl/tst-audit-threads-mod2.c [new file with mode: 0644]
nptl/tst-audit-threads.c [new file with mode: 0644]
nptl/tst-audit-threads.h [new file with mode: 0644]
nptl/tst-mutex10.c [new file with mode: 0644]
nptl/tst-rwlock-pwn.c [new file with mode: 0644]
nscd/Makefile
nscd/gai.c
nscd/gethstbynm3_r.c
nscd/initgrcache.c
nscd/netgroupcache.c
nscd/nscd-inet_addr.c [new file with mode: 0644]
nscd/nscd_conf.c
nss/Makefile
nss/digits_dots.c
nss/nss_files/files-alias.c
nss/nsswitch.c
nss/tst-nss-files-alias-leak.c [new file with mode: 0644]
posix/Makefile
posix/regex_internal.c
posix/tst-regcomp-truncated.c [new file with mode: 0644]
resolv/Makefile
resolv/Versions
resolv/gai_misc.c
resolv/inet_addr.c
resolv/nss_dns/dns-host.c
resolv/res_init.c
resolv/tst-aton.c
resolv/tst-inet_aton_exact.c [new file with mode: 0644]
resolv/tst-resolv-network.c
resolv/tst-resolv-nondecimal.c [new file with mode: 0644]
resolv/tst-resolv-trailing.c [new file with mode: 0644]
stdlib/test-bz22786.c
stdlib/tst-setcontext9.c
stdlib/tst-strtod-overflow.c
string/Makefile
string/strcasestr.c
string/strstr.c
string/test-strerror-errno.c [new file with mode: 0644]
string/test-strstr.c
support/Makefile
support/blob_repeat.c [new file with mode: 0644]
support/blob_repeat.h [new file with mode: 0644]
support/check.h
support/descriptors.h [new file with mode: 0644]
support/support.h
support/support_capture_subprocess.c
support/support_descriptors.c [new file with mode: 0644]
support/support_quote_string.c [new file with mode: 0644]
support/support_record_failure.c
support/support_test_main.c
support/tst-support_blob_repeat.c [new file with mode: 0644]
support/tst-support_descriptors.c [new file with mode: 0644]
support/tst-support_quote_string.c [new file with mode: 0644]
sysdeps/aarch64/dl-irel.h
sysdeps/alpha/fpu/libm-test-ulps
sysdeps/arm/dl-irel.h
sysdeps/generic/unwind-dw2.c
sysdeps/htl/pt-getspecific.c
sysdeps/htl/pt-setspecific.c
sysdeps/htl/pthreadP.h
sysdeps/i386/dl-cet.c [deleted file]
sysdeps/i386/dl-irel.h
sysdeps/i386/dl-machine.h
sysdeps/i386/start.S
sysdeps/ia64/fpu/e_exp2f.S
sysdeps/ia64/fpu/e_log2f.S
sysdeps/ia64/fpu/e_powf.S
sysdeps/ieee754/soft-fp/s_fdiv.c
sysdeps/nptl/bits/thread-shared-types.h
sysdeps/nptl/futex-internal.h
sysdeps/posix/getaddrinfo.c
sysdeps/powerpc/powerpc32/dl-irel.h
sysdeps/powerpc/powerpc64/addmul_1.S
sysdeps/powerpc/powerpc64/dl-irel.h
sysdeps/powerpc/powerpc64/lshift.S
sysdeps/powerpc/powerpc64/mul_1.S
sysdeps/riscv/rv64/rvd/libm-test-ulps
sysdeps/riscv/rvf/math_private.h
sysdeps/riscv/start.S
sysdeps/s390/dl-irel.h
sysdeps/sparc/sparc32/dl-irel.h
sysdeps/sparc/sparc64/dl-irel.h
sysdeps/unix/sysv/linux/Makefile
sysdeps/unix/sysv/linux/arm/atomic-machine.h
sysdeps/unix/sysv/linux/bits/types/siginfo_t.h
sysdeps/unix/sysv/linux/getdents64.c
sysdeps/unix/sysv/linux/gethostid.c
sysdeps/unix/sysv/linux/if_index.c
sysdeps/unix/sysv/linux/kernel_sigaction.h
sysdeps/unix/sysv/linux/m68k/kernel_sigaction.h
sysdeps/unix/sysv/linux/netlink_assert_response.c
sysdeps/unix/sysv/linux/nios2/kernel_sigaction.h
sysdeps/unix/sysv/linux/powerpc/force-elision.h
sysdeps/unix/sysv/linux/powerpc/kernel_sigaction.h
sysdeps/unix/sysv/linux/preadv2.c
sysdeps/unix/sysv/linux/preadv64v2.c
sysdeps/unix/sysv/linux/pwritev2.c
sysdeps/unix/sysv/linux/pwritev64v2.c
sysdeps/unix/sysv/linux/riscv/flush-icache.c
sysdeps/unix/sysv/linux/s390/force-elision.h
sysdeps/unix/sysv/linux/sh/kernel_sigaction.h
sysdeps/unix/sysv/linux/sparc/bits/siginfo-arch.h
sysdeps/unix/sysv/linux/sparc/kernel_sigaction.h
sysdeps/unix/sysv/linux/sparc/sparc64/Makefile
sysdeps/unix/sysv/linux/spawni.c
sysdeps/unix/sysv/linux/syscall-names.list
sysdeps/unix/sysv/linux/tst-readdir64-compat.c [new file with mode: 0644]
sysdeps/unix/sysv/linux/x86/force-elision.h
sysdeps/unix/sysv/linux/x86_64/sigaction.c
sysdeps/x86/cpu-features.c
sysdeps/x86/dl-prop.h
sysdeps/x86/link_map.h
sysdeps/x86_64/dl-irel.h
sysdeps/x86_64/memchr.S
sysdeps/x86_64/memcmp.S
sysdeps/x86_64/memrchr.S
sysdeps/x86_64/multiarch/memchr-avx2.S
sysdeps/x86_64/multiarch/memcmp-avx2-movbe.S
sysdeps/x86_64/multiarch/memcmp-sse4.S
sysdeps/x86_64/multiarch/memcmp-ssse3.S
sysdeps/x86_64/multiarch/memcpy-ssse3-back.S
sysdeps/x86_64/multiarch/memcpy-ssse3.S
sysdeps/x86_64/multiarch/memmove-avx512-no-vzeroupper.S
sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S
sysdeps/x86_64/multiarch/memrchr-avx2.S
sysdeps/x86_64/multiarch/memset-avx512-no-vzeroupper.S
sysdeps/x86_64/multiarch/memset-vec-unaligned-erms.S
sysdeps/x86_64/multiarch/strcmp-avx2.S
sysdeps/x86_64/multiarch/strcmp-sse42.S
sysdeps/x86_64/multiarch/strcpy-sse2-unaligned.S
sysdeps/x86_64/multiarch/strcpy-ssse3.S
sysdeps/x86_64/multiarch/strlen-avx2.S
sysdeps/x86_64/strcmp.S
sysdeps/x86_64/strlen.S
sysdeps/x86_64/x32/Makefile
sysdeps/x86_64/x32/test-size_t.h [new file with mode: 0644]
sysdeps/x86_64/x32/tst-size_t-memchr.c [new file with mode: 0644]
sysdeps/x86_64/x32/tst-size_t-memcmp-2.c [new file with mode: 0644]
sysdeps/x86_64/x32/tst-size_t-memcmp.c [new file with mode: 0644]
sysdeps/x86_64/x32/tst-size_t-memcpy.c [new file with mode: 0644]
sysdeps/x86_64/x32/tst-size_t-memrchr.c [new file with mode: 0644]
sysdeps/x86_64/x32/tst-size_t-memset.c [new file with mode: 0644]
sysdeps/x86_64/x32/tst-size_t-strncasecmp.c [new file with mode: 0644]
sysdeps/x86_64/x32/tst-size_t-strncmp.c [new file with mode: 0644]
sysdeps/x86_64/x32/tst-size_t-strncpy.c [new file with mode: 0644]
sysdeps/x86_64/x32/tst-size_t-strnlen.c [new file with mode: 0644]
sysdeps/x86_64/x32/tst-size_t-wcsncmp.c [new file with mode: 0644]
sysdeps/x86_64/x32/tst-size_t-wcsnlen.c [new file with mode: 0644]
sysdeps/x86_64/x32/tst-size_t-wmemchr.c [new file with mode: 0644]
sysdeps/x86_64/x32/tst-size_t-wmemcmp.c [new file with mode: 0644]
sysdeps/x86_64/x32/tst-size_t-wmemset.c [new file with mode: 0644]
time/tzfile.c

index 08b42bd2f56471e376fe4409786da0d37ade91e5..cb119f36acc4c8b0ae79b37aaee91a01b632fb93 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,717 @@
+2019-02-04  Florian Weimer  <fweimer@redhat.com>
+
+       [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 <arpa/inet.h> and change visibility of
+       __inet_aton_exact.
+
+2019-01-21  Florian Weimer  <fweimer@redhat.com>
+
+       [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 <support/test-driver.c>.
+       (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  <fweimer@redhat.com>
+
+       [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  <fweimer@redhat.com>
+
+       * resolv/inet_addr.c: Reformat to GNU style.
+       (__inet_addr, __inet_aton): Update comment.
+
+2019-02-04  H.J. Lu  <hongjiu.lu@intel.com>
+
+       [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  <hongjiu.lu@intel.com>
+
+       [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  <hongjiu.lu@intel.com>
+
+       [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  <hongjiu.lu@intel.com>
+
+       [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  <hongjiu.lu@intel.com>
+
+       [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  <hongjiu.lu@intel.com>
+
+       [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  <hongjiu.lu@intel.com>
+
+       [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  <hongjiu.lu@intel.com>
+
+       [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  <hongjiu.lu@intel.com>
+
+       [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  <tuliom@linux.ibm.com>
+
+       * math/libm-test-fma.inc (fma_test_data): Set
+       XFAIL_ROUNDING_IBM128_LIBGCC to more tests.
+
+2019-01-07  Aurelien Jarno  <aurelien@aurel32.net>
+
+       [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  <Martin.Jansa@gmail.com>
+
+       [BZ #19444]
+       * sysdeps/ieee754/soft-fp/s_fdiv.c: Include <libc-diag.h> and use
+       DIAG_PUSH_NEEDS_COMMENT, DIAG_IGNORE_NEEDS_COMMENT and
+       DIAG_POP_NEEDS_COMMENT to disable -Wmaybe-uninitialized.
+
+2019-01-02  Aurelien Jarno  <aurelien@aurel32.net>
+
+       [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  <hongjiu.lu@intel.com>
+
+       [BZ #24022]
+       * sysdeps/unix/sysv/linux/riscv/flush-icache.c: Check if
+       <asm/syscalls.h> exists with __has_include__ before including it.
+
+2019-01-02  Florian Weimer  <fweimer@redhat.com>
+
+       [BZ #24018]
+       * intl/dcigettext.c (DCIGETTEXT): Do not return NULL on asprintf
+       failure.
+
+2018-12-31  Florian Weimer  <fw@deneb.enyo.de>
+
+       [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  <aurelien@aurel32.net>
+
+       * sysdeps/alpha/fpu/libm-test-ulps: Regenerated.
+
+2018-12-18  Adhemerval Zanella  <adhemerval.zanella@linaro.org>
+           James Clarke  <jrtc27@jrtc27.com>
+
+       [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  <schwab@suse.de>
+
+       [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  <fweimer@redhat.com>
+
+       * 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  <schwab@suse.de>
+
+       [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  <tuliom@linux.ibm.com>
+
+       [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  <dj@redhat.com>
+
+       [BZ #23907]
+       * malloc/tst-tcfree3.c: New.
+       * malloc/Makefile: Add it.
+
+2018-12-07  Florian Weimer  <fweimer@redhat.com>
+
+       [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  <fweimer@redhat.com>
+
+       * 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  <fweimer@redhat.com>
+
+       * 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  <fweimer@redhat.com>
+
+       * support/support.h (support_quote_string): Do not use str
+       parameter name.
+
+2018-11-27  Florian Weimer  <fweimer@redhat.com>
+
+       * 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  <fweimer@redhat.com>
+
+       [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  <tuliom@linux.ibm.com>
+
+       [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  <fweimer@redhat.com>
+
+       [BZ #23907]
+       * malloc/malloc.c (_int_free): Validate tc_idx before checking for
+       double-frees.
+
+
+2018-11-20  DJ Delorie  <dj@redhat.com>
+
+       * 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  <fweimer@redhat.com>
+
+       [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  <fweimer@redhat.com>
+
+       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  <szabolcs.nagy@arm.com>
+
+       * libio/tst-readline.c (TIMEOUT): Define.
+
+2018-10-22  Joseph Myers  <joseph@codesourcery.com>
+
+       * sysdeps/unix/sysv/linux/syscall-names.list: Update kernel
+       version to 4.19.
+
+2018-09-18  Paul Eggert  <eggert@cs.ucla.edu>
+
+       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  <ppluzhnikov@google.com>
+
+       [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  <fweimer@redhat.com>
+
+       [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  <dj@delorie.com>
+
+       * malloc/malloc.c (_int_free): Check for corrupt prev_size vs size.
+       (malloc_consolidate): Likewise.
+
+2018-08-16  Pochang Chen  <johnchen902@gmail.com>
+
+       * malloc/malloc.c (_int_malloc.c): Verify size of top chunk.
+
+2018-08-13  Joseph Myers  <joseph@codesourcery.com>
+
+       * 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á  <ahajkova@redhat.com>
+
+       [BZ #17630]
+       * resolv/tst-resolv-network.c: Add test for getnetbyname.
+
+2018-11-08  H.J. Lu  <hongjiu.lu@intel.com>
+
+       [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  <schwab@suse.de>
+
+       [BZ #22927]
+       * resolv/gai_misc.c (__gai_enqueue_request): Don't crash if
+       creating the first helper thread failed.
+
+2018-10-23  Adhemerval Zanella  <adhemerval.zanella@linaro.org>
+
+       [BZ #23709]
+       * sysdeps/x86/cpu-features.c (init_cpu_features): Set TSX bits
+       independently of other flags.
+
+2018-10-30  Florian Weimer  <fweimer@redhat.com>
+
+       * stdlib/tst-strtod-overflow.c (do_test): Switch to
+       support_blob_repeat.
+
+2018-10-30  Florian Weimer  <fweimer@redhat.com>
+
+       * support/blob_repeat.c (allocate_big): Call mkstemp directly.
+
+2018-10-30  Florian Weimer  <fweimer@redhat.com>
+
+       * stdlib/test-bz22786.c (do_test): Additional free calls to avoid
+       memory leaks.
+
+2018-10-30  Florian Weimer  <fweimer@redhat.com>
+
+       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  <stli@linux.ibm.com>
+
+       * stdlib/test-bz22786.c (do_test): Return EXIT_UNSUPPORTED
+       if malloc fails.
+
+2018-08-24  Paul Pluzhnikov  <ppluzhnikov@google.com>
+
+        [BZ #23400]
+        * stdlib/test-bz22786.c (do_test): Fix undefined behavior, don't
+        create temporary files in source tree.
+
+2018-10-26  Szabolcs Nagy  <szabolcs.nagy@arm.com>
+
+       [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  <fweimer@redhat.com>
+
+       [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  <malakhov@mcst.ru>
+
+       [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  <stli@linux.ibm.com>
+
+       [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  <hongjiu.lu@intel.com>
+
+       [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  <digitalfreak@lingonborough.com>
+
+       [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  <adhemerval.zanella@linaro.org>
+
+       [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  <schwab@suse.de>
+
+       [BZ #23717]
+       * stdlib/tst-setcontext9.c (f1a): Make st2 static.
+       (do_test): Make st1 static.
+
+2018-09-21  H.J. Lu  <hongjiu.lu@intel.com>
+           Xuepeng Guo  <xuepeng.guo@intel.com>
+
+       [BZ #23606]
+       * sysdeps/i386/start.S: Include <sysdep.h>
+       (_start): Use ENTRY/END to insert ENDBR32 at entry when CET is
+       enabled.  Add cfi_undefined (eip).
+
+2018-09-19  Wilco Dijkstra  <wdijkstr@arm.com>
+
+       [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  <carlos@redhat.com>
+
+       * 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  <fweimer@redhat.com>
+
+       * misc/tst-gethostid.c: New file.
+       * misc/Makefile [$(build-shared)] (tests): Add tst-gethostid.
+       (tst-gethostid): Link with -ldl.
+
+2018-09-20  Mingli Yu  <Mingli.Yu@windriver.com>
+
+       * sysdeps/unix/sysv/linux/gethostid.c (gethostid): Check for NULL
+       value from gethostbyname_r.
+
+2018-09-06  Stefan Liebler  <stli@linux.ibm.com>
+
+       * sysdeps/unix/sysv/linux/spawni.c (maybe_script_execute):
+       Increment size of new_argv by one.
+
+2018-08-28  Florian Weimer  <fweimer@redhat.com>
+
+       [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  <eggert@cs.ucla.edu>
+
+       [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 <bugs@feusi.co> 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  <martin.kuchta@netapp.com>
+          Torvald Riegel  <triegel@redhat.com>
+
+       [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  <dj@redhat.com>
+
+       * 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  <fweimer@redhat.com>
+
+       [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  <fweimer@redhat.com>
+
+       * nscd/nscd_conf.c (nscd_parse_file): Deallocate old storage for
+       server_user, stat_user.
+
+2018-08-13  Florian Weimer  <fweimer@redhat.com>
+
+       * misc/error.c (error): Add missing va_end call.
+       (error_at_line): Likewise.
+
+2018-08-10  Florian Weimer  <fweimer@redhat.com>
+
+       [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  <samuel.thibault@ens-lyon.org>
+
+       * 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  <carlos@redhat.com>
 
        * version.h (RELEASE): Set to "stable".
index 608ffe648c80c724f756162aa95fe58de3afffa9..f5e81bdf5d8aae3b70ee8d00148432cc67ab3414 100644 (file)
@@ -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 154ab22d7ca065af5233406927302bb7f6a66890..5aa15afb9dc13efafd95f399a0b0b92466d55d89 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -5,6 +5,63 @@ See the end for copying conditions.
 Please send GNU C library bug reports via <https://sourceware.org/bugzilla/>
 using `glibc' in the "product" field.
 \f
+Version 2.28.1
+
+The following bugs are resolved with this release:
+
+  [19444] build failures with -O1 due to -Wmaybe-uninitialized
+  [20018] getaddrinfo should reject IP addresses with trailing characters
+  [20209] localedata: Spelling mistake for Sunday in Greenlandic kl_GL
+  [22927] libanl: properly cleanup if first helper thread creation failed
+  [23400] stdlib/test-bz22786.c creates temporary files in glibc source tree
+  [23497] readdir64@GLIBC_2.1 cannot parse the kernel directory stream
+  [23509] CET enabled glibc is incompatible with the older linker
+  [23521] nss_files aliases database file stream leak
+  [23538] pthread_cond_broadcast: Fix waiters-after-spinning case
+  [23562] signal: Use correct type for si_band in siginfo_t
+  [23578] regex: Fix memory overread in re_compile_pattern
+  [23579] libc: Errors misreported in preadv2
+  [23606] Missing ENDBR32 in sysdeps/i386/start.S
+  [23614] powerpc: missing CFI register information in __mpn_* functions
+  [23679] gethostid: Missing NULL check for gethostbyname_r result
+  [23709] Fix CPU string flags for Haswell-type CPUs
+  [23717] Fix stack overflow in stdlib/tst-setcontext9
+  [23821] si_band in siginfo_t has wrong type long int on sparc64
+  [23822] ia64 static libm.a is missing exp2f, log2f and powf symbols
+  [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 <asm/syscalls.h>
+  [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
+  [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)
+
+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.
+\f
 Version 2.28
 
 Major new features:
@@ -422,6 +479,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)
 
 \f
 Version 2.27
index 11e54adb04824c948de137503382602a77c90688..674e5793dbdf32b09cdd7105f6ebc35273116d18 100644 (file)
@@ -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
index ed3869b34fa6343e79481cdb93f4eccb9a0b456e..c0761424daa15738ccc607d6fe381bd3a46478d0 100644 (file)
@@ -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
index 33574faab65628ff85c358677e567837390efe7b..96bf92533335036b29bdb55c049ef6e50c9cc7a2 100644 (file)
@@ -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;
+       }
     }
 }
 
index cd0771307f90b6d45e8decd46db24dba4ecdb49c..43f625af05699d5ca520a1a9d7a9ecfed58b9731 100644 (file)
@@ -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
index 63bbc89776a782825f2fbf69c681a015743f90d9..3d2f4a7a76e616e3c2a0b3cf3275cdc017278ea9 100644 (file)
@@ -183,10 +183,36 @@ _dl_profile_fixup (
   /* This is the address in the array where we store the result of previous
      relocations.  */
   struct reloc_result *reloc_result = &l->l_reloc_result[reloc_index];
-  DL_FIXUP_VALUE_TYPE *resultp = &reloc_result->addr;
 
-  DL_FIXUP_VALUE_TYPE value = *resultp;
-  if (DL_FIXUP_VALUE_CODE_ADDR (value) == 0)
+ /* CONCURRENCY NOTES:
+
+  Multiple threads may be calling the same PLT sequence and with
+  LD_AUDIT enabled they will be calling into _dl_profile_fixup to
+  update the reloc_result with the result of the lazy resolution.
+  The reloc_result guard variable is reloc_init, and we use
+  acquire/release loads and store to it to ensure that the results of
+  the structure are consistent with the loaded value of the guard.
+  This does not fix all of the data races that occur when two or more
+  threads read reloc_result->reloc_init with a value of zero and read
+  and write to that reloc_result concurrently.  The expectation is
+  generally that while this is a data race it works because the
+  threads write the same values.  Until the data races are fixed
+  there is a potential for problems to arise from these data races.
+  The reloc result updates should happen in parallel but there should
+  be an atomic RMW which does the final update to the real result
+  entry (see bug 23790).
+
+  The following code uses reloc_result->init set to 0 to indicate if it is
+  the first time this object is being relocated, otherwise 1 which
+  indicates the object has already been relocated.
+
+  Reading/Writing from/to reloc_result->reloc_init must not happen
+  before previous writes to reloc_result complete as they could
+  end-up with an incomplete struct.  */
+  DL_FIXUP_VALUE_TYPE value;
+  unsigned int init = atomic_load_acquire (&reloc_result->init);
+
+  if (init == 0)
     {
       /* This is the first time we have to relocate this object.  */
       const ElfW(Sym) *const symtab
@@ -346,19 +372,31 @@ _dl_profile_fixup (
 
       /* Store the result for later runs.  */
       if (__glibc_likely (! GLRO(dl_bind_not)))
-       *resultp = value;
+       {
+         reloc_result->addr = value;
+         /* Guarantee all previous writes complete before
+            init is updated.  See CONCURRENCY NOTES earlier  */
+         atomic_store_release (&reloc_result->init, 1);
+       }
+      init = 1;
     }
+  else
+    value = reloc_result->addr;
 
   /* By default we do not call the pltexit function.  */
   long int framesize = -1;
 
+
 #ifdef SHARED
   /* Auditing checkpoint: report the PLT entering and allow the
      auditors to change the value.  */
-  if (DL_FIXUP_VALUE_CODE_ADDR (value) != 0 && GLRO(dl_naudit) > 0
+  if (GLRO(dl_naudit) > 0
       /* Don't do anything if no auditor wants to intercept this call.  */
       && (reloc_result->enterexit & LA_SYMB_NOPLTENTER) == 0)
     {
+      /* Sanity check:  DL_FIXUP_VALUE_CODE_ADDR (value) should have been
+        initialized earlier in this function or in another thread.  */
+      assert (DL_FIXUP_VALUE_CODE_ADDR (value) != 0);
       ElfW(Sym) *defsym = ((ElfW(Sym) *) D_PTR (reloc_result->bound,
                                                l_info[DT_SYMTAB])
                           + reloc_result->boundndx);
diff --git a/elf/tst-unwind-main.c b/elf/tst-unwind-main.c
new file mode 100644 (file)
index 0000000..d123603
--- /dev/null
@@ -0,0 +1,38 @@
+/* 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
+   <http://www.gnu.org/licenses/>.  */
+
+#include <unwind.h>
+#include <unistd.h>
+#include <support/test-driver.h>
+
+static _Unwind_Reason_Code
+callback (struct _Unwind_Context *ctx, void *arg)
+{
+  return _URC_NO_REASON;
+}
+
+int
+main (void)
+{
+  /* 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 _start.  */
+  alarm (DEFAULT_TIMEOUT);
+  _Unwind_Backtrace (callback, 0);
+}
index f056fbf5aa6aa14c49dea8d7553f9f0ed1f72f41..93e7f5814da6286dd8cc5efbb823b2594a1f09ca 100644 (file)
@@ -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
index 6a63a1b8a18a89cf894965bd18b33c83d7a695ce..c5a616da10d69b99d450e83f6901c820fb6203e2 100644 (file)
@@ -150,6 +150,8 @@ libpthread {
     __cthread_keycreate;
     __cthread_getspecific;
     __cthread_setspecific;
+    __pthread_getspecific;
+    __pthread_setspecific;
     __pthread_getattr_np;
     __pthread_attr_getstack;
   }
index c3f28f2baaa2ed662767d8e2d6262fc90a8f921d..19aec74275069a450713722a857484d1a2588b09 100644 (file)
@@ -1,10 +1,10 @@
 #include <inet/arpa/inet.h>
 
 #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;
index 5924594548e7ef820595217e7714f7994c533ec1..83b1c34b7b4db8f30c49b3fb2a81fb93f29066e6 100644 (file)
@@ -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.  */
index 9162d4e24717e31a443264802a342555c249114a..7a5c09089fc4d348e0d45fecc00ae86aa1e5e37d 100644 (file)
@@ -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,
index 09f5ba78fc5f3120e71c23126af4a6e02c4976da..7782913b4c06f057bcfe8abf197dc2b6a397e612 100644 (file)
@@ -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 (file)
index 0000000..3dc7487
--- /dev/null
@@ -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
+   <http://www.gnu.org/licenses/>.  */
+
+/* This test checks for a descriptor leak in case of a long interface
+   name (CVE-2018-19591, bug 23927).  */
+
+#include <errno.h>
+#include <net/if.h>
+#include <netdb.h>
+#include <string.h>
+#include <support/check.h>
+#include <support/descriptors.h>
+#include <support/support.h>
+
+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 <support/test-driver.c>
index 2a5036994824875b4db6b2e5ca7063a563903a2a..25f47c5bd3b0ea0482042fd460c67258c0d10aa5 100644 (file)
@@ -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
index 9322ef68da5e38a9cf819d6f2eab953f1fd0b7ba..63f5227760d88c632f77e4cc3b6dfb9b1aacfb42 100644 (file)
@@ -232,5 +232,6 @@ do_test (void)
   return 0;
 }
 
+#define TIMEOUT 100
 #define PREPARE prepare
 #include <support/test-driver.c>
index 5ab14a31aade8644dfdd07a7b8d186da5288635a..5723ce7dcf9c5742fccce80727f5380b3ec124f8 100644 (file)
@@ -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";/
index 7d54bad866f63cb8a23a1a1bb6eb793e92572ff8..388cf7e9ee3a2569ffe0a4ff53ed875f56307b14 100644 (file)
@@ -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 \
index e247c77b7d4de26e0f2fbec16e352889bac3781b..27cf6137c252a9ab9aef2c6d062d0ba3eae26e99 100644 (file)
@@ -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^<size_t> 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 (file)
index 0000000..bc29375
--- /dev/null
@@ -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
+   <http://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <error.h>
+#include <limits.h>
+#include <malloc.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/signal.h>
+
+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 <support/test-driver.c>
diff --git a/malloc/tst-tcfree2.c b/malloc/tst-tcfree2.c
new file mode 100644 (file)
index 0000000..17f06ba
--- /dev/null
@@ -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
+   <http://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <error.h>
+#include <limits.h>
+#include <malloc.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/signal.h>
+
+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<COUNT; i++)
+    ptrs[i] = malloc (20);
+  for (i=0; i<COUNT; i++)
+    free (ptrs[i]);
+  free (ptrs[0]);
+
+  printf("FAIL: tcache double free\n");
+  return 1;
+}
+
+#define TEST_FUNCTION do_test
+#define EXPECTED_SIGNAL SIGABRT
+#include <support/test-driver.c>
diff --git a/malloc/tst-tcfree3.c b/malloc/tst-tcfree3.c
new file mode 100644 (file)
index 0000000..016d30d
--- /dev/null
@@ -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
+   <http://www.gnu.org/licenses/>.  */
+
+#include <malloc.h>
+#include <string.h>
+
+/* 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 <support/test-driver.c>
index 5b29fb820194e0553eb467b62ed1f720e311b4d6..a7ee40992420c1ab41aa1e5f52f02c222ba33252 100644 (file)
@@ -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),
   };
index b7be2bc19a6f7ed57e5faaa957d105023198ef63..c9f81515ac9aef2cbdea01776faadce92345a7fb 100644 (file)
@@ -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)
index b4e8b6c93886b73765e91748a7fc2e8e24d9f183..03378e2f2aa6251ed7b65b8a3892f650120d7bd8 100644 (file)
@@ -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 (file)
index 0000000..1490aaf
--- /dev/null
@@ -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
+   <http://www.gnu.org/licenses/>.  */
+
+#include <gnu/lib-names.h>
+#include <nss.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <support/namespace.h>
+#include <support/support.h>
+#include <support/temp_file.h>
+#include <support/xdlfcn.h>
+#include <support/xstdio.h>
+#include <support/xunistd.h>
+#include <unistd.h>
+
+/* 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 <support/test-driver.c>
index f889a21544947042cd5db1d496bc3fe60569d952..50b9da3fea56d2887924a6695d0a86de99bfabfc 100644 (file)
@@ -19,9 +19,6 @@
 #include <limits.h>
 #include <support/check.h>
 
-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);
index be22802dbe00317f424076d127965328480026f4..cb58cbe41ecc639d13d16bfb8cabd7e8e835d747 100644 (file)
@@ -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);
 }
index 8d3cc32b284dbf4c7eda57717812ee3b63ed4791..6a9de54c786acc53bd5161d51fdeda9cc06f664b 100644 (file)
@@ -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);
 }
index be8066524cdc57db94f06d941c92aa039131f640..2d2db648f730db612a5d8725247f8e5d7bdd7ae7 100644 (file)
@@ -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,8 @@ 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
 
 tests-internal := tst-rwlock19 tst-rwlock20 \
                  tst-sem11 tst-sem12 tst-sem13 \
@@ -382,7 +383,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 +396,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 +712,16 @@ 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
+
 # The tests here better do not run in parallel
 ifneq ($(filter %tests,$(MAKECMDGOALS)),)
 .NOTPARALLEL:
index 13bdb11133536195e0d07e428c41a70e3b29dd23..19efe1e35feed5be386c510d5cddaeb20f759972 100644 (file)
@@ -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
index 8e425eb01eceabec64e2bad3cfeb2ec51b6f6d72..479e54febb41767596c85c3312716b6c52c8700a 100644 (file)
@@ -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);
index 3e1105418210288ef21c37730a59dc8bc619ab3b..ebf07ca82d87de7db9c9ada0e391c7bb42131363 100644 (file)
@@ -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;
index 85b8e1a6cb027e9bf4a10f412226196e055f8e14..4fbd875430439e4d365fe52334d03f3d764380bd 100644 (file)
 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;
 
index 5a22611541995778e7bee10ff2d8b1465f110753..713ea684962fefc10b7f3d9222fa623b64792c85 100644 (file)
@@ -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;
 }
index efa37b0d99201f57492ca7a19a2cb449c7e183d9..ee85949578475f3abe1e67fff0d088c08b73133b 100644 (file)
@@ -24,7 +24,9 @@
 int
 pthread_mutex_getprioceiling (const pthread_mutex_t *mutex, int *prioceiling)
 {
-  if (__builtin_expect ((mutex->__data.__kind
+  /* See concurrency notes regarding __kind in struct __pthread_mutex_s
+     in sysdeps/nptl/bits/thread-shared-types.h.  */
+  if (__builtin_expect ((atomic_load_relaxed (&(mutex->__data.__kind))
                         & PTHREAD_MUTEX_PRIO_PROTECT_NP) == 0, 0))
     return EINVAL;
 
index d8fe4737289c0bd705b46ca19d09aee45b898128..5cf290c272e279151f7cd219c0747a6e571b3060 100644 (file)
@@ -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
index 1519c142bd6ec5cc528c5921f28575d25c7fb664..29cc143e6cbf2421e853267c2a26c0f0e6918198 100644 (file)
@@ -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
index 8594874f8588b7a885ef32cb08ade002cf937967..8306cabcf4e5617495d9f237e34957b7925a95b5 100644 (file)
@@ -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.  */
index 28237b0e58cfcaf50268a335053ef038e3d81590..888c12fe28b2ebfdec7e23647d18c098162b57e3 100644 (file)
@@ -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;
 
index 7de61f4f688c153716531912ae0d386e470cac0b..fa90c1d1e6f5afc274ae442f99d99e7c84714aba 100644 (file)
@@ -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))
     {
@@ -199,8 +201,14 @@ __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.  */
@@ -325,7 +333,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;
 
index 9ea62943b7c6b159460f507c0a3a81f23becdbe3..68d04d53955584e560cec7edc0e51f019dd7306e 100644 (file)
@@ -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));
index a290d08332b802a5ddec0f8d5d33f6e94a84d609..9ce36d1026215e90f3cb9be95e81b8e515c3e55d 100644 (file)
@@ -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/tst-audit-threads-mod1.c b/nptl/tst-audit-threads-mod1.c
new file mode 100644 (file)
index 0000000..615d5ee
--- /dev/null
@@ -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
+   <http://www.gnu.org/licenses/>.  */
+
+#include <elf.h>
+#include <link.h>
+#include <stdio.h>
+#include <assert.h>
+#include <string.h>
+
+/* 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 (file)
index 0000000..f9817dd
--- /dev/null
@@ -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
+   <http://www.gnu.org/licenses/>.  */
+
+/* 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 (file)
index 0000000..e4bf433
--- /dev/null
@@ -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
+   <http://www.gnu.org/licenses/>.  */
+
+/* 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 <support/xthread.h>
+#include <strings.h>
+#include <stdlib.h>
+#include <sys/sysinfo.h>
+
+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 (file)
index 0000000..1c9ecc0
--- /dev/null
@@ -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
+   <http://www.gnu.org/licenses/>.  */
+
+/* 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 (file)
index 0000000..e1113ca
--- /dev/null
@@ -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
+   <http://www.gnu.org/licenses/>.  */
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <pthread.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <support/support.h>
+#include <support/xthread.h>
+
+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 <support/test-driver.c>
diff --git a/nptl/tst-rwlock-pwn.c b/nptl/tst-rwlock-pwn.c
new file mode 100644 (file)
index 0000000..c39dd70
--- /dev/null
@@ -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
+   <http://www.gnu.org/licenses/>.  */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <pthread.h>
+#include <support/xthread.h>
+
+/* 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 <support/test-driver.c>
index b713a84c4953d41109cee32d171cfbb153374ac7..eb23c01a396254a5d5c6de183aa5ef0c32c2477e 100644 (file)
@@ -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)
 
index 24bdfee1db3791e26acaa33e0c2108a8f73d7bf1..68a4abd30e5b5d2913f9f1eb2e95d2b3ab5afa7c 100644 (file)
@@ -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
 #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 <arpa/inet.h>
+__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
 
index 7beb9dce9f4b350c414a1e28fe859463c5e814d1..f792c4fcd042d13d3945e3a0e44b22f529710a1f 100644 (file)
@@ -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
 
index 2c74951f579f4afd2bef2609685d0a765b5fcc76..4764f14a45f68e0a183315812931a08bb947b34b 100644 (file)
@@ -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;
 
index 2b35389cc816c3c88384783664e937766fef0b79..87059fb28042f0a5a8797a32af844688f9c3dcdc 100644 (file)
@@ -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 (file)
index 0000000..f366b95
--- /dev/null
@@ -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
+   <http://www.gnu.org/licenses/>.  */
+
+#include <arpa/inet.h>
+
+/* We do not want to export __inet_aton_exact.  Get the prototype and
+   change the visibility to hidden.  */
+#include <arpa/inet.h>
+__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 <resolv/inet_addr.c>
index 265a02434dd26c290cce4378991e693d47ab9a04..7293b795b6bcf71e2080bab0d078f776471ed5ae 100644 (file)
@@ -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);
index 66fac7f5b8a4c0d84f8afcc0be302e57c0520a6f..5209fc0456dd67868ff9530a582fda71e1fc57b3 100644 (file)
@@ -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
index 39bff38865a1ac5b196d1d7a85303b42816e7c71..5441bce16ea8b2e9bf5348e9de0035f96135045e 100644 (file)
@@ -29,7 +29,6 @@
 #include "nsswitch.h"
 
 #ifdef USE_NSCD
-# define inet_aton __inet_aton
 # include <nscd/nscd_proto.h>
 #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);
index cfd34b66b921bbff7c972fc71b51e6358d136cdf..35b0bfc5d2479ab62dfefaa52c7b640c937428a8 100644 (file)
@@ -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)
index ee46f24424bc1ca2085f4fd7f1060ae330ee5bae..3c48b4b85e881cdbc9cdea6ee3fdc9fc3d21bcd1 100644 (file)
@@ -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 (file)
index 0000000..26d38e2
--- /dev/null
@@ -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
+   <http://www.gnu.org/licenses/>.  */
+
+#include <aliases.h>
+#include <array_length.h>
+#include <dlfcn.h>
+#include <errno.h>
+#include <gnu/lib-names.h>
+#include <nss.h>
+#include <stdlib.h>
+#include <string.h>
+#include <support/check.h>
+#include <support/namespace.h>
+#include <support/support.h>
+#include <support/temp_file.h>
+#include <support/test-driver.h>
+#include <support/xstdio.h>
+#include <support/xunistd.h>
+
+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 <support/test-driver.c>
index 00c62841a282f15a3d41ff807400a6c5df0dbf4b..83162123f9c927a0a171dfcdf7ead27efd7f1858 100644 (file)
@@ -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
index 7f0083b918de6530f73937f152ae45a4a5427e42..b10588f1ccbb1992f97c617055a794f0c7c2e4d5 100644 (file)
@@ -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/tst-regcomp-truncated.c b/posix/tst-regcomp-truncated.c
new file mode 100644 (file)
index 0000000..a4a1581
--- /dev/null
@@ -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
+   <http://www.gnu.org/licenses/>.  */
+
+/* This test constructs various patterns in an attempt to trigger
+   over-reading the regular expression compiler, such as bug
+   23578.  */
+
+#include <array_length.h>
+#include <errno.h>
+#include <locale.h>
+#include <regex.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <support/check.h>
+#include <support/next_to_fault.h>
+#include <support/support.h>
+#include <support/test-driver.h>
+#include <wchar.h>
+
+/* 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 (&reg, 0, sizeof (reg));
+                        const char *msg = re_compile_pattern
+                          (ntf_start, length, &reg);
+                        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 (&reg);
+                      }
+                }
+            }
+        }
+    }
+
+  support_next_to_fault_free (&ntf);
+
+  return 0;
+}
+
+#include <support/test-driver.c>
index ea395ac3eb4332e190a46ac57f08204027212ee1..d36eedd34a73a4588d51117dbaea09d560a0a258 100644 (file)
@@ -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: \
index b05778d9654aa0f24ff46554952580b4c28e687e..9a82704af75f789bc81d9c9c540f9c7b581130c1 100644 (file)
@@ -27,6 +27,7 @@ libc {
     __h_errno; __resp;
 
     __res_iclose;
+    __inet_aton_exact;
     __inet_pton_length;
     __resolv_context_get;
     __resolv_context_get_preinit;
index e7c3b63cc5725b4fc98cef4902f00d9a8228516a..80a2cff8353fcb6cade44431cefcbdf8805cf35b 100644 (file)
@@ -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;
index 022f7ea0841b6baeec80c11eb846ae25d571ad49..41b6166a5bd5a44bae5c8b6a065b9d1b7c4afd9b 100644 (file)
@@ -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
+   <http://www.gnu.org/licenses/>.  */
+
 /*
  * Copyright (c) 1983, 1990, 1993
  *    The Regents of the University of California.  All rights reserved.
 #include <limits.h>
 #include <errno.h>
 
-/*
- * 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)
index 5dc2829cd148a5681881d36b78fb9e18cfd5eab7..99c3b61e1cee4d4248e9104efc6f96de3e040ddb 100644 (file)
@@ -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);
index f5e52cbbb93777622bb2b8737841173a1a1bb4c4..94743a252e39d64a1be0a868c01a03be8ea8c02b 100644 (file)
@@ -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);
index 08110a007af909fffc9412634254e22954675938..eb734d7758d6ed87036477e65330321039981e33 100644 (file)
@@ -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
+   <http://www.gnu.org/licenses/>.  */
+
+#include <array_length.h>
 #include <stdio.h>
 #include <stdint.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
 
-
-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 <support/test-driver.c>
diff --git a/resolv/tst-inet_aton_exact.c b/resolv/tst-inet_aton_exact.c
new file mode 100644 (file)
index 0000000..0fdfa3d
--- /dev/null
@@ -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
+   <http://www.gnu.org/licenses/>.  */
+
+#include <arpa/inet.h>
+#include <support/check.h>
+
+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 <support/test-driver.c>
index 4b862d57e65276e53daf94615a5bcff287d289ab..735e38d0f8974da48d0c1f69ab8a369429a4f82c 100644 (file)
@@ -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 (file)
index 0000000..a0df6f3
--- /dev/null
@@ -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
+   <http://www.gnu.org/licenses/>.  */
+
+#include <netdb.h>
+#include <stdlib.h>
+#include <support/check.h>
+#include <support/check_nss.h>
+#include <support/resolv_test.h>
+#include <support/support.h>
+
+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 <support/test-driver.c>
diff --git a/resolv/tst-resolv-trailing.c b/resolv/tst-resolv-trailing.c
new file mode 100644 (file)
index 0000000..7504bda
--- /dev/null
@@ -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
+   <http://www.gnu.org/licenses/>.  */
+
+#include <array_length.h>
+#include <netdb.h>
+#include <support/check.h>
+#include <support/check_nss.h>
+#include <support/resolv_test.h>
+#include <support/support.h>
+
+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 <support/test-driver.c>
index e7837f98c19fc4bf8ac1da3a2fa5daa84d277051..8035e8a394e7d034b34173102463cbee08cf65de 100644 (file)
 #include <unistd.h>
 #include <sys/stat.h>
 #include <sys/types.h>
+#include <support/blob_repeat.h>
+#include <support/check.h>
+#include <support/support.h>
+#include <support/temp_file.h>
 #include <support/test-driver.h>
 #include <libc-diag.h>
 
 static int
 do_test (void)
 {
-  const char dir[] = "bz22786";
-  const char lnk[] = "bz22786/symlink";
-
-  rmdir (dir);
-  if (mkdir (dir, 0755) != 0 && errno != EEXIST)
-    {
-      printf ("mkdir %s: %m\n", dir);
-      return EXIT_FAILURE;
-    }
-  if (symlink (".", lnk) != 0 && errno != EEXIST)
-    {
-      printf ("symlink (%s, %s): %m\n", dir, lnk);
-      return EXIT_FAILURE;
-    }
-
-  const size_t path_len = (size_t) INT_MAX + 1;
-
-  DIAG_PUSH_NEEDS_COMMENT;
-#if __GNUC_PREREQ (7, 0)
-  /* GCC 7 warns about too-large allocations; here we need such
-     allocation to succeed for the test to work.  */
-  DIAG_IGNORE_NEEDS_COMMENT (7, "-Walloc-size-larger-than=");
-#endif
-  char *path = malloc (path_len);
-  DIAG_POP_NEEDS_COMMENT;
+  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;
 }
index 4636ce9030fa38a7dd9b83e9aa95108f38e046cc..009928235dd5987ed73a117f51336284270e49d6 100644 (file)
@@ -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)
     {
index d14638d68ef4f471ed3e70abf8ab44826afed284..dc53c1e521443e1d41aaec374e2923d0c65b47db 100644 (file)
@@ -19,6 +19,8 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <support/blob_repeat.h>
+#include <support/test-driver.h>
 
 #define EXPONENT "e-2147483649"
 #define SIZE 214748364
 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;
 }
 
index 680431f92185f9143710809b4105e12daa2daaa5..aa2da9ca72262886d2854a2c4bd16132e8f53841 100644 (file)
@@ -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
index 5909fe3cdba88e476c7a989a020f3611bbfeb1de..421764bd1b0ff22e36053dc7b82850b0697de7b8 100644 (file)
@@ -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)
index 265e9f310ce507ce63740cc42d8ceea1d28dab01..79ebcc75329d0b17c94950f62269277d2ce0713b 100644 (file)
@@ -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 (file)
index 0000000..8e744e7
--- /dev/null
@@ -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
+   <http://www.gnu.org/licenses/>.  */
+
+#include <dlfcn.h>
+#include <errno.h>
+#include <string.h>
+
+#include <support/check.h>
+#include <support/support.h>
+
+/* 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 <support/test-driver.c>
index 8d99716ff39cc2c22ebebdacb5f30438f9b32ffc..5861b01b73e4c315c471d68300f2ba25e3533ac1 100644 (file)
@@ -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);
index 652d2cdf6945b2eb960c10be555f1db67e36299b..550fdba0f7b1bc42e60b930133a016e347721d69 100644 (file)
@@ -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 \
@@ -154,9 +157,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 (file)
index 0000000..718846d
--- /dev/null
@@ -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
+   <http://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <support/blob_repeat.h>
+#include <support/check.h>
+#include <support/test-driver.h>
+#include <support/support.h>
+#include <support/xunistd.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include <wchar.h>
+
+/* 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 <malloc/malloc-internal.h>.  */
+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 (file)
index 0000000..8e9d7ff
--- /dev/null
@@ -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
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef SUPPORT_BLOB_REPEAT_H
+#define SUPPORT_BLOB_REPEAT_H
+
+#include <stdbool.h>
+#include <stddef.h>
+
+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 */
index b3a4645e9255e90d2490a1bcf62f03c976f87add..10468b74d8a4aa84bda8275342ff68adbf3b5972 100644 (file)
@@ -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 (file)
index 0000000..8ec4cbb
--- /dev/null
@@ -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
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef SUPPORT_DESCRIPTORS_H
+#define SUPPORT_DESCRIPTORS_H
+
+#include <stdio.h>
+
+/* 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 */
index b61fe0735c9204de03da18b53b20d747f857ce8a..4ea92e1c2109c06fc9e8879cb54c0fd1d252647a 100644 (file)
@@ -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.  */
 
index 6d2029e13bd6ae73dd3ef55592e7246446a7a102..93f6ea310290000a2cccb786078a34b3f5a8b672 100644 (file)
@@ -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 (file)
index 0000000..d66cf55
--- /dev/null
@@ -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
+   <http://www.gnu.org/licenses/>.  */
+
+#include <dirent.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <support/check.h>
+#include <support/support.h>
+#include <sys/stat.h>
+#include <sys/sysmacros.h>
+#include <xunistd.h>
+
+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 <malloc/dynarray-skeleton.c>
+
+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 (&current->list);
+  struct procfs_descriptor *right_end = descriptor_list_end (&current->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 (file)
index 0000000..d324371
--- /dev/null
@@ -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
+   <http://www.gnu.org/licenses/>.  */
+
+#include <string.h>
+#include <support/support.h>
+
+char *
+support_quote_string (const char *str)
+{
+  return support_quote_blob (str, strlen (str));
+}
index 356798f55608ca7116be84aa6c76ff62d0b1732b..17ab1d80ef2bbdea06ca815f0f31b31397d4ea92 100644 (file)
@@ -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);
+}
index 23429779aca85613d30eaca0e990b95372b00ac9..fa3c2e06dee5ae0ff5bf733253f8bf006b80bb4b 100644 (file)
@@ -30,6 +30,7 @@
 #include <string.h>
 #include <sys/param.h>
 #include <sys/resource.h>
+#include <sys/time.h>
 #include <sys/types.h>
 #include <sys/wait.h>
 #include <time.h>
@@ -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 (file)
index 0000000..1978c14
--- /dev/null
@@ -0,0 +1,85 @@
+/* Tests for <support/blob_repeat.h>
+   Copyright (C) 2018 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <stdio.h>
+#include <support/blob_repeat.h>
+#include <support/check.h>
+
+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 <support/test-driver.c>
diff --git a/support/tst-support_descriptors.c b/support/tst-support_descriptors.c
new file mode 100644 (file)
index 0000000..5e9e824
--- /dev/null
@@ -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
+   <http://www.gnu.org/licenses/>.  */
+
+#include <fcntl.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <support/capture_subprocess.h>
+#include <support/check.h>
+#include <support/descriptors.h>
+#include <support/support.h>
+#include <support/xunistd.h>
+
+/* 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 <support/test-driver.c>
diff --git a/support/tst-support_quote_string.c b/support/tst-support_quote_string.c
new file mode 100644 (file)
index 0000000..3c00475
--- /dev/null
@@ -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
+   <http://www.gnu.org/licenses/>.  */
+
+#include <support/check.h>
+#include <support/support.h>
+#include <string.h>
+#include <stdlib.h>
+
+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 <support/test-driver.c>
index 5889ee187b7a1eafc22bbf54502557482955475b..bef71ed0f31a6387c4baa4574da18e9e5d21c0ff 100644 (file)
@@ -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
index 12a6127ddf93cadf8534cafa2a915d93db60501e..3fc18d57d741676e183aec62e845b32c1315dd8c 100644 (file)
@@ -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
index a7b6456075659baf945bcf2c7643f14ff78db250..be6eb7743eb5f08d577f8851b3203528ec9c89c3 100644 (file)
@@ -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 */
index 082609b34a3f773bc9caa45d4e84708d7407c4ac..724c16a7f0bf465b2139f665f0db4932678c28dd 100644 (file)
@@ -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
              {
index a0227a67f61cb83d4adb7825e3181b0697577a7c..64ddf9551a852f536c19259b542f54ea4681abe3 100644 (file)
@@ -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)
index a46a12f157a17ad47148f36dcf80afe329bd9076..02aff417efcdac8679163493effb52334bd0196f 100644 (file)
@@ -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)
index 132ac1718eafc059b3857da91764d03905590f1a..71c2fcd9c6509c24c50726a2e5b6956b281fddc8 100644 (file)
@@ -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 (file)
index 5d9a4e8..0000000
+++ /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
-   <http://www.gnu.org/licenses/>.  */
-
-
-#define LINKAGE static inline
-#define _dl_cet_check cet_check
-#include <sysdeps/x86/dl-cet.c>
-#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
index 55303180c7aca4957525e31c04dc869c796b1507..bcaf0668acf8e2f20e6de0e10d91e4ff2b1b2548 100644 (file)
@@ -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 */
index 1afdcbd9ea2626e4434e15ece5f8e4ba03c99407..f6cfb90e21015250ea62934ff0330c2ba577ab43 100644 (file)
@@ -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;
index 91035fa83fb7ee38a0ca5834ba1d215b4a7f78e8..e35e9bd31b2cea3011fd9574cb7f9358129681d1 100644 (file)
                                        NULL
 */
 
-       .text
-       .globl _start
-       .type _start,@function
-_start:
+#include <sysdep.h>
+
+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.  */
index 77bc6ea68646bcd19102a3968075c5078cfcd70f..3010a95a2d9e9dc08bbaab373dafed48c979ec35 100644 (file)
@@ -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
index 5ca3bd61ea472f4a31b56851a29d522957f229b2..e4ea0943448d574c9327e7a2bd3c06613893407c 100644 (file)
@@ -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
index 7449f8c7d56853938714d55a40a5a4c714024467..945d5cdf281a6f4c722b5369e53926420a6eb620 100644 (file)
@@ -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
index 341339f5edd52241af88f005657de5c04d099f27..7a15cbeee699a18e105b32ed5beec4bd9896f278 100644 (file)
 #undef fdivl
 
 #include <math-narrow.h>
+#include <libc-diag.h>
+
+/* 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 <soft-fp.h>
 #include <single.h>
 #include <double.h>
@@ -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)
index 1e2092a05d5610f7bf5aedac1d369c818c672a97..05c94e7a710c0eb912471fb60773e567b2cafe67 100644 (file)
@@ -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
index 1a5624789d4ab117f4c1ab7544168b508401ab9f..6fd27f0df6c27b69e3bada224dd9bf081eb23289 100644 (file)
@@ -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 */
index 553833d1f22d6ea4ae24c68fe14e2140aa059d50..c91b281e317c3abf2935a050647417a7ecf91bd2 100644 (file)
@@ -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;
index a7368b25829618cb3dee9a87fdf9f8eda21fa7c3..61d0e4cf61ec45d30538ffc3f4867aed794a36db 100644 (file)
@@ -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 */
index 48e3b1b290084174e477fc4bb9ba9349efd2f62a..e450d6a52cdea0e3ee82339fb7d6c467649b15b3 100644 (file)
 #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)
index ab13c04358868270b2426d064a6b060e4e9e0ac5..2fd0ee8a86e85ba0cd1d42bb3c1d90828ae82708 100644 (file)
@@ -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 */
index 8b6396ee6cf21153d93800aaddbec6f039899556..855d6f2993d7634b5072273d512469682a56be13 100644 (file)
 #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)
index 953ded802888ecc1abc05e9af569b13bf162c5e0..cade3652586ba65af69d5efcbd4488910f111692 100644 (file)
 #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)
index f8feadcd0de96aa572f419f54f9b8fdd78eee858..61be2df60d1bb0d3adbf7ffd8e1e737230056e22 100644 (file)
@@ -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
 
index cdb7858fc8ce9a129bde4918e44b1dfb5cb91d3d..ca587620cb36bb1b519ea49da428853e9a466c4f 100644 (file)
@@ -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
index 4635ddb5eb8c54156bbe576d05ca45599927cd5f..2d6f06e630588ad1e6c8d3f0de41c81a87adb4b1 100644 (file)
    __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
index d8ba7ba42709f45ca97436d30a5c8b853a2f8842..ecb24f0a9be0daa7005a436e1a97ae147152458f 100644 (file)
@@ -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 */
index ffca36864f24d1fba869ef3bfae6ac0b640ed2f3..cf47cda8345b1a399ee9c5c6970d1556169c09c7 100644 (file)
@@ -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 */
index c5cd3057aca1baf64438d07f0e765fd837ffa2b1..446fed18365cfd13abf9e0119d4e704d98143949 100644 (file)
@@ -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 */
index f71cc39c7e257a0a9208060ce9c858a034bc4750..773aaea0e980bdd67562f4a96c79a39d8fcf33c7 100644 (file)
@@ -161,6 +161,7 @@ inhibit-glue = yes
 
 ifeq ($(subdir),dirent)
 sysdep_routines += getdirentries getdirentries64
+tests-internal += tst-readdir64-compat
 endif
 
 ifeq ($(subdir),nis)
index ad165274d81e891cace9d20dc685fda67bff5a51..a5d244e65eace807f641976d727aed1eed7055f4 100644 (file)
    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__                                                    \
      (__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__                                                    \
index 33766d1813c689a8942e8f5d37758105a7501036..43c4e009a44faef57558093d248a715f75759f89 100644 (file)
@@ -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;
 
index 3bde0cf4f0226f95104a03f67af58b7527700155..46eb5f441986607e2a84235cd5a4139424a2fc89 100644 (file)
@@ -33,41 +33,90 @@ strong_alias (__getdents64, __getdents)
 # include <shlib-compat.h>
 
 # if SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_2)
-# include <olddirent.h>
+#  include <olddirent.h>
+#  include <unistd.h>
 
-/* 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;
index 2e20f034dc134cc7f6cd927a920880bce7efcd29..ee0190e7f945db1f25fcb6546100ee9e97adb4de 100644 (file)
@@ -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;
index e3d08982d9931108b8965d07dbded44bcb2f5ff8..782fc5e1750e9eadcc2dbfff2d62828ac06973ad 100644 (file)
@@ -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;
index 2dbec08099345c74b37acc93547af1e142a45815..1c36146d4616b902bc0acac1180e7b624194bb3c 100644 (file)
@@ -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
 
index 54972feb13bf0b14d35eedaf0b1c38e9dd8867ba..464b351d6d86563f4d15a0a5e273ed27f27e2660 100644 (file)
@@ -1,22 +1,4 @@
-#ifndef _KERNEL_SIGACTION_H
-# define _KERNEL_SIGACTION_H
-
-#include <signal.h>
-
-#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 <sysdeps/unix/sysv/linux/kernel_sigaction.h>
index f31ccb52ffa564363e116639de5b334513228e0a..6afc3a17ced18e1c3df904484d0b9174ec736f26 100644 (file)
@@ -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);
         }
index 4ada32210407a4a1046f981ae11df957dbb20849..89f9bcedfd30e356df9c0840a0d9e37d865d45de 100644 (file)
@@ -1,8 +1,9 @@
 /* NIOS2 uses the generic Linux UAPI but defines SA_RESTORER.  */
 #define SA_RESTORER 0x04000000
-#include <sysdeps/unix/sysv/linux/kernel_sigaction.h>
 
 #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 <sysdeps/unix/sysv/linux/kernel_sigaction.h>
index fe5d6ceade2bad36297c0714327dd98edc88d756..d8f5a4b1c7713bd4de9ed863f9d1e091d0798afc 100644 (file)
 
 /* 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;                                                            \
+       }                                                               \
     }
index aef3d5a3b3c73844c7037800de1529c3e773c9b5..bac03ee45d19f5a129348e65b4a9b82bfba922fc 100644 (file)
@@ -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 <sysdeps/unix/sysv/linux/kernel_sigaction.h>
 
 #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 <sysdeps/unix/sysv/linux/kernel_sigaction.h>
index c8bf0764ef2629fc8d75021ad032a3d85761f39e..bb08cbc5fd96962e51d2357cfdb3f280de172371 100644 (file)
@@ -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:
index d7400a0252a8c6a1df7568d24fb1bc24358a81b8..b72a047347b1db0ee33ee93ae97f73d702bb12cf 100644 (file)
@@ -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:
index 29c2264c8f3d949aed1b9b2985d1cf22f7afa075..26333ebd43c5f0afe5476ec3134d3963e2b1ab45 100644 (file)
@@ -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:
index 42da321149bce40de47c5e1cfe593378dd76faa5..17ea905aa6a8db9435467343ec945c3a73e8121f 100644 (file)
@@ -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:
index d612ef4c6c6bf996e96332a56e658b25d3acd983..0b2042620bf21349c50e26b7c74e8ceaa8ec293c 100644 (file)
 #include <stdlib.h>
 #include <atomic.h>
 #include <sys/cachectl.h>
-#include <asm/syscalls.h>
+#if __has_include__ (<asm/syscalls.h>)
+# include <asm/syscalls.h>
+#else
+# include <asm/unistd.h>
+#endif
 
 typedef int (*func_type) (void *, void *, unsigned long int);
 
index d8a1b9972f739cfebd8cf492999b306cd50f8559..71f32367dd6b648920ee172ce698a0ba8f7b09d9 100644 (file)
 
 /* 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;                                                            \
+       }                                                               \
     }
index 7ebcd08d629c1598806658d5168c756c62880a67..c8dc77a02bd8d182bafbddf06fc8ebee6288233b 100644 (file)
@@ -1,8 +1,9 @@
 /* SH uses the generic Linux UAPI but defines SA_RESTORER.  */
 #define SA_RESTORER 0x04000000
-#include <sysdeps/unix/sysv/linux/kernel_sigaction.h>
 
 #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 <sysdeps/unix/sysv/linux/kernel_sigaction.h>
index 9f79715ebe6c94828bb383be5edee5f2a1ea2007..4dd35237f67a63c555becffdf038e489558564e6 100644 (file)
@@ -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;
index bee7e9cd03e28577bcb4c4232f623da92da1b597..eb4a5224539136f3c219c0bff71d99d09dfab36e 100644 (file)
@@ -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 <sysdeps/unix/sysv/linux/kernel_sigaction.h>
-
-#define SET_SA_RESTORER(kact, act)             \
-  (kact)->sa_restorer = NULL
-#define RESET_SA_RESTORER(act, kact)           \
-  (act)->sa_restorer = (kact)->sa_restorer
index 715af3df7b14857f760f02a46a27d59a1d4f0c2e..218c246f161256d8a7eb8a75bc0faa3e8bca8597 100644 (file)
@@ -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
index cf0213ece55c675d44b72f23f8c317566849c5aa..85239cedbf2a5ab51cb4b38ebd94bf182603fb8a 100644 (file)
@@ -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)
index 5306d538e644816319a701a58c3f137d3c0c1c2c..f88001c9c38d5fc76f41b2464c2b3aaa393b198d 100644 (file)
@@ -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 (file)
index 0000000..cb78bc9
--- /dev/null
@@ -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
+   <http://www.gnu.org/licenses/>.  */
+
+#include <dirent.h>
+#include <dlfcn.h>
+#include <errno.h>
+#include <shlib-compat.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+#include <support/check.h>
+
+/* Copied from <olddirent.h>.  */
+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 <support/test-driver.c>
index dd659c908f3046c1af0830cc09ad93a0fe40c3bb..61282d6678d897877c5485e0d2b9c415537089f0 100644 (file)
 
 /* 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;                                                            \
+       }                                                               \
     }
index 4e6d9cc32e1e18746726fa430d092de9a19ba6c6..9aa2c7f860b7c419269f46ab0a48f3c3982c24eb 100644 (file)
@@ -18,7 +18,6 @@
 
 #include <signal.h>
 #define SA_RESTORER 0x04000000
-#include <kernel_sigaction.h>
 
 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 <kernel_sigaction.h>
+
 #include <sysdeps/unix/sysv/linux/sigaction.c>
 
 /* NOTE: Please think twice before making any changes to the bits of
index ea0b64fdb962a934c2950d37dfe7ba061aa00ccf..4695ac80d414832783dccf12451c414b83b2e3d1 100644 (file)
@@ -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)
index 26c3131ac5e2d080dd9ddf2d8be07ec09e9f758e..9ab890d12bb991339826d26c1bed9e1d0cde7934 100644 (file)
@@ -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
 }
 
index ef1206a9d2396a6f17bbb236765761a4b97dac3e..9367ed08896794a4fc2b937286f3eb302259c20b 100644 (file)
@@ -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;
index 6ecc50fb42333c19519b94a0652888117d64717c..33f100d8b1781ea775b3f10273c416949d142a65 100644 (file)
@@ -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 */
index feef5d4f24b32ffa56733285c39e8477d23e2590..cb320257a247cc2293a3e9dcc05cf1ed55db4e0c 100644 (file)
@@ -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
index bcb4a2e88d58953c0ebbe48da57c1228a787e2e7..45918d375af002b39cd0fa5068124ebea5396a40 100644 (file)
 
        .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
index b8e3fa1d87fcc7895438894022cf6b2cf72d90e6..dc82f8f73dffd2de2f10e38ad3aeac04e7c9ad5b 100644 (file)
 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
index 5f5e772554b618af96d76e25f67c2e14b4d55337..c81da19bf00ac520943285cd718d1b0129e112fb 100644 (file)
 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.  */
index 30f764c393592178fdc2b7492dfebf96a91a6559..e3a35b899ee71fdbc082a5a62dbb799f02addb16 100644 (file)
        .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.  */
index 8e164f2cb6a9dd53cb0fea136e938158c83f8b92..302900f5b8e6feb9e222195145ecfdbfbe4b78a6 100644 (file)
        .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
index 6f76c641239456ec425198e4fdacca2d33cfef0c..69d030fc00febac91684befbeb48d85c440e7c79 100644 (file)
        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
index 3cd1123326a9fbf545da527eaa7c28e470be37a8..568eebd3ae28c2f1462f9017bc39bd4672e32bd8 100644 (file)
        .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
index 0240bfa30978ae8db8bdf7d024de3e1229ab7d9c..0bd5ee999a1251bdaa05386515ceb06a0e86b5c8 100644 (file)
        .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
index effc3ac2deaa4ce783e1e205520a9f185b80eae8..6ca2bbc91adddd7f05ecd1af34f4b7aa4bdebe75 100644 (file)
 
        .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
index e2ede45e9f68791b4d9b91002a77382b21888512..9bab1147d57a520ab82d32f80728061945fa731d 100644 (file)
        .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
index b41a58bcbab6d1946e1ffb9d5df9db00e5035e50..ce488dd9e8a718c70f7e46827f0a07a79b8704cb 100644 (file)
@@ -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
index 689cc1199ca67ddc442b97e342226f0f0896d9ab..99e255195a02eb2a9a46d55c147c39005aa06259 100644 (file)
        .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
index dc9cb88b37a5477a8e66a8ef25ed4b503fef8a1c..a44f1bc3b2de9b8bb61b6a8afd4fafd7011192bf 100644 (file)
@@ -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)
index e8397f3b05e6e9eafacbd3b45617476dee91e475..78fc116877f1437f51afce96ac4ee8cc3c7e3a13 100644 (file)
 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
index d3c07bd292ce66629eaff2932e5f83d2be3665c4..a1ebea46fef797cf99ef8371a3c6751e4cb31663 100644 (file)
@@ -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
index 72bf7e8586b7ea5f604a1627985d8dd2b35d5bca..50aca22d2ee7abbd1c084564d5dd3c5f138dce00 100644 (file)
@@ -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
index 9858d0c4d5a49699a7287f598063488479019467..0a62814a06d3455a61e370649eabf8543b85b975 100644 (file)
@@ -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)
index fb2418cddc18b2ec30bd0440f6f8f8d7efe2896e..645e04461f95d5bb9ee43d3bf3c8d638cffd9bfc 100644 (file)
 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
index e16945b96165ee3bdf7479ad0ae2fce473a83d03..f47c8ad45cf0aeb20953babe230b93ad0f6056f5 100644 (file)
@@ -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
index 01cb5fa846e72a2408eaeb8cbe04ba60129a9dcf..f845f3d46e0a888a4a153674c570bcdffc89938f 100644 (file)
@@ -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
index f2ebc24fb07cf96bc7094491c29f01603acffeec..8748956563babf8f0ad816d361a26f79486d9a7b 100644 (file)
@@ -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 (file)
index 0000000..78a9408
--- /dev/null
@@ -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
+   <http://www.gnu.org/licenses/>.  */
+
+#define TEST_MAIN
+#include <string/test-string.h>
+
+/* 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 (file)
index 0000000..29a3daf
--- /dev/null
@@ -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
+   <http://www.gnu.org/licenses/>.  */
+
+#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 <wchar.h>
+# 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 <support/test-driver.c>
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 (file)
index 0000000..d8ae1a0
--- /dev/null
@@ -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
+   <http://www.gnu.org/licenses/>.  */
+
+#define TEST_MAIN
+#ifdef WIDE
+# define TEST_NAME "wmemcmp"
+#else
+# define TEST_NAME "memcmp"
+#endif
+
+#include "test-size_t.h"
+
+#ifdef WIDE
+# include <inttypes.h>
+# include <wchar.h>
+
+# 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 <support/test-driver.c>
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 (file)
index 0000000..9bd6fdb
--- /dev/null
@@ -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
+   <http://www.gnu.org/licenses/>.  */
+
+#define TEST_MAIN
+#ifdef WIDE
+# define TEST_NAME "wmemcmp"
+#else
+# define TEST_NAME "memcmp"
+#endif
+
+#include "test-size_t.h"
+
+#ifdef WIDE
+# include <inttypes.h>
+# include <wchar.h>
+
+# 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 <support/test-driver.c>
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 (file)
index 0000000..66b71e1
--- /dev/null
@@ -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
+   <http://www.gnu.org/licenses/>.  */
+
+#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 <support/test-driver.c>
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 (file)
index 0000000..c83699c
--- /dev/null
@@ -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
+   <http://www.gnu.org/licenses/>.  */
+
+#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 <support/test-driver.c>
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 (file)
index 0000000..2c367af
--- /dev/null
@@ -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
+   <http://www.gnu.org/licenses/>.  */
+
+#ifdef WIDE
+# define TEST_NAME "wmemset"
+#else
+# define TEST_NAME "memset"
+#endif /* WIDE */
+
+#include "test-size_t.h"
+
+#ifdef WIDE
+# include <wchar.h>
+# 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 <support/test-driver.c>
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 (file)
index 0000000..8623359
--- /dev/null
@@ -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
+   <http://www.gnu.org/licenses/>.  */
+
+#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 <support/test-driver.c>
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 (file)
index 0000000..54e6bd8
--- /dev/null
@@ -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
+   <http://www.gnu.org/licenses/>.  */
+
+#ifdef WIDE
+# define TEST_NAME "wcsncmp"
+#else
+# define TEST_NAME "strncmp"
+#endif
+
+#include "test-size_t.h"
+
+#ifdef WIDE
+# include <wchar.h>
+
+# 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 <support/test-driver.c>
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 (file)
index 0000000..4dec71e
--- /dev/null
@@ -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
+   <http://www.gnu.org/licenses/>.  */
+
+#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 <support/test-driver.c>
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 (file)
index 0000000..690a4a8
--- /dev/null
@@ -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
+   <http://www.gnu.org/licenses/>.  */
+
+#ifdef WIDE
+# define TEST_NAME "wcsnlen"
+#else
+# define TEST_NAME "strnlen"
+#endif /* WIDE */
+
+#include "test-size_t.h"
+
+#ifdef WIDE
+# include <wchar.h>
+# 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 <support/test-driver.c>
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 (file)
index 0000000..4829647
--- /dev/null
@@ -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
+   <http://www.gnu.org/licenses/>.  */
+
+#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 (file)
index 0000000..093b4bb
--- /dev/null
@@ -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
+   <http://www.gnu.org/licenses/>.  */
+
+#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 (file)
index 0000000..877801d
--- /dev/null
@@ -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
+   <http://www.gnu.org/licenses/>.  */
+
+#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 (file)
index 0000000..e8b5ffd
--- /dev/null
@@ -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
+   <http://www.gnu.org/licenses/>.  */
+
+#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 (file)
index 0000000..955eb48
--- /dev/null
@@ -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
+   <http://www.gnu.org/licenses/>.  */
+
+#define WIDE 1
+#include "tst-size_t-memset.c"
index 2a385b92bcdefec08576a835293ccd10e5572019..ea6e94030392fc754118a6a60feffff0c54a7069 100644 (file)
@@ -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