aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTulio Magno Quites Machado Filho <tuliom@linux.vnet.ibm.com>2018-02-02 15:18:56 -0200
committerTulio Magno Quites Machado Filho <tuliom@linux.vnet.ibm.com>2018-02-02 15:18:56 -0200
commit400747ec4ff4c0b8bc094437c2e8cc8da42ee452 (patch)
tree6c17c1adc37ca84e8354d33cd2dde31ca004a41e
parent962a4b638fe0dbffba9de7a408eedb1a27be1096 (diff)
parentbbabb868cd248763373d0db763bacd84ce27ede8 (diff)
downloadtermbaud-ibm/2.26/master.tar.gz
termbaud-ibm/2.26/master.tar.xz
termbaud-ibm/2.26/master.zip
Merge branch 'release/2.26/master' into ibm/2.26/masteribm/2.26/master
-rw-r--r--ChangeLog332
-rw-r--r--NEWS55
-rw-r--r--elf/dl-load.c96
-rw-r--r--include/array_length.h36
-rw-r--r--io/Makefile2
-rw-r--r--io/tst-getcwd-abspath.c66
-rw-r--r--malloc/arena.c31
-rw-r--r--malloc/hooks.c88
-rw-r--r--malloc/malloc.c376
-rw-r--r--malloc/tst-realloc.c4
-rw-r--r--manual/memory.texi21
-rw-r--r--manual/probes.texi7
-rw-r--r--manual/terminal.texi5
-rw-r--r--manual/tunables.texi28
-rw-r--r--math/Makefile2
-rw-r--r--math/math.h72
-rw-r--r--math/test-math-iseqsig.cc111
-rw-r--r--nptl/Makefile11
-rw-r--r--nptl/allocatestack.c33
-rw-r--r--nptl/descr.h4
-rw-r--r--nptl/nptl-init.c5
-rw-r--r--nptl/pthread_create.c27
-rw-r--r--nptl/pthread_getattr_np.c7
-rw-r--r--nptl/tst-minstack-cancel.c48
-rw-r--r--nptl/tst-minstack-exit.c46
-rw-r--r--nptl/tst-minstack-throw.cc87
-rw-r--r--nptl/tst-thread-exit-clobber.cc243
-rw-r--r--posix/glob.c4
-rw-r--r--posix/tst-glob-tilde.c53
-rw-r--r--scripts/backport-support.sh2
-rw-r--r--support/Makefile22
-rw-r--r--support/capture_subprocess.h2
-rw-r--r--support/check.c5
-rw-r--r--support/check.h57
-rw-r--r--support/check_addrinfo.c3
-rw-r--r--support/check_dns_packet.c3
-rw-r--r--support/check_hostent.c3
-rw-r--r--support/check_netent.c3
-rw-r--r--support/check_nss.h2
-rw-r--r--support/delayed_exit.c2
-rw-r--r--support/format_nss.h2
-rw-r--r--support/ignore_stderr.c2
-rw-r--r--support/namespace.h7
-rw-r--r--support/next_to_fault.c52
-rw-r--r--support/next_to_fault.h48
-rw-r--r--support/oom_error.c2
-rw-r--r--support/resolv_test.c296
-rw-r--r--support/resolv_test.h2
-rw-r--r--support/run_diff.h2
-rw-r--r--support/set_fortify_handler.c2
-rw-r--r--support/support-xfstat.c28
-rw-r--r--support/support-xstat.c2
-rw-r--r--support/support.h3
-rw-r--r--support/support_become_root.c70
-rw-r--r--support/support_can_chroot.c4
-rw-r--r--support/support_capture_subprocess.c2
-rw-r--r--support/support_capture_subprocess_check.c2
-rw-r--r--support/support_chroot.c8
-rw-r--r--support/support_enter_mount_namespace.c47
-rw-r--r--support/support_enter_network_namespace.c2
-rw-r--r--support/support_format_address_family.c2
-rw-r--r--support/support_format_addrinfo.c3
-rw-r--r--support/support_format_dns_packet.c3
-rw-r--r--support/support_format_herrno.c2
-rw-r--r--support/support_format_hostent.c17
-rw-r--r--support/support_format_netent.c3
-rw-r--r--support/support_isolate_in_subprocess.c2
-rw-r--r--support/support_record_failure.c2
-rw-r--r--support/support_run_diff.c2
-rw-r--r--support/support_shared_allocate.c2
-rw-r--r--support/support_test_compare_failure.c58
-rw-r--r--support/support_test_main.c2
-rw-r--r--support/support_test_verify_impl.c5
-rw-r--r--support/support_write_file_string.c4
-rw-r--r--support/temp_file-internal.h2
-rw-r--r--support/temp_file.c15
-rw-r--r--support/temp_file.h7
-rw-r--r--support/test-driver.c2
-rw-r--r--support/test-driver.h2
-rw-r--r--support/tst-support-namespace.c2
-rw-r--r--support/tst-support_capture_subprocess.c2
-rw-r--r--support/tst-support_format_dns_packet.c2
-rw-r--r--support/tst-support_record_failure-2.sh2
-rw-r--r--support/tst-support_record_failure.c2
-rw-r--r--support/tst-test_compare.c116
-rw-r--r--support/tst-xreadlink.c72
-rw-r--r--support/write_message.c5
-rw-r--r--support/xaccept.c2
-rw-r--r--support/xaccept4.c2
-rw-r--r--support/xasprintf.c2
-rw-r--r--support/xbind.c2
-rw-r--r--support/xcalloc.c2
-rw-r--r--support/xchroot.c2
-rw-r--r--support/xclose.c2
-rw-r--r--support/xconnect.c2
-rw-r--r--support/xdlfcn.c59
-rw-r--r--support/xdlfcn.h34
-rw-r--r--support/xdup2.c2
-rw-r--r--support/xfclose.c2
-rw-r--r--support/xfopen.c2
-rw-r--r--support/xfork.c2
-rw-r--r--support/xftruncate.c27
-rw-r--r--support/xgetsockname.c2
-rw-r--r--support/xlisten.c2
-rw-r--r--support/xlseek.c29
-rw-r--r--support/xmalloc.c2
-rw-r--r--support/xmemstream.c2
-rw-r--r--support/xmemstream.h2
-rw-r--r--support/xmkdir.c2
-rw-r--r--support/xmmap.c2
-rw-r--r--support/xmprotect.c2
-rw-r--r--support/xmunmap.c2
-rw-r--r--support/xopen.c2
-rw-r--r--support/xpipe.c2
-rw-r--r--support/xpoll.c2
-rw-r--r--support/xpthread_attr_destroy.c2
-rw-r--r--support/xpthread_attr_init.c2
-rw-r--r--support/xpthread_attr_setdetachstate.c2
-rw-r--r--support/xpthread_attr_setguardsize.c2
-rw-r--r--support/xpthread_attr_setstacksize.c2
-rw-r--r--support/xpthread_barrier_destroy.c2
-rw-r--r--support/xpthread_barrier_init.c2
-rw-r--r--support/xpthread_barrier_wait.c2
-rw-r--r--support/xpthread_cancel.c2
-rw-r--r--support/xpthread_check_return.c2
-rw-r--r--support/xpthread_cond_wait.c2
-rw-r--r--support/xpthread_create.c2
-rw-r--r--support/xpthread_detach.c2
-rw-r--r--support/xpthread_join.c2
-rw-r--r--support/xpthread_mutex_consistent.c2
-rw-r--r--support/xpthread_mutex_destroy.c2
-rw-r--r--support/xpthread_mutex_init.c2
-rw-r--r--support/xpthread_mutex_lock.c2
-rw-r--r--support/xpthread_mutex_unlock.c2
-rw-r--r--support/xpthread_mutexattr_destroy.c2
-rw-r--r--support/xpthread_mutexattr_init.c2
-rw-r--r--support/xpthread_mutexattr_setprotocol.c2
-rw-r--r--support/xpthread_mutexattr_setpshared.c2
-rw-r--r--support/xpthread_mutexattr_setrobust.c2
-rw-r--r--support/xpthread_mutexattr_settype.c2
-rw-r--r--support/xpthread_once.c2
-rw-r--r--support/xpthread_rwlock_init.c2
-rw-r--r--support/xpthread_rwlock_rdlock.c2
-rw-r--r--support/xpthread_rwlock_unlock.c2
-rw-r--r--support/xpthread_rwlock_wrlock.c2
-rw-r--r--support/xpthread_rwlockattr_init.c2
-rw-r--r--support/xpthread_rwlockattr_setkind_np.c2
-rw-r--r--support/xpthread_sigmask.c2
-rw-r--r--support/xpthread_spin_lock.c2
-rw-r--r--support/xpthread_spin_unlock.c2
-rw-r--r--support/xraise.c27
-rw-r--r--support/xreadlink.c44
-rw-r--r--support/xrealloc.c2
-rw-r--r--support/xrecvfrom.c2
-rw-r--r--support/xsendto.c2
-rw-r--r--support/xsetsockopt.c2
-rw-r--r--support/xsigaction.c27
-rw-r--r--support/xsignal.c29
-rw-r--r--support/xsignal.h10
-rw-r--r--support/xsocket.c2
-rw-r--r--support/xsocket.h2
-rw-r--r--support/xstdio.h2
-rw-r--r--support/xstrdup.c2
-rw-r--r--support/xstrndup.c30
-rw-r--r--support/xsysconf.c36
-rw-r--r--support/xthread.h2
-rw-r--r--support/xunistd.h11
-rw-r--r--support/xunlink.c27
-rw-r--r--support/xwaitpid.c2
-rw-r--r--support/xwrite.c2
-rw-r--r--sysdeps/aarch64/dl-machine.h39
-rw-r--r--sysdeps/i386/fpu/libm-test-ulps12
-rw-r--r--sysdeps/ia64/fpu/libm-test-ulps1940
-rw-r--r--sysdeps/ia64/memchr.S4
-rw-r--r--sysdeps/nptl/unwind-forcedunwind.c2
-rw-r--r--sysdeps/powerpc/powerpc32/sysdep.h5
-rw-r--r--sysdeps/powerpc/powerpc64/sysdep.h5
-rw-r--r--sysdeps/powerpc/powerpc64le/Makefile7
-rw-r--r--sysdeps/unix/sysv/linux/Makefile3
-rw-r--r--sysdeps/unix/sysv/linux/getcwd.c8
-rw-r--r--sysdeps/unix/sysv/linux/ia64/ipc_priv.h21
-rw-r--r--sysdeps/unix/sysv/linux/ia64/mmap_internal.h29
-rw-r--r--sysdeps/unix/sysv/linux/m68k/mmap_internal.h2
-rw-r--r--sysdeps/unix/sysv/linux/mmap.c2
-rw-r--r--sysdeps/unix/sysv/linux/mmap_internal.h6
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/not-errno.h30
-rw-r--r--sysdeps/unix/sysv/linux/tst-ttyname.c577
-rw-r--r--sysdeps/unix/sysv/linux/ttyname.c63
-rw-r--r--sysdeps/unix/sysv/linux/ttyname.h18
-rw-r--r--sysdeps/unix/sysv/linux/ttyname_r.c65
-rw-r--r--sysdeps/x86_64/dl-trampoline.h12
191 files changed, 5393 insertions, 912 deletions
diff --git a/ChangeLog b/ChangeLog
index 812c5380f15..e6add48bf51 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,334 @@
+2018-01-19 Tulio Magno Quites Machado Filho <tuliom@linux.vnet.ibm.com>
+
+ [BZ #22685]
+ * sysdeps/powerpc/powerpc32/sysdep.h (ABORT_TRANSACTION_IMPL): Renamed
+ from ABORT_TRANSACTION.
+ (ABORT_TRANSACTION): Redirect to ABORT_TRANSACTION_IMPL.
+ * sysdeps/powerpc/powerpc64/sysdep.h (ABORT_TRANSACTION,
+ ABORT_TRANSACTION_IMPL): Likewise.
+ * sysdeps/unix/sysv/linux/powerpc/not-errno.h: New file. Reuse
+ Linux code, but remove the code that aborts transactions.
+
+2017-12-19 Gabriel F. T. Gomes <gabriel@inconstante.eti.br>
+
+ [BZ #22377]
+ * math/Makefile [C++] (tests): Add test for iseqsig.
+ * math/math.h [C++] (iseqsig): New implementation, which does
+ not rely on __MATH_TG/__builtin_types_compatible_p.
+ * math/test-math-iseqsig.cc: New file.
+ * sysdeps/powerpc/powerpc64le/Makefile
+ (CFLAGS-test-math-iseqsig.cc): New variable.
+
+2017-10-18 Renlin Li <renlin.li@arm.com>
+
+ * sysdeps/aarch64/dl-machine.h (elf_machine_load_address): Use
+ _DYNAMIC symbol to calculate load address.
+
+2018-01-19 H.J. Lu <hongjiu.lu@intel.com>
+
+ [BZ #22715]
+ * sysdeps/x86_64/dl-trampoline.h (_dl_runtime_profile): Properly
+ align La_x86_64_retval to VEC_SIZE.
+
+2018-01-16 Florian Weimer <fweimer@redhat.com>
+
+ * nptl/Makefile [$(have-cxx-thread_local)] (tests-unsupported):
+ Move tst-thread-exit-clobber ...
+ [$(CXX)] (tests-unsupported): ... to here.
+
+2018-01-16 Florian Weimer <fweimer@redhat.com>
+
+ * nptl/Makefile (CFLAGS-tst-minstack-throw.o): Compile in C++11
+ mode with GNU extensions.
+
+2018-01-15 Florian Weimer <fweimer@redhat.com>
+
+ [BZ #22636]
+ * nptl/tst-minstack-throw.cc: New file.
+ * nptl/Makefile (tests): Add tst-minstack-throw.
+ (LDLIBS-tst-minstack-throw): Link with libstdc++.
+ [!CXX] (tests-unsupported): Add tst-minstack-throw.
+
+2018-01-11 Florian Weimer <fweimer@redhat.com>
+
+ [BZ #22636]
+ * nptl/Makefile (tests): Add tst-minstack-cancel, tst-minstack-exit.
+ * nptl/tst-minstack-cancel.c, nptl/tst-minstack-exit.c: New files.
+
+2018-01-10 Florian Weimer <fweimer@redhat.com>
+
+ [BZ #22636]
+ * sysdeps/nptl/unwind-forcedunwind.c (pthread_cancel_init): Open
+ libgcc.so with RTLD_NOW, to avoid lazy binding during unwind.
+
+2018-01-08 Szabolcs Nagy <szabolcs.nagy@arm.com>
+
+ [BZ #22637]
+ * nptl/descr.h (stackblock, stackblock_size): Update comments.
+ * nptl/allocatestack.c (allocate_stack): Add guardsize to stacksize.
+ * nptl/nptl-init.c (__pthread_get_minstack): Remove guardsize from
+ stacksize.
+ * nptl/pthread_getattr_np.c (pthread_getattr_np): Likewise.
+
+2018-01-08 Florian Weimer <fweimer@redhat.com>
+
+ * nptl/tst-thread-exit-clobber.cc: New file.
+ * nptl/Makefile (CFLAGS-tst-thread-exit-clobber.o): Compile in
+ C++11 mode.
+ (LDLIBS-tst-thread-exit-clobber): Link with libstdc++.
+ (tests): Add tst-thread-exit-clobber.
+ [!CXX] (tests-unsupported): Add tst-thread-exit-clobber.
+
+2018-01-12 Dmitry V. Levin <ldv@altlinux.org>
+
+ [BZ #22679]
+ CVE-2018-1000001
+ * sysdeps/unix/sysv/linux/getcwd.c (__getcwd): Fall back to
+ generic_getcwd if the path returned by getcwd syscall is not absolute.
+ * io/tst-getcwd-abspath.c: New test.
+ * io/Makefile (tests): Add tst-getcwd-abspath.
+
+2017-12-19 Adhemerval Zanella <adhemerval.zanella@linaro.org>
+ James Clarke <jrtc27@jrtc27.com>
+
+ [BZ #22603]
+ * sysdeps/ia64/memchr.S (__memchr): Avoid overflow in pointer
+ addition.
+
+2018-01-08 Dmitry V. Levin <ldv@altlinux.org>
+
+ * sysdeps/unix/sysv/linux/tst-ttyname.c (do_in_chroot_1): Skip the
+ test instead of failing in case of ENOENT returned by posix_openpt.
+
+2017-12-29 Aurelien Jarno <aurelien@aurel32.net>
+
+ [BZ #22611]
+ * malloc/tst-realloc.c (do_test): Remove the test checking that errno
+ is unchanged on success.
+
+2017-12-30 Aurelien Jarno <aurelien@aurel32.net>
+ Dmitry V. Levin <ldv@altlinux.org>
+
+ [BZ #22625]
+ CVE-2017-16997
+ * elf/dl-load.c (fillin_rpath): Check for empty tokens before dynamic
+ string token expansion. Check for NULL pointer or empty string possibly
+ returned by expand_dynamic_string_token.
+ (decompose_rpath): Check for empty path after dynamic string
+ token expansion.
+
+2017-12-18 Dmitry V. Levin <ldv@altlinux.org>
+
+ [BZ #22627]
+ * elf/dl-load.c (_dl_init_paths): Remove _dl_dst_substitute preparatory
+ code and invocation.
+
+2017-11-18 Florian Weimer <fweimer@redhat.com>
+
+ * sysdeps/unix/sysv/linux/tst-ttyname.c
+ (become_root_in_mount_ns): Remove.
+ (do_in_chroot_1): Call support_enter_mount_namespace.
+ (do_in_chroot_2): Likewise.
+ (do_test): Call support_become_root early.
+
+2017-11-15 Luke Shumaker <lukeshu@parabola.nu>
+
+ [BZ #22145]
+ * sysdeps/unix/sysv/linux/tst-ttyname.c: New file.
+ * sysdeps/unix/sysv/linux/Makefile: Add tst-ttyname to tests.
+
+2017-11-15 Luke Shumaker <lukeshu@parabola.nu>
+
+ [BZ #22145]
+ * sysdeps/unix/sysv/linux/ttyname.c (ttyname):
+ Defer is_pty check until end of the function.
+ * sysdeps/unix/sysv/linux/ttyname_r.c (__ttyname_r): Likewise.
+
+2017-11-15 Luke Shumaker <lukeshu@parabola.nu>
+
+ [BZ #22145]
+ * sysdeps/unix/sysv/linux/ttyname.h (is_mytty): New function.
+ * sysdeps/unix/sysv/linux/ttyname.c (getttyname): Call is_mytty.
+ (ttyname): Likewise.
+ * sysdeps/unix/sysv/linux/ttyname_r.c (getttyname_r): Likewise.
+ (__ttyname_r): Likewise.
+
+2017-11-15 Luke Shumaker <lukeshu@parabola.nu>
+
+ * sysdeps/unix/sysv/linux/ttyname.h (is_pty): Change return type from
+ int to bool.
+
+2017-11-15 Luke Shumaker <lukeshu@parabola.nu>
+
+ * sysdeps/unix/sysv/linux/ttyname.h (is_pty): Update doc reference.
+
+2017-11-15 Luke Shumaker <lukeshu@parabola.nu>
+
+ * manual/terminal.texi (Is It a Terminal):
+ Mention ENODEV for ttyname and ttyname_r.
+
+2017-12-14 Florian Weimer <fweimer@redhat.com>
+
+ [BZ #22607]
+ CVE-2017-1000409
+ * elf/dl-load.c (_dl_init_paths): Compute number of components in
+ the expanded path string.
+
+2017-12-14 Florian Weimer <fweimer@redhat.com>
+
+ [BZ #22606]
+ CVE-2017-1000408
+ * elf/dl-load.c (system_dirs): Update comment.
+ (nsystem_dirs_len): Use array_length.
+ (_dl_init_paths): Use nsystem_dirs_len to compute the array size.
+
+2017-11-02 Florian Weimer <fweimer@redhat.com>
+
+ Add array_length and array_end macros.
+ * include/array_length.h: New file.
+
+2017-10-27 H.J. Lu <hongjiu.lu@intel.com>
+
+ * sysdeps/i386/fpu/libm-test-ulps: Regenerated for GCC 7 with
+ "-O2 -march=i586".
+
+2017-12-13 Adhemerval Zanella <adhemerval.zanella@linaro.org>
+
+ * sysdeps/ia64/fpu/libm-test-ulps: Update.
+
+2017-12-12 Adhemerval Zanella <adhemerval.zanella@linaro.org>
+
+ [BZ #21672]
+ * nptl/allocatestack.c [_STACK_GROWS_DOWN] (setup_stack_prot):
+ Set to use !NEED_SEPARATE_REGISTER_STACK as well.
+ (advise_stack_range): New function.
+ * nptl/pthread_create.c (START_THREAD_DEFN): Move logic to mark
+ stack non required to advise_stack_range at allocatestack.c
+
+2017-12-12 Adhemerval Zanella <adhemerval.zanella@linaro.org>
+ Sergei Trofimovich <slyfox@inbox.ru>
+
+ [BZ #21908]
+ * sysdeps/unix/sysv/linux/m68k/mmap_internal.h (MMAP2_PAGE_SHIFT):
+ Rename to MMAP2_PAGE_UNIT.
+ * sysdeps/unix/sysv/linux/ia64/mmap_internal.h: New file.
+ * sysdeps/unix/sysv/linux/mmap.c: Include mmap_internal iff
+ __OFF_T_MATCHES_OFF64_T is not defined.
+ * sysdeps/unix/sysv/linux/mmap_internal.h (page_unit): Declare as
+ uint64_t.
+ (MMAP2_PAGE_UNIT) [MMAP2_PAGE_UNIT == -1]: Redefine to page_unit.
+ (page_unit) [MMAP2_PAGE_UNIT != -1]: Remove definition.
+
+2017-12-12 James Clarke <jrtc27@jrtc27.com>
+
+ * sysdeps/unix/sysv/linux/ia64/ipc_priv.h: New file defining
+ __IPC_64 to 0 to avoid IPC_64 being set.
+
+2017-10-15 H.J. Lu <hongjiu.lu@intel.com>
+
+ [BZ #22052]
+ * malloc/hooks.c (realloc_check): Use DIAG_IGNORE_NEEDS_COMMENT
+ to silence -O3 -Wall warning with GCC 7.
+
+2017-11-30 Arjun Shankar <arjun@redhat.com>
+
+ [BZ #22375]
+ CVE-2017-17426
+ * malloc/malloc.c (__libc_malloc): Use checked_request2size
+ instead of request2size.
+
+2017-11-02 Florian Weimer <fweimer@redhat.com>
+
+ [BZ #22332]
+ * posix/tst-glob-tilde.c (do_noescape): New variable.
+ (one_test): Process it.
+ (do_test): Set do_noescape. Add unescaping test case.
+
+2017-10-22 Paul Eggert <eggert@cs.ucla.edu>
+
+ [BZ #22332]
+ * posix/glob.c (__glob): Fix buffer overflow during GLOB_TILDE
+ unescaping.
+
+2017-10-23 Wilco Dijkstra <wdijkstr@arm.com>
+
+ * malloc/malloc.c (_int_malloc): Add SINGLE_THREAD_P path.
+
+2017-10-23 Wilco Dijkstra <wdijkstr@arm.com>
+
+ * malloc/malloc.c (__libc_malloc): Add SINGLE_THREAD_P path.
+ (__libc_realloc): Likewise.
+ (_mid_memalign): Likewise.
+ (__libc_calloc): Likewise.
+
+2017-10-20 Wilco Dijkstra <wdijkstr@arm.com>
+
+ * malloc/malloc.c (sysdep-cancel.h): Add include.
+
+2017-10-20 Wilco Dijkstra <wdijkstr@arm.com>
+
+ * malloc/malloc.c (_int_free): Add SINGLE_THREAD_P fast paths.
+
+2017-10-19 Wilco Dijkstra <wdijkstr@arm.com>
+
+ * malloc/malloc.c (_int_free): Fix deadlock bug in consistency check.
+
+2017-08-31 Florian Weimer <fweimer@redhat.com>
+
+ * malloc/malloc.c (_int_free): Remove locked variable and related
+ asserts.
+
+2017-08-31 Florian Weimer <fweimer@redhat.com>
+
+ * malloc/malloc.c (top_check): Change return type to void. Remove
+ internal_function.
+ * malloc/hooks.c (top_check): Likewise.
+ (malloc_check, realloc_check, memalign_check): Adjust.
+
+2017-08-30 Florian Weimer <fweimer@redhat.com>
+
+ * malloc/malloc.c (ARENA_CORRUPTION_BIT, arena_is_corrupt)
+ (set_arena_corrupt): Remove definitions.
+ (mtrim): Do not check for corrupt arena.
+ * malloc/arena.c (arena_lock, reused_arena, arena_get_retry):
+ Likewise.
+
+2017-08-30 Florian Weimer <fweimer@redhat.com>
+
+ [BZ #21754]
+ * malloc/arena.c (TUNABLE_CALLBACK set_mallopt_check): Do not set
+ check_action.
+ (ptmalloc_init): Do not set or use check_action.
+ * malloc/hooks.c (malloc_check_get_size, realloc_check): Adjust
+ call to malloc_printerr. Remove return statement.
+ (free_check): Likewise. Remove arena unlock.
+ (top_check): Update comment. Adjust call to malloc_printerr.
+ Remove heap repair code.
+ * malloc/malloc.c (unlink): Adjust calls to malloc_printerr.
+ (DEFAULT_CHECK_ACTION, check_action): Remove definitions.
+ (sysmalloc): Adjust call to malloc_printerr.
+ (munmap_chunk, __libc_realloc): Likewise. Remove return
+ statement.
+ (_int_malloc, int_realloc): Likewise. Remove errstr variable.
+ Remove errout label and corresponding gotos.
+ (_int_free): Likewise. Remove arena unlock.
+ (do_set_mallopt_check): Do not set check_action.
+ (malloc_printerr): Adjust parameter list. Do not mark arena as
+ corrupt.
+ * manual/memory.texi (Malloc Tunable Parameters): Remove TODO
+ comment.
+ * manual/probes.texi (Memory Allocation Probes): Remove
+ memory_mallopt_check_action.
+
+2017-08-30 Florian Weimer <fweimer@redhat.com>
+
+ [BZ #21754]
+ * malloc/malloc.c (malloc_printerr): Always terminate the process,
+ without printing a backtrace. Do not leak any information in the
+ error message.
+ * manual/memory.texi (Heap Consistency Checking): Update.
+ * manual/tunables.texi (Memory Allocation Tunables): Likewise.
+
2017-11-17 Tulio Magno Quites Machado Filho <tuliom@linux.vnet.ibm.com>
* sysdeps/powerpc/bits/hwcap.h (PPC_FEATURE2_HTM_NO_SUSPEND): New
@@ -733,6 +1064,7 @@
2017-09-01 Florian Weimer <fweimer@redhat.com>
+ [BZ #20532]
* sysdeps/posix/getaddrinfo.c (gaih_inet): Make reporting of NSS
function lookup failures more reliable.
diff --git a/NEWS b/NEWS
index e7b62a8d463..3f2cb5915fd 100644
--- a/NEWS
+++ b/NEWS
@@ -7,6 +7,16 @@ using `glibc' in the "product" field.
Version 2.26.1
+Major new features:
+
+* In order to support faster and safer process termination the malloc API
+ family of functions will no longer print a failure address and stack
+ backtrace after detecting heap corruption. The goal is to minimize the
+ amount of work done after corruption is detected and to avoid potential
+ security issues in continued process execution. Reducing shutdown time
+ leads to lower overall process restart latency, so there is benefit both
+ from a security and performance perspective.
+
Security related changes:
CVE-2009-5064: The ldd script would sometimes run the program under
@@ -20,10 +30,44 @@ Security related changes:
on the stack or the heap, depending on the length of the user name).
Reported by Tim Rühsen.
+ CVE-2017-15671: The glob function, when invoked with GLOB_TILDE,
+ would sometimes fail to free memory allocated during ~ operator
+ processing, leading to a memory leak and, potentially, to a denial
+ of service.
+
+ CVE-2017-15804: The glob function, when invoked with GLOB_TILDE and
+ without GLOB_NOESCAPE, could write past the end of a buffer while
+ unescaping user names. Reported by Tim Rühsen.
+
+ CVE-2017-17426: The malloc function, when called with an object size near
+ the value SIZE_MAX, would return a pointer to a buffer which is too small,
+ instead of NULL. This was a regression introduced with the new malloc
+ thread cache in glibc 2.26. Reported by Iain Buclaw.
+
+ CVE-2017-1000408: Incorrect array size computation in _dl_init_paths leads
+ to the allocation of too much memory. (This is not a security bug per se,
+ it is mentioned here only because of the CVE assignment.) Reported by
+ Qualys.
+
+ CVE-2017-1000409: Buffer overflow in _dl_init_paths due to miscomputation
+ of the number of search path components. (This is not a security
+ vulnerability per se because no trust boundary is crossed if the fix for
+ CVE-2017-1000366 has been applied, but it is mentioned here only because
+ of the CVE assignment.) Reported by Qualys.
+
+ CVE-2017-16997: Incorrect handling of RPATH or RUNPATH containing $ORIGIN
+ for AT_SECURE or SUID binaries could be used to load libraries from the
+ current directory.
+
+ CVE-2018-1000001: Buffer underflow in realpath function when getcwd function
+ succeeds without returning an absolute path due to unexpected behaviour
+ of the Linux kernel getcwd syscall. Reported by halfdog.
+
The following bugs are resolved with this release:
[16750] ldd: Never run file directly.
[17956] crypt: Use NSPR header files in addition to NSS header files
+ [20532] getaddrinfo: More robust handling of dlopen failures
[21242] assert: Suppress pedantic warning caused by statement expression
[21265] x86-64: Use fxsave/xsave/xsavec in _dl_runtime_resolve
[21780] posix: Set p{read,write}v2 to return ENOTSUP
@@ -39,11 +83,13 @@ The following bugs are resolved with this release:
occur with -O3
[21987] Fix sparc32 bits/long-double.h
[22051] libc: zero terminator in the middle of glibc's .eh_frame
+ [22052] malloc failed to compile with GCC 7 and -O3
[22078] nss_files performance issue in hosts multi mode
[22093] x86: Add x86_64 to x86-64 HWCAP
[22095] resolv: Fix memory leak with OOM during resolv.conf parsing
[22096] resolv: __resolv_conf_attach must not free passed conf object
[22111] malloc: per thread cache is not returned when thread exits
+ [22145] ttyname gives up too early in the face of namespaces
[22146] Let fpclassify use the builtin when optimizing for size in C++ mode
[22225] math: nearbyint arithmetic moved before feholdexcept
[22235] Add C++ versions of iscanonical for ldbl-96 and ldbl-128ibm
@@ -53,6 +99,15 @@ The following bugs are resolved with this release:
[22321] sysconf: Fix missing definition of UIO_MAXIOV on Linux
[22322] libc: [mips64] wrong bits/long-double.h installed
[22325] glibc: Memory leak in glob with GLOB_TILDE (CVE-2017-15671)
+ [22375] malloc returns pointer from tcache instead of NULL (CVE-2017-17426)
+ [22377] Provide a C++ version of iseqsig
+ [22636] PTHREAD_STACK_MIN is too small on x86-64
+ [22627] $ORIGIN in $LD_LIBRARY_PATH is substituted twice
+ [22637] nptl: Fix stack guard size accounting
+ [22679] getcwd(3) can succeed without returning an absolute path
+ (CVE-2018-1000001)
+ [22685] powerpc: Fix syscalls during early process initialization
+ [22715] x86-64: Properly align La_x86_64_retval to VEC_SIZE
Version 2.26
diff --git a/elf/dl-load.c b/elf/dl-load.c
index c1b6d4ba0f1..7397c1882cb 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -37,6 +37,7 @@
#include <sysdep.h>
#include <stap-probe.h>
#include <libc-pointer-arith.h>
+#include <array_length.h>
#include <dl-dst.h>
#include <dl-load.h>
@@ -103,7 +104,9 @@ static size_t ncapstr attribute_relro;
static size_t max_capstrlen attribute_relro;
-/* Get the generated information about the trusted directories. */
+/* Get the generated information about the trusted directories. Use
+ an array of concatenated strings to avoid relocations. See
+ gen-trusted-dirs.awk. */
#include "trusted-dirs.h"
static const char system_dirs[] = SYSTEM_DIRS;
@@ -111,9 +114,7 @@ static const size_t system_dirs_len[] =
{
SYSTEM_DIRS_LEN
};
-#define nsystem_dirs_len \
- (sizeof (system_dirs_len) / sizeof (system_dirs_len[0]))
-
+#define nsystem_dirs_len array_length (system_dirs_len)
static bool
is_trusted_path (const char *path, size_t len)
@@ -433,31 +434,40 @@ fillin_rpath (char *rpath, struct r_search_path_elem **result, const char *sep,
{
char *cp;
size_t nelems = 0;
- char *to_free;
while ((cp = __strsep (&rpath, sep)) != NULL)
{
struct r_search_path_elem *dirp;
+ char *to_free = NULL;
+ size_t len = 0;
- to_free = cp = expand_dynamic_string_token (l, cp, 1);
+ /* `strsep' can pass an empty string. */
+ if (*cp != '\0')
+ {
+ to_free = cp = expand_dynamic_string_token (l, cp, 1);
- size_t len = strlen (cp);
+ /* expand_dynamic_string_token can return NULL in case of empty
+ path or memory allocation failure. */
+ if (cp == NULL)
+ continue;
- /* `strsep' can pass an empty string. This has to be
- interpreted as `use the current directory'. */
- if (len == 0)
- {
- static const char curwd[] = "./";
- cp = (char *) curwd;
- }
+ /* Compute the length after dynamic string token expansion and
+ ignore empty paths. */
+ len = strlen (cp);
+ if (len == 0)
+ {
+ free (to_free);
+ continue;
+ }
- /* Remove trailing slashes (except for "/"). */
- while (len > 1 && cp[len - 1] == '/')
- --len;
+ /* Remove trailing slashes (except for "/"). */
+ while (len > 1 && cp[len - 1] == '/')
+ --len;
- /* Now add one if there is none so far. */
- if (len > 0 && cp[len - 1] != '/')
- cp[len++] = '/';
+ /* Now add one if there is none so far. */
+ if (len > 0 && cp[len - 1] != '/')
+ cp[len++] = '/';
+ }
/* Make sure we don't use untrusted directories if we run SUID. */
if (__glibc_unlikely (check_trusted) && !is_trusted_path (cp, len))
@@ -621,6 +631,14 @@ decompose_rpath (struct r_search_path_struct *sps,
necessary. */
free (copy);
+ /* There is no path after expansion. */
+ if (result[0] == NULL)
+ {
+ free (result);
+ sps->dirs = (struct r_search_path_elem **) -1;
+ return false;
+ }
+
sps->dirs = result;
/* The caller will change this value if we haven't used a real malloc. */
sps->malloced = 1;
@@ -688,9 +706,8 @@ _dl_init_paths (const char *llp)
+ ncapstr * sizeof (enum r_dir_status))
/ sizeof (struct r_search_path_elem));
- rtld_search_dirs.dirs[0] = (struct r_search_path_elem *)
- malloc ((sizeof (system_dirs) / sizeof (system_dirs[0]))
- * round_size * sizeof (struct r_search_path_elem));
+ rtld_search_dirs.dirs[0] = malloc (nsystem_dirs_len * round_size
+ * sizeof (*rtld_search_dirs.dirs[0]));
if (rtld_search_dirs.dirs[0] == NULL)
{
errstring = N_("cannot create cache for search path");
@@ -776,37 +793,14 @@ _dl_init_paths (const char *llp)
if (llp != NULL && *llp != '\0')
{
- size_t nllp;
- const char *cp = llp;
- char *llp_tmp;
-
-#ifdef SHARED
- /* Expand DSTs. */
- size_t cnt = DL_DST_COUNT (llp, 1);
- if (__glibc_likely (cnt == 0))
- llp_tmp = strdupa (llp);
- else
- {
- /* Determine the length of the substituted string. */
- size_t total = DL_DST_REQUIRED (l, llp, strlen (llp), cnt);
-
- /* Allocate the necessary memory. */
- llp_tmp = (char *) alloca (total + 1);
- llp_tmp = _dl_dst_substitute (l, llp, llp_tmp, 1);
- }
-#else
- llp_tmp = strdupa (llp);
-#endif
+ char *llp_tmp = strdupa (llp);
/* Decompose the LD_LIBRARY_PATH contents. First determine how many
elements it has. */
- nllp = 1;
- while (*cp)
- {
- if (*cp == ':' || *cp == ';')
- ++nllp;
- ++cp;
- }
+ size_t nllp = 1;
+ for (const char *cp = llp_tmp; *cp != '\0'; ++cp)
+ if (*cp == ':' || *cp == ';')
+ ++nllp;
env_path_list.dirs = (struct r_search_path_elem **)
malloc ((nllp + 1) * sizeof (struct r_search_path_elem *));
diff --git a/include/array_length.h b/include/array_length.h
new file mode 100644
index 00000000000..cb4a8b2a56b
--- /dev/null
+++ b/include/array_length.h
@@ -0,0 +1,36 @@
+/* The array_length and array_end macros.
+ Copyright (C) 2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _ARRAY_LENGTH_H
+#define _ARRAY_LENGTH_H
+
+/* array_length (VAR) is the number of elements in the array VAR. VAR
+ must evaluate to an array, not a pointer. */
+#define array_length(var) \
+ __extension__ ({ \
+ _Static_assert (!__builtin_types_compatible_p \
+ (__typeof (var), __typeof (&(var)[0])), \
+ "argument must be an array"); \
+ sizeof (var) / sizeof ((var)[0]); \
+ })
+
+/* array_end (VAR) is a pointer one past the end of the array VAR.
+ VAR must evaluate to an array, not a pointer. */
+#define array_end(var) (&(var)[array_length (var)])
+
+#endif /* _ARRAY_LENGTH_H */
diff --git a/io/Makefile b/io/Makefile
index 2f26bf56dbc..f0bdc838bb6 100644
--- a/io/Makefile
+++ b/io/Makefile
@@ -70,7 +70,7 @@ tests := test-utime test-stat test-stat2 test-lfs tst-getcwd \
tst-symlinkat tst-linkat tst-readlinkat tst-mkdirat \
tst-mknodat tst-mkfifoat tst-ttyname_r bug-ftw5 \
tst-posix_fallocate tst-posix_fallocate64 \
- tst-fts tst-fts-lfs tst-open-tmpfile
+ tst-fts tst-fts-lfs tst-open-tmpfile tst-getcwd-abspath
ifeq ($(run-built-tests),yes)
tests-special += $(objpfx)ftwtest.out
diff --git a/io/tst-getcwd-abspath.c b/io/tst-getcwd-abspath.c
new file mode 100644
index 00000000000..3a3636f2ede
--- /dev/null
+++ b/io/tst-getcwd-abspath.c
@@ -0,0 +1,66 @@
+/* BZ #22679 getcwd(3) should not succeed without returning an absolute path.
+
+ 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
+ <https://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.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/xunistd.h>
+#include <unistd.h>
+
+static char *chroot_dir;
+
+/* The actual test. Run it in a subprocess, so that the test harness
+ can remove the temporary directory in --direct mode. */
+static void
+getcwd_callback (void *closure)
+{
+ xchroot (chroot_dir);
+
+ errno = 0;
+ char *cwd = getcwd (NULL, 0);
+ TEST_COMPARE (errno, ENOENT);
+ TEST_VERIFY (cwd == NULL);
+
+ errno = 0;
+ cwd = realpath (".", NULL);
+ TEST_COMPARE (errno, ENOENT);
+ TEST_VERIFY (cwd == NULL);
+
+ _exit (0);
+}
+
+static int
+do_test (void)
+{
+ support_become_root ();
+ if (!support_can_chroot ())
+ return EXIT_UNSUPPORTED;
+
+ chroot_dir = support_create_temp_directory ("tst-getcwd-abspath-");
+ support_isolate_in_subprocess (getcwd_callback, NULL);
+
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/malloc/arena.c b/malloc/arena.c
index dc14fae152f..afd423240a2 100644
--- a/malloc/arena.c
+++ b/malloc/arena.c
@@ -116,7 +116,7 @@ int __malloc_initialized = -1;
} while (0)
#define arena_lock(ptr, size) do { \
- if (ptr && !arena_is_corrupt (ptr)) \
+ if (ptr) \
__libc_lock_lock (ptr->mutex); \
else \
ptr = arena_get2 ((size), NULL); \
@@ -215,8 +215,7 @@ void
TUNABLE_CALLBACK (set_mallopt_check) (tunable_val_t *valp)
{
int32_t value = (int32_t) valp->numval;
- do_set_mallopt_check (value);
- if (check_action != 0)
+ if (value != 0)
__malloc_check_init ();
}
@@ -397,12 +396,8 @@ ptmalloc_init (void)
}
}
}
- if (s && s[0])
- {
- __libc_mallopt (M_CHECK_ACTION, (int) (s[0] - '0'));
- if (check_action != 0)
- __malloc_check_init ();
- }
+ if (s && s[0] != '\0' && s[0] != '0')
+ __malloc_check_init ();
#endif
#if HAVE_MALLOC_INIT_HOOK
@@ -837,7 +832,7 @@ reused_arena (mstate avoid_arena)
result = next_to_use;
do
{
- if (!arena_is_corrupt (result) && !__libc_lock_trylock (result->mutex))
+ if (!__libc_lock_trylock (result->mutex))
goto out;
/* FIXME: This is a data race, see _int_new_arena. */
@@ -850,18 +845,6 @@ reused_arena (mstate avoid_arena)
if (result == avoid_arena)
result = result->next;
- /* Make sure that the arena we get is not corrupted. */
- mstate begin = result;
- while (arena_is_corrupt (result) || result == avoid_arena)
- {
- result = result->next;
- if (result == begin)
- /* We looped around the arena list. We could not find any
- arena that was either not corrupted or not the one we
- wanted to avoid. */
- return NULL;
- }
-
/* No arena available without contention. Wait for the next in line. */
LIBC_PROBE (memory_arena_reuse_wait, 3, &result->mutex, result, avoid_arena);
__libc_lock_lock (result->mutex);
@@ -958,10 +941,6 @@ arena_get_retry (mstate ar_ptr, size_t bytes)
if (ar_ptr != &main_arena)
{
__libc_lock_unlock (ar_ptr->mutex);
- /* Don't touch the main arena if it is corrupt. */
- if (arena_is_corrupt (&main_arena))
- return NULL;
-
ar_ptr = &main_arena;
__libc_lock_lock (ar_ptr->mutex);
}
diff --git a/malloc/hooks.c b/malloc/hooks.c
index 1d80be20d28..2c6cebc889a 100644
--- a/malloc/hooks.c
+++ b/malloc/hooks.c
@@ -121,12 +121,7 @@ malloc_check_get_size (mchunkptr p)
size -= c)
{
if (c <= 0 || size < (c + 2 * SIZE_SZ))
- {
- malloc_printerr (check_action, "malloc_check_get_size: memory corruption",
- chunk2mem (p),
- chunk_is_mmapped (p) ? NULL : arena_for_chunk (p));
- return 0;
- }
+ malloc_printerr ("malloc_check_get_size: memory corruption");
}
/* chunk2mem size. */
@@ -232,17 +227,11 @@ mem2chunk_check (void *mem, unsigned char **magic_p)
return p;
}
-/* Check for corruption of the top chunk, and try to recover if
- necessary. */
-
-static int
-internal_function
+/* Check for corruption of the top chunk. */
+static void
top_check (void)
{
mchunkptr t = top (&main_arena);
- char *brk, *new_brk;
- INTERNAL_SIZE_T front_misalign, sbrk_size;
- unsigned long pagesz = GLRO (dl_pagesize);
if (t == initial_top (&main_arena) ||
(!chunk_is_mmapped (t) &&
@@ -250,34 +239,9 @@ top_check (void)
prev_inuse (t) &&
(!contiguous (&main_arena) ||
(char *) t + chunksize (t) == mp_.sbrk_base + main_arena.system_mem)))
- return 0;
-
- malloc_printerr (check_action, "malloc: top chunk is corrupt", t,
- &main_arena);
-
- /* Try to set up a new top chunk. */
- brk = MORECORE (0);
- front_misalign = (unsigned long) chunk2mem (brk) & MALLOC_ALIGN_MASK;
- if (front_misalign > 0)
- front_misalign = MALLOC_ALIGNMENT - front_misalign;
- sbrk_size = front_misalign + mp_.top_pad + MINSIZE;
- sbrk_size += pagesz - ((unsigned long) (brk + sbrk_size) & (pagesz - 1));
- new_brk = (char *) (MORECORE (sbrk_size));
- if (new_brk == (char *) (MORECORE_FAILURE))
- {
- __set_errno (ENOMEM);
- return -1;
- }
- /* Call the `morecore' hook if necessary. */
- void (*hook) (void) = atomic_forced_read (__after_morecore_hook);
- if (hook)
- (*hook)();
- main_arena.system_mem = (new_brk - mp_.sbrk_base) + sbrk_size;
-
- top (&main_arena) = (mchunkptr) (brk + front_misalign);
- set_head (top (&main_arena), (sbrk_size - front_misalign) | PREV_INUSE);
+ return;
- return 0;
+ malloc_printerr ("malloc: top chunk is corrupt");
}
static void *
@@ -292,7 +256,8 @@ malloc_check (size_t sz, const void *caller)
}
__libc_lock_lock (main_arena.mutex);
- victim = (top_check () >= 0) ? _int_malloc (&main_arena, sz + 1) : NULL;
+ top_check ();
+ victim = _int_malloc (&main_arena, sz + 1);
__libc_lock_unlock (main_arena.mutex);
return mem2mem_check (victim, sz);
}
@@ -308,13 +273,7 @@ free_check (void *mem, const void *caller)
__libc_lock_lock (main_arena.mutex);
p = mem2chunk_check (mem, NULL);
if (!p)
- {
- __libc_lock_unlock (main_arena.mutex);
-
- malloc_printerr (check_action, "free(): invalid pointer", mem,
- &main_arena);
- return;
- }
+ malloc_printerr ("free(): invalid pointer");
if (chunk_is_mmapped (p))
{
__libc_lock_unlock (main_arena.mutex);
@@ -349,11 +308,7 @@ realloc_check (void *oldmem, size_t bytes, const void *caller)
const mchunkptr oldp = mem2chunk_check (oldmem, &magic_p);
__libc_lock_unlock (main_arena.mutex);
if (!oldp)
- {
- malloc_printerr (check_action, "realloc(): invalid pointer", oldmem,
- &main_arena);
- return malloc_check (bytes, NULL);
- }
+ malloc_printerr ("realloc(): invalid pointer");
const INTERNAL_SIZE_T oldsize = chunksize (oldp);
checked_request2size (bytes + 1, nb);
@@ -374,8 +329,8 @@ realloc_check (void *oldmem, size_t bytes, const void *caller)
else
{
/* Must alloc, copy, free. */
- if (top_check () >= 0)
- newmem = _int_malloc (&main_arena, bytes + 1);
+ top_check ();
+ newmem = _int_malloc (&main_arena, bytes + 1);
if (newmem)
{
memcpy (newmem, oldmem, oldsize - 2 * SIZE_SZ);
@@ -386,19 +341,24 @@ realloc_check (void *oldmem, size_t bytes, const void *caller)
}
else
{
- if (top_check () >= 0)
- {
- INTERNAL_SIZE_T nb;
- checked_request2size (bytes + 1, nb);
- newmem = _int_realloc (&main_arena, oldp, oldsize, nb);
- }
+ top_check ();
+ INTERNAL_SIZE_T nb;
+ checked_request2size (bytes + 1, nb);
+ newmem = _int_realloc (&main_arena, oldp, oldsize, nb);
}
+ DIAG_PUSH_NEEDS_COMMENT;
+#if __GNUC_PREREQ (7, 0)
+ /* GCC 7 warns about magic_p may be used uninitialized. But we never
+ reach here if magic_p is uninitialized. */
+ DIAG_IGNORE_NEEDS_COMMENT (7, "-Wmaybe-uninitialized");
+#endif
/* mem2chunk_check changed the magic byte in the old chunk.
If newmem is NULL, then the old chunk will still be used though,
so we need to invert that change here. */
if (newmem == NULL)
*magic_p ^= 0xFF;
+ DIAG_POP_NEEDS_COMMENT;
__libc_lock_unlock (main_arena.mutex);
@@ -441,8 +401,8 @@ memalign_check (size_t alignment, size_t bytes, const void *caller)
}
__libc_lock_lock (main_arena.mutex);
- mem = (top_check () >= 0) ? _int_memalign (&main_arena, alignment, bytes + 1) :
- NULL;
+ top_check ();
+ mem = _int_memalign (&main_arena, alignment, bytes + 1);
__libc_lock_unlock (main_arena.mutex);
return mem2mem_check (mem, bytes);
}
diff --git a/malloc/malloc.c b/malloc/malloc.c
index dd9f699d978..6a52c288de5 100644
--- a/malloc/malloc.c
+++ b/malloc/malloc.c
@@ -243,6 +243,9 @@
#include <malloc/malloc-internal.h>
+/* For SINGLE_THREAD_P. */
+#include <sysdep-cancel.h>
+
/*
Debugging:
@@ -1019,10 +1022,10 @@ static void* _int_realloc(mstate, mchunkptr, INTERNAL_SIZE_T,
static void* _int_memalign(mstate, size_t, size_t);
static void* _mid_memalign(size_t, size_t, void *);
-static void malloc_printerr(int action, const char *str, void *ptr, mstate av);
+static void malloc_printerr(const char *str) __attribute__ ((noreturn));
static void* internal_function mem2mem_check(void *p, size_t sz);
-static int internal_function top_check(void);
+static void top_check (void);
static void internal_function munmap_chunk(mchunkptr p);
#if HAVE_MREMAP
static mchunkptr internal_function mremap_chunk(mchunkptr p, size_t new_size);
@@ -1403,11 +1406,11 @@ typedef struct malloc_chunk *mbinptr;
/* Take a chunk off a bin list */
#define unlink(AV, P, BK, FD) { \
if (__builtin_expect (chunksize(P) != prev_size (next_chunk(P)), 0)) \
- malloc_printerr (check_action, "corrupted size vs. prev_size", P, AV); \
+ malloc_printerr ("corrupted size vs. prev_size"); \
FD = P->fd; \
BK = P->bk; \
if (__builtin_expect (FD->bk != P || BK->fd != P, 0)) \
- malloc_printerr (check_action, "corrupted double-linked list", P, AV); \
+ malloc_printerr ("corrupted double-linked list"); \
else { \
FD->bk = BK; \
BK->fd = FD; \
@@ -1415,9 +1418,7 @@ typedef struct malloc_chunk *mbinptr;
&& __builtin_expect (P->fd_nextsize != NULL, 0)) { \
if (__builtin_expect (P->fd_nextsize->bk_nextsize != P, 0) \
|| __builtin_expect (P->bk_nextsize->fd_nextsize != P, 0)) \
- malloc_printerr (check_action, \
- "corrupted double-linked list (not small)", \
- P, AV); \
+ malloc_printerr ("corrupted double-linked list (not small)"); \
if (FD->fd_nextsize == NULL) { \
if (P->fd_nextsize == P) \
FD->fd_nextsize = FD->bk_nextsize = FD; \
@@ -1628,15 +1629,6 @@ typedef struct malloc_chunk *mfastbinptr;
#define set_noncontiguous(M) ((M)->flags |= NONCONTIGUOUS_BIT)
#define set_contiguous(M) ((M)->flags &= ~NONCONTIGUOUS_BIT)
-/* ARENA_CORRUPTION_BIT is set if a memory corruption was detected on the
- arena. Such an arena is no longer used to allocate chunks. Chunks
- allocated in that arena before detecting corruption are not freed. */
-
-#define ARENA_CORRUPTION_BIT (4U)
-
-#define arena_is_corrupt(A) (((A)->flags & ARENA_CORRUPTION_BIT))
-#define set_arena_corrupt(A) ((A)->flags |= ARENA_CORRUPTION_BIT)
-
/* Maximum size of memory handled in fastbins. */
static INTERNAL_SIZE_T global_max_fast;
@@ -1886,15 +1878,6 @@ void *weak_variable (*__memalign_hook)
void weak_variable (*__after_morecore_hook) (void) = NULL;
-/* ---------------- Error behavior ------------------------------------ */
-
-#ifndef DEFAULT_CHECK_ACTION
-# define DEFAULT_CHECK_ACTION 3
-#endif
-
-static int check_action = DEFAULT_CHECK_ACTION;
-
-
/* ------------------ Testing support ----------------------------------*/
static int perturb_byte;
@@ -2567,11 +2550,8 @@ sysmalloc (INTERNAL_SIZE_T nb, mstate av)
set_head (old_top, (size + old_size) | PREV_INUSE);
else if (contiguous (av) && old_size && brk < old_end)
- {
- /* Oops! Someone else killed our space.. Can't touch anything. */
- malloc_printerr (3, "break adjusted to free malloc space", brk,
- av);
- }
+ /* Oops! Someone else killed our space.. Can't touch anything. */
+ malloc_printerr ("break adjusted to free malloc space");
/*
Otherwise, make adjustments:
@@ -2862,11 +2842,7 @@ munmap_chunk (mchunkptr p)
(in the moment at least) so we combine the two values into one before
the bit test. */
if (__builtin_expect (((block | total_size) & (GLRO (dl_pagesize) - 1)) != 0, 0))
- {
- malloc_printerr (check_action, "munmap_chunk(): invalid pointer",
- chunk2mem (p), NULL);
- return;
- }
+ malloc_printerr ("munmap_chunk(): invalid pointer");
atomic_decrement (&mp_.n_mmaps);
atomic_add (&mp_.mmapped_mem, -total_size);
@@ -3053,7 +3029,8 @@ __libc_malloc (size_t bytes)
return (*hook)(bytes, RETURN_ADDRESS (0));
#if USE_TCACHE
/* int_free also calls request2size, be careful to not pad twice. */
- size_t tbytes = request2size (bytes);
+ size_t tbytes;
+ checked_request2size (bytes, tbytes);
size_t tc_idx = csize2tidx (tbytes);
MAYBE_INIT_TCACHE ();
@@ -3069,6 +3046,14 @@ __libc_malloc (size_t bytes)
DIAG_POP_NEEDS_COMMENT;
#endif
+ if (SINGLE_THREAD_P)
+ {
+ victim = _int_malloc (&main_arena, bytes);
+ assert (!victim || chunk_is_mmapped (mem2chunk (victim)) ||
+ &main_arena == arena_for_chunk (mem2chunk (victim)));
+ return victim;
+ }
+
arena_get (ar_ptr, bytes);
victim = _int_malloc (ar_ptr, bytes);
@@ -3180,11 +3165,7 @@ __libc_realloc (void *oldmem, size_t bytes)
if ((__builtin_expect ((uintptr_t) oldp > (uintptr_t) -oldsize, 0)
|| __builtin_expect (misaligned_chunk (oldp), 0))
&& !DUMPED_MAIN_ARENA_CHUNK (oldp))
- {
- malloc_printerr (check_action, "realloc(): invalid pointer", oldmem,
- ar_ptr);
- return NULL;
- }
+ malloc_printerr ("realloc(): invalid pointer");
checked_request2size (bytes, nb);
@@ -3229,6 +3210,15 @@ __libc_realloc (void *oldmem, size_t bytes)
return newmem;
}
+ if (SINGLE_THREAD_P)
+ {
+ newp = _int_realloc (ar_ptr, oldp, oldsize, nb);
+ assert (!newp || chunk_is_mmapped (mem2chunk (newp)) ||
+ ar_ptr == arena_for_chunk (mem2chunk (newp)));
+
+ return newp;
+ }
+
__libc_lock_lock (ar_ptr->mutex);
newp = _int_realloc (ar_ptr, oldp, oldsize, nb);
@@ -3304,6 +3294,15 @@ _mid_memalign (size_t alignment, size_t bytes, void *address)
alignment = a;
}
+ if (SINGLE_THREAD_P)
+ {
+ p = _int_memalign (&main_arena, alignment, bytes);
+ assert (!p || chunk_is_mmapped (mem2chunk (p)) ||
+ &main_arena == arena_for_chunk (mem2chunk (p)));
+
+ return p;
+ }
+
arena_get (ar_ptr, bytes + alignment + MINSIZE);
p = _int_memalign (ar_ptr, alignment, bytes);
@@ -3396,7 +3395,11 @@ __libc_calloc (size_t n, size_t elem_size)
MAYBE_INIT_TCACHE ();
- arena_get (av, sz);
+ if (SINGLE_THREAD_P)
+ av = &main_arena;
+ else
+ arena_get (av, sz);
+
if (av)
{
/* Check if we hand out the top chunk, in which case there may be no
@@ -3426,19 +3429,21 @@ __libc_calloc (size_t n, size_t elem_size)
}
mem = _int_malloc (av, sz);
-
assert (!mem || chunk_is_mmapped (mem2chunk (mem)) ||
av == arena_for_chunk (mem2chunk (mem)));
- if (mem == 0 && av != NULL)
+ if (!SINGLE_THREAD_P)
{
- LIBC_PROBE (memory_calloc_retry, 1, sz);
- av = arena_get_retry (av, sz);
- mem = _int_malloc (av, sz);
- }
+ if (mem == 0 && av != NULL)
+ {
+ LIBC_PROBE (memory_calloc_retry, 1, sz);
+ av = arena_get_retry (av, sz);
+ mem = _int_malloc (av, sz);
+ }
- if (av != NULL)
- __libc_lock_unlock (av->mutex);
+ if (av != NULL)
+ __libc_lock_unlock (av->mutex);
+ }
/* Allocation failed even after a retry. */
if (mem == 0)
@@ -3530,8 +3535,6 @@ _int_malloc (mstate av, size_t bytes)
size_t tcache_unsorted_count; /* count of unsorted chunks processed */
#endif
- const char *errstr = NULL;
-
/*
Convert request size to internal form by adding SIZE_SZ bytes
overhead plus possibly more to obtain necessary alignment and/or
@@ -3573,42 +3576,50 @@ _int_malloc (mstate av, size_t bytes)
{
idx = fastbin_index (nb);
mfastbinptr *fb = &fastbin (av, idx);
- mchunkptr pp = *fb;
- REMOVE_FB (fb, victim, pp);
- if (victim != 0)
- {
- if (__builtin_expect (fastbin_index (chunksize (victim)) != idx, 0))
- {
- errstr = "malloc(): memory corruption (fast)";
- errout:
- malloc_printerr (check_action, errstr, chunk2mem (victim), av);
- return NULL;
- }
- check_remalloced_chunk (av, victim, nb);
-#if USE_TCACHE
- /* While we're here, if we see other chunks of the same size,
- stash them in the tcache. */
- size_t tc_idx = csize2tidx (nb);
- if (tcache && tc_idx < mp_.tcache_bins)
- {
- mchunkptr tc_victim;
+ mchunkptr pp;
+ victim = *fb;
- /* While bin not empty and tcache not full, copy chunks over. */
- while (tcache->counts[tc_idx] < mp_.tcache_count
- && (pp = *fb) != NULL)
+ if (victim != NULL)
+ {
+ if (SINGLE_THREAD_P)
+ *fb = victim->fd;
+ else
+ REMOVE_FB (fb, pp, victim);
+ if (__glibc_likely (victim != NULL))
+ {
+ size_t victim_idx = fastbin_index (chunksize (victim));
+ if (__builtin_expect (victim_idx != idx, 0))
+ malloc_printerr ("malloc(): memory corruption (fast)");
+ check_remalloced_chunk (av, victim, nb);
+#if USE_TCACHE
+ /* While we're here, if we see other chunks of the same size,
+ stash them in the tcache. */
+ size_t tc_idx = csize2tidx (nb);
+ if (tcache && tc_idx < mp_.tcache_bins)
{
- REMOVE_FB (fb, tc_victim, pp);
- if (tc_victim != 0)
+ mchunkptr tc_victim;
+
+ /* While bin not empty and tcache not full, copy chunks. */
+ while (tcache->counts[tc_idx] < mp_.tcache_count
+ && (tc_victim = *fb) != NULL)
{
+ if (SINGLE_THREAD_P)
+ *fb = tc_victim->fd;
+ else
+ {
+ REMOVE_FB (fb, pp, tc_victim);
+ if (__glibc_unlikely (tc_victim == NULL))
+ break;
+ }
tcache_put (tc_victim, tc_idx);
- }
+ }
}
- }
#endif
- void *p = chunk2mem (victim);
- alloc_perturb (p, bytes);
- return p;
- }
+ void *p = chunk2mem (victim);
+ alloc_perturb (p, bytes);
+ return p;
+ }
+ }
}
/*
@@ -3631,11 +3642,9 @@ _int_malloc (mstate av, size_t bytes)
else
{
bck = victim->bk;
- if (__glibc_unlikely (bck->fd != victim))
- {
- errstr = "malloc(): smallbin double linked list corrupted";
- goto errout;
- }
+ if (__glibc_unlikely (bck->fd != victim))
+ malloc_printerr
+ ("malloc(): smallbin double linked list corrupted");
set_inuse_bit_at_offset (victim, nb);
bin->bk = bck;
bck->fd = bin;
@@ -3726,8 +3735,7 @@ _int_malloc (mstate av, size_t bytes)
if (__builtin_expect (chunksize_nomask (victim) <= 2 * SIZE_SZ, 0)
|| __builtin_expect (chunksize_nomask (victim)
> av->system_mem, 0))
- malloc_printerr (check_action, "malloc(): memory corruption",
- chunk2mem (victim), av);
+ malloc_printerr ("malloc(): memory corruption");
size = chunksize (victim);
/*
@@ -3932,11 +3940,8 @@ _int_malloc (mstate av, size_t bytes)
have to perform a complete insert here. */
bck = unsorted_chunks (av);
fwd = bck->fd;
- if (__glibc_unlikely (fwd->bk != bck))
- {
- errstr = "malloc(): corrupted unsorted chunks";
- goto errout;
- }
+ if (__glibc_unlikely (fwd->bk != bck))
+ malloc_printerr ("malloc(): corrupted unsorted chunks");
remainder->bk = bck;
remainder->fd = fwd;
bck->fd = remainder;
@@ -4039,11 +4044,8 @@ _int_malloc (mstate av, size_t bytes)
have to perform a complete insert here. */
bck = unsorted_chunks (av);
fwd = bck->fd;
- if (__glibc_unlikely (fwd->bk != bck))
- {
- errstr = "malloc(): corrupted unsorted chunks 2";
- goto errout;
- }
+ if (__glibc_unlikely (fwd->bk != bck))
+ malloc_printerr ("malloc(): corrupted unsorted chunks 2");
remainder->bk = bck;
remainder->fd = fwd;
bck->fd = remainder;
@@ -4144,9 +4146,6 @@ _int_free (mstate av, mchunkptr p, int have_lock)
mchunkptr bck; /* misc temp for linking */
mchunkptr fwd; /* misc temp for linking */
- const char *errstr = NULL;
- int locked = 0;
-
size = chunksize (p);
/* Little security check which won't hurt performance: the
@@ -4155,21 +4154,11 @@ _int_free (mstate av, mchunkptr p, int have_lock)
here by accident or by "design" from some intruder. */
if (__builtin_expect ((uintptr_t) p > (uintptr_t) -size, 0)
|| __builtin_expect (misaligned_chunk (p), 0))
- {
- errstr = "free(): invalid pointer";
- errout:
- if (!have_lock && locked)
- __libc_lock_unlock (av->mutex);
- malloc_printerr (check_action, errstr, chunk2mem (p), av);
- return;
- }
+ malloc_printerr ("free(): invalid pointer");
/* We know that each chunk is at least MINSIZE bytes in size or a
multiple of MALLOC_ALIGNMENT. */
if (__glibc_unlikely (size < MINSIZE || !aligned_OK (size)))
- {
- errstr = "free(): invalid size";
- goto errout;
- }
+ malloc_printerr ("free(): invalid size");
check_inuse_chunk(av, p);
@@ -4208,25 +4197,20 @@ _int_free (mstate av, mchunkptr p, int have_lock)
|| __builtin_expect (chunksize (chunk_at_offset (p, size))
>= av->system_mem, 0))
{
+ bool fail = true;
/* We might not have a lock at this point and concurrent modifications
- of system_mem might have let to a false positive. Redo the test
- after getting the lock. */
- if (have_lock
- || ({ assert (locked == 0);
- __libc_lock_lock (av->mutex);
- locked = 1;
- chunksize_nomask (chunk_at_offset (p, size)) <= 2 * SIZE_SZ
- || chunksize (chunk_at_offset (p, size)) >= av->system_mem;
- }))
- {
- errstr = "free(): invalid next size (fast)";
- goto errout;
- }
- if (! have_lock)
+ of system_mem might result in a false positive. Redo the test after
+ getting the lock. */
+ if (!have_lock)
{
+ __libc_lock_lock (av->mutex);
+ fail = (chunksize_nomask (chunk_at_offset (p, size)) <= 2 * SIZE_SZ
+ || chunksize (chunk_at_offset (p, size)) >= av->system_mem);
__libc_lock_unlock (av->mutex);
- locked = 0;
}
+
+ if (fail)
+ malloc_printerr ("free(): invalid next size (fast)");
}
free_perturb (chunk2mem(p), size - 2 * SIZE_SZ);
@@ -4237,31 +4221,35 @@ _int_free (mstate av, mchunkptr p, int have_lock)
/* Atomically link P to its fastbin: P->FD = *FB; *FB = P; */
mchunkptr old = *fb, old2;
- unsigned int old_idx = ~0u;
- do
- {
- /* Check that the top of the bin is not the record we are going to add
- (i.e., double free). */
- if (__builtin_expect (old == p, 0))
- {
- errstr = "double free or corruption (fasttop)";
- goto errout;
- }
- /* Check that size of fastbin chunk at the top is the same as
- size of the chunk that we are adding. We can dereference OLD
- only if we have the lock, otherwise it might have already been
- deallocated. See use of OLD_IDX below for the actual check. */
- if (have_lock && old != NULL)
- old_idx = fastbin_index(chunksize(old));
- p->fd = old2 = old;
- }
- while ((old = catomic_compare_and_exchange_val_rel (fb, p, old2)) != old2);
- if (have_lock && old != NULL && __builtin_expect (old_idx != idx, 0))
+ if (SINGLE_THREAD_P)
{
- errstr = "invalid fastbin entry (free)";
- goto errout;
+ /* Check that the top of the bin is not the record we are going to
+ add (i.e., double free). */
+ if (__builtin_expect (old == p, 0))
+ malloc_printerr ("double free or corruption (fasttop)");
+ p->fd = old;
+ *fb = p;
}
+ else
+ do
+ {
+ /* Check that the top of the bin is not the record we are going to
+ add (i.e., double free). */
+ if (__builtin_expect (old == p, 0))
+ malloc_printerr ("double free or corruption (fasttop)");
+ p->fd = old2 = old;
+ }
+ while ((old = catomic_compare_and_exchange_val_rel (fb, p, old2))
+ != old2);
+
+ /* Check that size of fastbin chunk at the top is the same as
+ size of the chunk that we are adding. We can dereference OLD
+ only if we have the lock, otherwise it might have already been
+ allocated again. */
+ if (have_lock && old != NULL
+ && __builtin_expect (fastbin_index (chunksize (old)) != idx, 0))
+ malloc_printerr ("invalid fastbin entry (free)");
}
/*
@@ -4269,42 +4257,33 @@ _int_free (mstate av, mchunkptr p, int have_lock)
*/
else if (!chunk_is_mmapped(p)) {
- if (! have_lock) {
+
+ /* If we're single-threaded, don't lock the arena. */
+ if (SINGLE_THREAD_P)
+ have_lock = true;
+
+ if (!have_lock)
__libc_lock_lock (av->mutex);
- locked = 1;
- }
nextchunk = chunk_at_offset(p, size);
/* Lightweight tests: check whether the block is already the
top block. */
if (__glibc_unlikely (p == av->top))
- {
- errstr = "double free or corruption (top)";
- goto errout;
- }
+ malloc_printerr ("double free or corruption (top)");
/* Or whether the next chunk is beyond the boundaries of the arena. */
if (__builtin_expect (contiguous (av)
&& (char *) nextchunk
>= ((char *) av->top + chunksize(av->top)), 0))
- {
- errstr = "double free or corruption (out)";
- goto errout;
- }
+ malloc_printerr ("double free or corruption (out)");
/* Or whether the block is actually not marked used. */
if (__glibc_unlikely (!prev_inuse(nextchunk)))
- {
- errstr = "double free or corruption (!prev)";
- goto errout;
- }
+ malloc_printerr ("double free or corruption (!prev)");
nextsize = chunksize(nextchunk);
if (__builtin_expect (chunksize_nomask (nextchunk) <= 2 * SIZE_SZ, 0)
|| __builtin_expect (nextsize >= av->system_mem, 0))
- {
- errstr = "free(): invalid next size (normal)";
- goto errout;
- }
+ malloc_printerr ("free(): invalid next size (normal)");
free_perturb (chunk2mem(p), size - 2 * SIZE_SZ);
@@ -4336,10 +4315,7 @@ _int_free (mstate av, mchunkptr p, int have_lock)
bck = unsorted_chunks(av);
fwd = bck->fd;
if (__glibc_unlikely (fwd->bk != bck))
- {
- errstr = "free(): corrupted unsorted chunks";
- goto errout;
- }
+ malloc_printerr ("free(): corrupted unsorted chunks");
p->fd = fwd;
p->bk = bck;
if (!in_smallbin_range(size))
@@ -4401,10 +4377,8 @@ _int_free (mstate av, mchunkptr p, int have_lock)
}
}
- if (! have_lock) {
- assert (locked);
+ if (!have_lock)
__libc_lock_unlock (av->mutex);
- }
}
/*
If the chunk was allocated via mmap, release via munmap().
@@ -4552,17 +4526,10 @@ _int_realloc(mstate av, mchunkptr oldp, INTERNAL_SIZE_T oldsize,
INTERNAL_SIZE_T* s; /* copy source */
INTERNAL_SIZE_T* d; /* copy destination */
- const char *errstr = NULL;
-
/* oldmem size */
if (__builtin_expect (chunksize_nomask (oldp) <= 2 * SIZE_SZ, 0)
|| __builtin_expect (oldsize >= av->system_mem, 0))
- {
- errstr = "realloc(): invalid old size";
- errout:
- malloc_printerr (check_action, errstr, chunk2mem (oldp), av);
- return NULL;
- }
+ malloc_printerr ("realloc(): invalid old size");
check_inuse_chunk (av, oldp);
@@ -4573,10 +4540,7 @@ _int_realloc(mstate av, mchunkptr oldp, INTERNAL_SIZE_T oldsize,
INTERNAL_SIZE_T nextsize = chunksize (next);
if (__builtin_expect (chunksize_nomask (next) <= 2 * SIZE_SZ, 0)
|| __builtin_expect (nextsize >= av->system_mem, 0))
- {
- errstr = "realloc(): invalid next size";
- goto errout;
- }
+ malloc_printerr ("realloc(): invalid next size");
if ((unsigned long) (oldsize) >= (unsigned long) (nb))
{
@@ -4801,10 +4765,6 @@ _int_memalign (mstate av, size_t alignment, size_t bytes)
static int
mtrim (mstate av, size_t pad)
{
- /* Don't touch corrupt arenas. */
- if (arena_is_corrupt (av))
- return 0;
-
/* Ensure initialization/consolidation */
malloc_consolidate (av);
@@ -5116,8 +5076,6 @@ static inline int
__always_inline
do_set_mallopt_check (int32_t value)
{
- LIBC_PROBE (memory_mallopt_check_action, 2, value, check_action);
- check_action = value;
return 1;
}
@@ -5391,32 +5349,10 @@ libc_hidden_def (__libc_mallopt)
extern char **__libc_argv attribute_hidden;
static void
-malloc_printerr (int action, const char *str, void *ptr, mstate ar_ptr)
+malloc_printerr (const char *str)
{
- /* Avoid using this arena in future. We do not attempt to synchronize this
- with anything else because we minimally want to ensure that __libc_message
- gets its resources safely without stumbling on the current corruption. */
- if (ar_ptr)
- set_arena_corrupt (ar_ptr);
-
- if ((action & 5) == 5)
- __libc_message ((action & 2) ? (do_abort | do_backtrace) : do_message,
- "%s\n", str);
- else if (action & 1)
- {
- char buf[2 * sizeof (uintptr_t) + 1];
-
- buf[sizeof (buf) - 1] = '\0';
- char *cp = _itoa_word ((uintptr_t) ptr, &buf[sizeof (buf) - 1], 16, 0);
- while (cp > buf)
- *--cp = '0';
-
- __libc_message ((action & 2) ? (do_abort | do_backtrace) : do_message,
- "*** Error in `%s': %s: 0x%s ***\n",
- __libc_argv[0] ? : "<unknown>", str, cp);
- }
- else if (action & 2)
- abort ();
+ __libc_message (do_abort, "%s\n", str);
+ __builtin_unreachable ();
}
/* We need a wrapper function for one of the additions of POSIX. */
diff --git a/malloc/tst-realloc.c b/malloc/tst-realloc.c
index 31a58bd0260..d942c6e536f 100644
--- a/malloc/tst-realloc.c
+++ b/malloc/tst-realloc.c
@@ -66,10 +66,6 @@ do_test (void)
if (p == NULL)
merror ("realloc (NULL, 10) failed.");
- /* errno should be clear on success (POSIX). */
- if (p != NULL && save != 0)
- merror ("errno is set but should not be");
-
free (p);
p = calloc (20, 1);
diff --git a/manual/memory.texi b/manual/memory.texi
index 82f473806c2..51a5f4e83c9 100644
--- a/manual/memory.texi
+++ b/manual/memory.texi
@@ -1104,7 +1104,6 @@ When calling @code{mallopt}, the @var{param} argument specifies the
parameter to be set, and @var{value} the new value to be set. Possible
choices for @var{param}, as defined in @file{malloc.h}, are:
-@comment TODO: @item M_CHECK_ACTION
@vtable @code
@item M_MMAP_MAX
The maximum number of chunks to allocate with @code{mmap}. Setting this
@@ -1309,17 +1308,15 @@ The block was already freed.
Another possibility to check for and guard against bugs in the use of
@code{malloc}, @code{realloc} and @code{free} is to set the environment
-variable @code{MALLOC_CHECK_}. When @code{MALLOC_CHECK_} is set, a
-special (less efficient) implementation is used which is designed to be
-tolerant against simple errors, such as double calls of @code{free} with
-the same argument, or overruns of a single byte (off-by-one bugs). Not
-all such errors can be protected against, however, and memory leaks can
-result. If @code{MALLOC_CHECK_} is set to @code{0}, any detected heap
-corruption is silently ignored; if set to @code{1}, a diagnostic is
-printed on @code{stderr}; if set to @code{2}, @code{abort} is called
-immediately. This can be useful because otherwise a crash may happen
-much later, and the true cause for the problem is then very hard to
-track down.
+variable @code{MALLOC_CHECK_}. When @code{MALLOC_CHECK_} is set to a
+non-zero value, a special (less efficient) implementation is used which
+is designed to be tolerant against simple errors, such as double calls
+of @code{free} with the same argument, or overruns of a single byte
+(off-by-one bugs). Not all such errors can be protected against,
+however, and memory leaks can result.
+
+Any detected heap corruption results in immediate termination of the
+process.
There is one problem with @code{MALLOC_CHECK_}: in SUID or SGID binaries
it could possibly be exploited since diverging from the normal programs
diff --git a/manual/probes.texi b/manual/probes.texi
index 96acaed2064..8ab67562d77 100644
--- a/manual/probes.texi
+++ b/manual/probes.texi
@@ -195,13 +195,6 @@ this @code{malloc} parameter, and @var{$arg3} is nonzero if dynamic
threshold adjustment was already disabled.
@end deftp
-@deftp Probe memory_mallopt_check_action (int @var{$arg1}, int @var{$arg2})
-This probe is triggered shortly after the @code{memory_mallopt} probe,
-when the parameter to be changed is @code{M_CHECK_ACTION}. Argument
-@var{$arg1} is the requested value, and @var{$arg2} is the previous
-value of this @code{malloc} parameter.
-@end deftp
-
@deftp Probe memory_mallopt_perturb (int @var{$arg1}, int @var{$arg2})
This probe is triggered shortly after the @code{memory_mallopt} probe,
when the parameter to be changed is @code{M_PERTURB}. Argument
diff --git a/manual/terminal.texi b/manual/terminal.texi
index 4fef5045b84..4aace48b140 100644
--- a/manual/terminal.texi
+++ b/manual/terminal.texi
@@ -109,6 +109,11 @@ The @var{filedes} is not associated with a terminal.
@item ERANGE
The buffer length @var{len} is too small to store the string to be
returned.
+
+@item ENODEV
+The @var{filedes} is associated with a terminal device that is a slave
+pseudo-terminal, but the file name associated with that device could
+not be determined. This is a GNU extension.
@end table
@end deftypefun
diff --git a/manual/tunables.texi b/manual/tunables.texi
index 3c19567a28a..b09e3fe7917 100644
--- a/manual/tunables.texi
+++ b/manual/tunables.texi
@@ -71,27 +71,13 @@ following tunables in the @code{malloc} namespace:
This tunable supersedes the @env{MALLOC_CHECK_} environment variable and is
identical in features.
-Setting this tunable enables a special (less efficient) memory allocator for
-the malloc family of functions that is designed to be tolerant against simple
-errors such as double calls of free with the same argument, or overruns of a
-single byte (off-by-one bugs). Not all such errors can be protected against,
-however, and memory leaks can result. The following list describes the values
-that this tunable can take and the effect they have on malloc functionality:
-
-@itemize @bullet
-@item @code{0} Ignore all errors. The default allocator continues to be in
-use, but all errors are silently ignored.
-@item @code{1} Report errors. The alternate allocator is selected and heap
-corruption, if detected, is reported as diagnostic messages to @code{stderr}
-and the program continues execution.
-@item @code{2} Abort on errors. The alternate allocator is selected and if
-heap corruption is detected, the program is ended immediately by calling
-@code{abort}.
-@item @code{3} Fully enabled. The alternate allocator is selected and is fully
-functional. That is, if heap corruption is detected, a verbose diagnostic
-message is printed to @code{stderr} and the program is ended by calling
-@code{abort}.
-@end itemize
+Setting this tunable to a non-zero value enables a special (less
+efficient) memory allocator for the malloc family of functions that is
+designed to be tolerant against simple errors such as double calls of
+free with the same argument, or overruns of a single byte (off-by-one
+bugs). Not all such errors can be protected against, however, and memory
+leaks can result. Any detected heap corruption results in immediate
+termination of the process.
Like @env{MALLOC_CHECK_}, @code{glibc.malloc.check} has a problem in that it
diverges from normal program behavior by writing to @code{stderr}, which could
diff --git a/math/Makefile b/math/Makefile
index 2c17c68eda7..1039985ea6b 100644
--- a/math/Makefile
+++ b/math/Makefile
@@ -204,7 +204,7 @@ tests-static = test-fpucw-static test-fpucw-ieee-static \
ifneq (,$(CXX))
tests += test-math-isinff test-math-iszero test-math-issignaling \
- test-math-iscanonical
+ test-math-iscanonical test-math-iseqsig
endif
ifneq (no,$(PERL))
diff --git a/math/math.h b/math/math.h
index ba266248353..5a282b8c6b6 100644
--- a/math/math.h
+++ b/math/math.h
@@ -845,8 +845,76 @@ extern int matherr (struct exception *__exc);
/* Return X == Y but raising "invalid" and setting errno if X or Y is
a NaN. */
-# define iseqsig(x, y) \
- __MATH_TG (__MATH_EVAL_FMT2 (x, y), __iseqsig, ((x), (y)))
+# if !defined __cplusplus || (__cplusplus < 201103L && !defined __GNUC__)
+# define iseqsig(x, y) \
+ __MATH_TG (__MATH_EVAL_FMT2 (x, y), __iseqsig, ((x), (y)))
+# else
+/* In C++ mode, __MATH_TG cannot be used, because it relies on
+ __builtin_types_compatible_p, which is a C-only builtin. Moreover,
+ the comparison macros from ISO C take two floating-point arguments,
+ which need not have the same type. Choosing what underlying function
+ to call requires evaluating the formats of the arguments, then
+ selecting which is wider. The macro __MATH_EVAL_FMT2 provides this
+ information, however, only the type of the macro expansion is
+ relevant (actually evaluating the expression would be incorrect).
+ Thus, the type is used as a template parameter for __iseqsig_type,
+ which calls the appropriate underlying function. */
+extern "C++" {
+template<typename> struct __iseqsig_type;
+
+template<> struct __iseqsig_type<float>
+{
+ static int __call (float __x, float __y) throw ()
+ {
+ return __iseqsigf (__x, __y);
+ }
+};
+
+template<> struct __iseqsig_type<double>
+{
+ static int __call (double __x, double __y) throw ()
+ {
+ return __iseqsig (__x, __y);
+ }
+};
+
+template<> struct __iseqsig_type<long double>
+{
+ static int __call (double __x, double __y) throw ()
+ {
+# ifndef __NO_LONG_DOUBLE_MATH
+ return __iseqsigl (__x, __y);
+# else
+ return __iseqsig (__x, __y);
+# endif
+ }
+};
+
+# if __HAVE_DISTINCT_FLOAT128
+template<> struct __iseqsig_type<_Float128>
+{
+ static int __call (_Float128 __x, _Float128 __y) throw ()
+ {
+ return __iseqsigf128 (__x, __y);
+ }
+};
+# endif
+
+template<typename _T1, typename _T2>
+inline int
+iseqsig (_T1 __x, _T2 __y) throw ()
+{
+# if __cplusplus >= 201103L
+ typedef decltype (__MATH_EVAL_FMT2 (__x, __y)) _T3;
+# else
+ typedef __typeof (__MATH_EVAL_FMT2 (__x, __y)) _T3;
+# endif
+ return __iseqsig_type<_T3>::__call (__x, __y);
+}
+
+} /* extern "C++" */
+# endif /* __cplusplus */
+
#endif
__END_DECLS
diff --git a/math/test-math-iseqsig.cc b/math/test-math-iseqsig.cc
new file mode 100644
index 00000000000..48e8f1e7994
--- /dev/null
+++ b/math/test-math-iseqsig.cc
@@ -0,0 +1,111 @@
+/* Test for the C++ implementation of iseqsig.
+ Copyright (C) 2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#define _GNU_SOURCE 1
+#include <math.h>
+#include <stdio.h>
+
+#include <limits>
+
+/* There is no NaN for _Float128 in std::numeric_limits.
+ Include ieee754_float128.h and use the bitfields in the union
+ ieee854_float128.ieee_nan to build a NaN. */
+#if __HAVE_DISTINCT_FLOAT128
+# include <ieee754_float128.h>
+#endif
+
+#include <support/check.h>
+
+static void
+check (int actual, int expected, const char *actual_expr, int line)
+{
+ if (actual != expected)
+ {
+ support_record_failure ();
+ printf ("%s:%d: error: %s\n", __FILE__, line, actual_expr);
+ printf ("%s:%d: expected: %d\n", __FILE__, line, expected);
+ printf ("%s:%d: actual: %d\n", __FILE__, line, actual);
+ }
+}
+
+#define CHECK(actual, expected) \
+ check ((actual), (expected), #actual, __LINE__)
+
+template <class T1, class T2>
+static void
+check_type ()
+{
+ T1 t1 = 0;
+ T2 t2 = 0;
+ CHECK (iseqsig (t1, t2), 1);
+
+ t2 = 1;
+ CHECK (iseqsig (t1, t2), 0);
+
+ if (std::numeric_limits<T1>::has_quiet_NaN
+ && std::numeric_limits<T2>::has_quiet_NaN)
+ {
+ CHECK (iseqsig (std::numeric_limits<T1>::quiet_NaN (), t2), 0);
+ CHECK (iseqsig (t1, std::numeric_limits<T2>::quiet_NaN ()), 0);
+ CHECK (iseqsig (std::numeric_limits<T1>::quiet_NaN (),
+ std::numeric_limits<T2>::quiet_NaN ()), 0);
+ }
+}
+
+#if __HAVE_DISTINCT_FLOAT128
+static void
+check_float128 ()
+{
+ ieee854_float128 q1, q2, q3_nan;
+
+ q1.d = 0;
+ q2.d = 1;
+ q3_nan.ieee_nan.negative = 0;
+ q3_nan.ieee_nan.exponent = 0x7FFF;
+ q3_nan.ieee_nan.quiet_nan = 1;
+ q3_nan.ieee_nan.mantissa0 = 0x0000;
+ q3_nan.ieee_nan.mantissa1 = 0x00000000;
+ q3_nan.ieee_nan.mantissa2 = 0x00000000;
+ q3_nan.ieee_nan.mantissa3 = 0x00000000;
+
+ CHECK (iseqsig (q1.d, q1.d), 1);
+ CHECK (iseqsig (q1.d, q2.d), 0);
+ CHECK (iseqsig (q1.d, q3_nan.d), 0);
+ CHECK (iseqsig (q3_nan.d, q3_nan.d), 0);
+}
+#endif
+
+static int
+do_test (void)
+{
+ check_type<float, float> ();
+ check_type<float, double> ();
+ check_type<float, long double> ();
+ check_type<double, float> ();
+ check_type<double, double> ();
+ check_type<double, long double> ();
+ check_type<long double, float> ();
+ check_type<long double, double> ();
+ check_type<long double, long double> ();
+#if __HAVE_DISTINCT_FLOAT128
+ check_float128 ();
+#endif
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/nptl/Makefile b/nptl/Makefile
index 9ca6d01b8c5..0b01e18106d 100644
--- a/nptl/Makefile
+++ b/nptl/Makefile
@@ -227,6 +227,10 @@ CFLAGS-pt-system.c = -fexceptions
LDLIBS-tst-once5 = -lstdc++
CFLAGS-tst-thread_local1.o = -std=gnu++11
LDLIBS-tst-thread_local1 = -lstdc++
+CFLAGS-tst-thread-exit-clobber.o = -std=gnu++11
+LDLIBS-tst-thread-exit-clobber = -lstdc++
+CFLAGS-tst-minstack-throw.o = -std=gnu++11
+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 \
@@ -302,7 +306,9 @@ tests = tst-attr1 tst-attr2 tst-attr3 tst-default-attr \
c89 gnu89 c99 gnu99 c11 gnu11) \
tst-bad-schedattr \
tst-thread_local1 tst-mutex-errorcheck tst-robust10 \
- tst-robust-fork tst-create-detached tst-memstream
+ tst-robust-fork tst-create-detached tst-memstream \
+ tst-thread-exit-clobber tst-minstack-cancel tst-minstack-exit \
+ tst-minstack-throw
tests-internal := tst-typesizes \
tst-rwlock19 tst-rwlock20 \
@@ -453,7 +459,8 @@ endif
ifeq (,$(CXX))
# These tests require a C++ compiler and runtime.
-tests-unsupported += tst-cancel24 tst-cancel24-static tst-once5
+tests-unsupported += tst-cancel24 tst-cancel24-static tst-once5 \
+ tst-thread-exit-clobber tst-minstack-throw
endif
# These tests require a C++ compiler and runtime with thread_local support.
ifneq ($(have-cxx-thread_local),yes)
diff --git a/nptl/allocatestack.c b/nptl/allocatestack.c
index dff5d3469e6..e351ce9d990 100644
--- a/nptl/allocatestack.c
+++ b/nptl/allocatestack.c
@@ -356,7 +356,7 @@ setup_stack_prot (char *mem, size_t size, char *guard, size_t guardsize,
const int prot)
{
char *guardend = guard + guardsize;
-#if _STACK_GROWS_DOWN
+#if _STACK_GROWS_DOWN && !defined(NEED_SEPARATE_REGISTER_STACK)
/* As defined at guard_position, for architectures with downward stack
the guard page is always at start of the allocated area. */
if (__mprotect (guardend, size - guardsize, prot) != 0)
@@ -372,6 +372,33 @@ setup_stack_prot (char *mem, size_t size, char *guard, size_t guardsize,
return 0;
}
+/* Mark the memory of the stack as usable to the kernel. It frees everything
+ except for the space used for the TCB itself. */
+static inline void
+__always_inline
+advise_stack_range (void *mem, size_t size, uintptr_t pd, size_t guardsize)
+{
+ uintptr_t sp = (uintptr_t) CURRENT_STACK_FRAME;
+ size_t pagesize_m1 = __getpagesize () - 1;
+#if _STACK_GROWS_DOWN && !defined(NEED_SEPARATE_REGISTER_STACK)
+ size_t freesize = (sp - (uintptr_t) mem) & ~pagesize_m1;
+ assert (freesize < size);
+ if (freesize > PTHREAD_STACK_MIN)
+ __madvise (mem, freesize - PTHREAD_STACK_MIN, MADV_DONTNEED);
+#else
+ /* Page aligned start of memory to free (higher than or equal
+ to current sp plus the minimum stack size). */
+ uintptr_t freeblock = (sp + PTHREAD_STACK_MIN + pagesize_m1) & ~pagesize_m1;
+ uintptr_t free_end = (pd - guardsize) & ~pagesize_m1;
+ if (free_end > freeblock)
+ {
+ size_t freesize = free_end - freeblock;
+ assert (freesize < size);
+ __madvise ((void*) freeblock, freesize, MADV_DONTNEED);
+ }
+#endif
+}
+
/* Returns a usable stack for a new thread either by allocating a
new stack or reusing a cached stack of sufficient size.
ATTR must be non-NULL and point to a valid pthread_attr.
@@ -506,6 +533,10 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
/* Make sure the size of the stack is enough for the guard and
eventually the thread descriptor. */
guardsize = (attr->guardsize + pagesize_m1) & ~pagesize_m1;
+ if (guardsize < attr->guardsize || size + guardsize < guardsize)
+ /* Arithmetic overflow. */
+ return EINVAL;
+ size += guardsize;
if (__builtin_expect (size < ((guardsize + __static_tls_size
+ MINIMAL_REST_STACK + pagesize_m1)
& ~pagesize_m1),
diff --git a/nptl/descr.h b/nptl/descr.h
index c83b17b674b..82dab056e2a 100644
--- a/nptl/descr.h
+++ b/nptl/descr.h
@@ -380,9 +380,9 @@ struct pthread
/* Machine-specific unwind info. */
struct _Unwind_Exception exc;
- /* If nonzero pointer to area allocated for the stack and its
- size. */
+ /* If nonzero, pointer to the area allocated for the stack and guard. */
void *stackblock;
+ /* Size of the stackblock area including the guard. */
size_t stackblock_size;
/* Size of the included guard area. */
size_t guardsize;
diff --git a/nptl/nptl-init.c b/nptl/nptl-init.c
index 869e926f17a..e5c0bdfbebb 100644
--- a/nptl/nptl-init.c
+++ b/nptl/nptl-init.c
@@ -473,8 +473,5 @@ strong_alias (__pthread_initialize_minimal_internal,
size_t
__pthread_get_minstack (const pthread_attr_t *attr)
{
- struct pthread_attr *iattr = (struct pthread_attr *) attr;
-
- return (GLRO(dl_pagesize) + __static_tls_size + PTHREAD_STACK_MIN
- + iattr->guardsize);
+ return GLRO(dl_pagesize) + __static_tls_size + PTHREAD_STACK_MIN;
}
diff --git a/nptl/pthread_create.c b/nptl/pthread_create.c
index 16c05c3a58c..791587218b6 100644
--- a/nptl/pthread_create.c
+++ b/nptl/pthread_create.c
@@ -551,31 +551,8 @@ START_THREAD_DEFN
}
#endif
- /* Mark the memory of the stack as usable to the kernel. We free
- everything except for the space used for the TCB itself. */
- size_t pagesize_m1 = __getpagesize () - 1;
-#ifdef _STACK_GROWS_DOWN
- char *sp = CURRENT_STACK_FRAME;
- size_t freesize = (sp - (char *) pd->stackblock) & ~pagesize_m1;
- assert (freesize < pd->stackblock_size);
- if (freesize > PTHREAD_STACK_MIN)
- __madvise (pd->stackblock, freesize - PTHREAD_STACK_MIN, MADV_DONTNEED);
-#else
- /* Page aligned start of memory to free (higher than or equal
- to current sp plus the minimum stack size). */
- void *freeblock = (void*)((size_t)(CURRENT_STACK_FRAME
- + PTHREAD_STACK_MIN
- + pagesize_m1)
- & ~pagesize_m1);
- char *free_end = (char *) (((uintptr_t) pd - pd->guardsize) & ~pagesize_m1);
- /* Is there any space to free? */
- if (free_end > (char *)freeblock)
- {
- size_t freesize = (size_t)(free_end - (char *)freeblock);
- assert (freesize < pd->stackblock_size);
- __madvise (freeblock, freesize, MADV_DONTNEED);
- }
-#endif
+ advise_stack_range (pd->stackblock, pd->stackblock_size, (uintptr_t) pd,
+ pd->guardsize);
/* If the thread is detached free the TCB. */
if (IS_DETACHED (pd))
diff --git a/nptl/pthread_getattr_np.c b/nptl/pthread_getattr_np.c
index 06093b3d927..210a3f8a1fa 100644
--- a/nptl/pthread_getattr_np.c
+++ b/nptl/pthread_getattr_np.c
@@ -57,9 +57,12 @@ pthread_getattr_np (pthread_t thread_id, pthread_attr_t *attr)
/* The sizes are subject to alignment. */
if (__glibc_likely (thread->stackblock != NULL))
{
- iattr->stacksize = thread->stackblock_size;
+ /* The stack size reported to the user should not include the
+ guard size. */
+ iattr->stacksize = thread->stackblock_size - thread->guardsize;
#if _STACK_GROWS_DOWN
- iattr->stackaddr = (char *) thread->stackblock + iattr->stacksize;
+ iattr->stackaddr = (char *) thread->stackblock
+ + thread->stackblock_size;
#else
iattr->stackaddr = (char *) thread->stackblock;
#endif
diff --git a/nptl/tst-minstack-cancel.c b/nptl/tst-minstack-cancel.c
new file mode 100644
index 00000000000..a306320e88d
--- /dev/null
+++ b/nptl/tst-minstack-cancel.c
@@ -0,0 +1,48 @@
+/* Test cancellation with a minimal stack size.
+ Copyright (C) 2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+/* Note: This test is similar to tst-minstack-exit, but is separate to
+ avoid spurious test passes due to warm-up effects. */
+
+#include <limits.h>
+#include <unistd.h>
+#include <support/check.h>
+#include <support/xthread.h>
+
+static void *
+threadfunc (void *closure)
+{
+ while (1)
+ pause ();
+ return NULL;
+}
+
+static int
+do_test (void)
+{
+ pthread_attr_t attr;
+ xpthread_attr_init (&attr);
+ xpthread_attr_setstacksize (&attr, PTHREAD_STACK_MIN);
+ pthread_t thr = xpthread_create (&attr, threadfunc, NULL);
+ xpthread_cancel (thr);
+ TEST_VERIFY (xpthread_join (thr) == PTHREAD_CANCELED);
+ xpthread_attr_destroy (&attr);
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/nptl/tst-minstack-exit.c b/nptl/tst-minstack-exit.c
new file mode 100644
index 00000000000..9c7e9a4dfea
--- /dev/null
+++ b/nptl/tst-minstack-exit.c
@@ -0,0 +1,46 @@
+/* Test that pthread_exit works with the minimum stack size.
+ Copyright (C) 2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+/* Note: This test is similar to tst-minstack-cancel, but is separate
+ to avoid spurious test passes due to warm-up effects. */
+
+#include <limits.h>
+#include <unistd.h>
+#include <support/check.h>
+#include <support/xthread.h>
+
+static void *
+threadfunc (void *closure)
+{
+ pthread_exit (threadfunc);
+ return NULL;
+}
+
+static int
+do_test (void)
+{
+ pthread_attr_t attr;
+ xpthread_attr_init (&attr);
+ xpthread_attr_setstacksize (&attr, PTHREAD_STACK_MIN);
+ pthread_t thr = xpthread_create (&attr, threadfunc, NULL);
+ TEST_VERIFY (xpthread_join (thr) == threadfunc);
+ xpthread_attr_destroy (&attr);
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/nptl/tst-minstack-throw.cc b/nptl/tst-minstack-throw.cc
new file mode 100644
index 00000000000..b0a897b0c6e
--- /dev/null
+++ b/nptl/tst-minstack-throw.cc
@@ -0,0 +1,87 @@
+/* Test that throwing C++ exceptions works with the minimum stack size.
+ Copyright (C) 2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <stdexcept>
+
+#include <limits.h>
+#include <string.h>
+#include <support/check.h>
+#include <support/xthread.h>
+
+/* Throw a std::runtime_exception. */
+__attribute__ ((noinline, noclone, weak))
+void
+do_throw_exception ()
+{
+ throw std::runtime_error ("test exception");
+}
+
+/* Class with a destructor, to trigger unwind handling. */
+struct class_with_destructor
+{
+ class_with_destructor ();
+ ~class_with_destructor ();
+};
+
+__attribute__ ((noinline, noclone, weak))
+class_with_destructor::class_with_destructor ()
+{
+}
+
+__attribute__ ((noinline, noclone, weak))
+class_with_destructor::~class_with_destructor ()
+{
+}
+
+__attribute__ ((noinline, noclone, weak))
+void
+function_with_destructed_object ()
+{
+ class_with_destructor obj;
+ do_throw_exception ();
+}
+
+static void *
+threadfunc (void *closure)
+{
+ try
+ {
+ function_with_destructed_object ();
+ FAIL_EXIT1 ("no exception thrown");
+ }
+ catch (std::exception &e)
+ {
+ TEST_COMPARE (strcmp (e.what (), "test exception"), 0);
+ return reinterpret_cast<void *> (threadfunc);
+ }
+ FAIL_EXIT1 ("no exception caught");
+}
+
+static int
+do_test (void)
+{
+ pthread_attr_t attr;
+ xpthread_attr_init (&attr);
+ xpthread_attr_setstacksize (&attr, PTHREAD_STACK_MIN);
+ pthread_t thr = xpthread_create (&attr, threadfunc, NULL);
+ TEST_VERIFY (xpthread_join (thr) == threadfunc);
+ xpthread_attr_destroy (&attr);
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/nptl/tst-thread-exit-clobber.cc b/nptl/tst-thread-exit-clobber.cc
new file mode 100644
index 00000000000..b9be25a65b8
--- /dev/null
+++ b/nptl/tst-thread-exit-clobber.cc
@@ -0,0 +1,243 @@
+/* Test that pthread_exit does not clobber callee-saved registers.
+ 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/check.h>
+#include <support/xthread.h>
+
+/* This test attempts to check that callee-saved registers are
+ restored to their original values when destructors are run after
+ pthread_exit is called. GCC PR 83641 causes this test to fail.
+
+ The constants have been chosen randomly and are magic values which
+ are used to detect whether registers have been clobbered. The idea
+ is that these values are hidden behind a compiler barrier and only
+ present in .rodata initially, so that it is less likely that they
+ are in a register by accident.
+
+ The checker class can be stored in registers, and the magic values
+ are directly loaded into these registers. The checker destructor
+ is eventually invoked by pthread_exit and calls one of the
+ check_magic functions to verify that the class contents (that is,
+ register value) is correct.
+
+ These tests are performed both for unsigned int and double values,
+ to cover different calling conventions. */
+
+template <class T>
+struct values
+{
+ T v0;
+ T v1;
+ T v2;
+ T v3;
+ T v4;
+};
+
+static const values<unsigned int> magic_values =
+ {
+ 0x57f7fc72,
+ 0xe582daba,
+ 0x5f6ac994,
+ 0x35efddb7,
+ 0x1fbf5a74,
+ };
+
+static const values<double> magic_values_double =
+ {
+ 0.6764041905675465,
+ 0.9533336788140494,
+ 0.6091161359041452,
+ 0.7668653957125336,
+ 0.010374520235509666,
+ };
+
+/* Special index value which tells check_magic that no check should be
+ performed. */
+enum { no_check = -1 };
+
+/* Check that VALUE is the magic value for INDEX, behind a compiler
+ barrier. */
+__attribute__ ((noinline, noclone, weak))
+void
+check_magic (int index, unsigned int value)
+{
+ switch (index)
+ {
+ case 0:
+ TEST_COMPARE (value, magic_values.v0);
+ break;
+ case 1:
+ TEST_COMPARE (value, magic_values.v1);
+ break;
+ case 2:
+ TEST_COMPARE (value, magic_values.v2);
+ break;
+ case 3:
+ TEST_COMPARE (value, magic_values.v3);
+ break;
+ case 4:
+ TEST_COMPARE (value, magic_values.v4);
+ break;
+ case no_check:
+ break;
+ default:
+ FAIL_EXIT1 ("invalid magic value index %d", index);
+ }
+}
+
+/* Check that VALUE is the magic value for INDEX, behind a compiler
+ barrier. Double variant. */
+__attribute__ ((noinline, noclone, weak))
+void
+check_magic (int index, double value)
+{
+ switch (index)
+ {
+ case 0:
+ TEST_VERIFY (value == magic_values_double.v0);
+ break;
+ case 1:
+ TEST_VERIFY (value == magic_values_double.v1);
+ break;
+ case 2:
+ TEST_VERIFY (value == magic_values_double.v2);
+ break;
+ case 3:
+ TEST_VERIFY (value == magic_values_double.v3);
+ break;
+ case 4:
+ TEST_VERIFY (value == magic_values_double.v4);
+ break;
+ case no_check:
+ break;
+ default:
+ FAIL_EXIT1 ("invalid magic value index %d", index);
+ }
+}
+
+/* Store a magic value and check, via the destructor, that it has the
+ expected value. */
+template <class T, int I>
+struct checker
+{
+ T value;
+
+ checker (T v)
+ : value (v)
+ {
+ }
+
+ ~checker ()
+ {
+ check_magic (I, value);
+ }
+};
+
+/* The functions call_pthread_exit_0, call_pthread_exit_1,
+ call_pthread_exit are used to call pthread_exit indirectly, with
+ the intent of clobbering the register values. */
+
+__attribute__ ((noinline, noclone, weak))
+void
+call_pthread_exit_0 (const values<unsigned int> *pvalues)
+{
+ checker<unsigned int, no_check> c0 (pvalues->v0);
+ checker<unsigned int, no_check> c1 (pvalues->v1);
+ checker<unsigned int, no_check> c2 (pvalues->v2);
+ checker<unsigned int, no_check> c3 (pvalues->v3);
+ checker<unsigned int, no_check> c4 (pvalues->v4);
+
+ pthread_exit (NULL);
+}
+
+__attribute__ ((noinline, noclone, weak))
+void
+call_pthread_exit_1 (const values<double> *pvalues)
+{
+ checker<double, no_check> c0 (pvalues->v0);
+ checker<double, no_check> c1 (pvalues->v1);
+ checker<double, no_check> c2 (pvalues->v2);
+ checker<double, no_check> c3 (pvalues->v3);
+ checker<double, no_check> c4 (pvalues->v4);
+
+ values<unsigned int> other_values = { 0, };
+ call_pthread_exit_0 (&other_values);
+}
+
+__attribute__ ((noinline, noclone, weak))
+void
+call_pthread_exit ()
+{
+ values<double> other_values = { 0, };
+ call_pthread_exit_1 (&other_values);
+}
+
+/* Create on-stack objects and check that their values are restored by
+ pthread_exit. If Nested is true, call pthread_exit indirectly via
+ call_pthread_exit. */
+template <class T, bool Nested>
+__attribute__ ((noinline, noclone, weak))
+void *
+threadfunc (void *closure)
+{
+ const values<T> *pvalues = static_cast<const values<T> *> (closure);
+
+ checker<T, 0> c0 (pvalues->v0);
+ checker<T, 1> c1 (pvalues->v1);
+ checker<T, 2> c2 (pvalues->v2);
+ checker<T, 3> c3 (pvalues->v3);
+ checker<T, 4> c4 (pvalues->v4);
+
+ if (Nested)
+ call_pthread_exit ();
+ else
+ pthread_exit (NULL);
+
+ /* This should not be reached. */
+ return const_cast<char *> ("");
+}
+
+static int
+do_test ()
+{
+ puts ("info: unsigned int, direct pthread_exit call");
+ pthread_t thr
+ = xpthread_create (NULL, &threadfunc<unsigned int, false>,
+ const_cast<values<unsigned int> *> (&magic_values));
+ TEST_VERIFY (xpthread_join (thr) == NULL);
+
+ puts ("info: double, direct pthread_exit call");
+ thr = xpthread_create (NULL, &threadfunc<double, false>,
+ const_cast<values<double> *> (&magic_values_double));
+ TEST_VERIFY (xpthread_join (thr) == NULL);
+
+ puts ("info: unsigned int, indirect pthread_exit call");
+ thr = xpthread_create (NULL, &threadfunc<unsigned int, true>,
+ const_cast<values<unsigned int> *> (&magic_values));
+ TEST_VERIFY (xpthread_join (thr) == NULL);
+
+ puts ("info: double, indirect pthread_exit call");
+ thr = xpthread_create (NULL, &threadfunc<double, true>,
+ const_cast<values<double> *> (&magic_values_double));
+ TEST_VERIFY (xpthread_join (thr) == NULL);
+
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/posix/glob.c b/posix/glob.c
index c761c0861dd..b2273ea7bce 100644
--- a/posix/glob.c
+++ b/posix/glob.c
@@ -850,11 +850,11 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
char *p = mempcpy (newp, dirname + 1,
unescape - dirname - 1);
char *q = unescape;
- while (*q != '\0')
+ while (q != end_name)
{
if (*q == '\\')
{
- if (q[1] == '\0')
+ if (q + 1 == end_name)
{
/* "~fo\\o\\" unescape to user_name "foo\\",
but "~fo\\o\\/" unescape to user_name
diff --git a/posix/tst-glob-tilde.c b/posix/tst-glob-tilde.c
index 9518b4a6f85..6886f4371fc 100644
--- a/posix/tst-glob-tilde.c
+++ b/posix/tst-glob-tilde.c
@@ -1,4 +1,4 @@
-/* Check for GLOB_TIDLE heap allocation issues (bug 22320, bug 22325).
+/* Check for GLOB_TIDLE heap allocation issues (bugs 22320, 22325, 22332).
Copyright (C) 2017 Free Software Foundation, Inc.
This file is part of the GNU C Library.
@@ -34,6 +34,9 @@ static int do_nocheck;
/* Flag which indicates whether to pass the GLOB_MARK flag. */
static int do_mark;
+/* Flag which indicates whether to pass the GLOB_NOESCAPE flag. */
+static int do_noescape;
+
static void
one_test (const char *prefix, const char *middle, const char *suffix)
{
@@ -45,6 +48,8 @@ one_test (const char *prefix, const char *middle, const char *suffix)
flags |= GLOB_NOCHECK;
if (do_mark)
flags |= GLOB_MARK;
+ if (do_noescape)
+ flags |= GLOB_NOESCAPE;
glob_t gl;
/* This glob call might result in crashes or memory leaks. */
if (glob (pattern, flags, NULL, &gl) == 0)
@@ -105,28 +110,30 @@ do_test (void)
for (do_onlydir = 0; do_onlydir < 2; ++do_onlydir)
for (do_nocheck = 0; do_nocheck < 2; ++do_nocheck)
for (do_mark = 0; do_mark < 2; ++do_mark)
- for (int base_idx = 0; base_sizes[base_idx] >= 0; ++base_idx)
- {
- for (int size_skew = -max_size_skew; size_skew <= max_size_skew;
- ++size_skew)
- {
- int size = base_sizes[base_idx] + size_skew;
- if (size < 0)
- continue;
-
- const char *user_name = repeating_string (size);
- one_test ("~", user_name, "/a/b");
- }
-
- const char *user_name = repeating_string (base_sizes[base_idx]);
- one_test ("~", user_name, "");
- one_test ("~", user_name, "/");
- one_test ("~", user_name, "/a");
- one_test ("~", user_name, "/*/*");
- one_test ("~", user_name, "\\/");
- one_test ("/~", user_name, "");
- one_test ("*/~", user_name, "/a/b");
- }
+ for (do_noescape = 0; do_noescape < 2; ++do_noescape)
+ for (int base_idx = 0; base_sizes[base_idx] >= 0; ++base_idx)
+ {
+ for (int size_skew = -max_size_skew; size_skew <= max_size_skew;
+ ++size_skew)
+ {
+ int size = base_sizes[base_idx] + size_skew;
+ if (size < 0)
+ continue;
+
+ const char *user_name = repeating_string (size);
+ one_test ("~", user_name, "/a/b");
+ one_test ("~", user_name, "x\\x\\x////x\\a");
+ }
+
+ const char *user_name = repeating_string (base_sizes[base_idx]);
+ one_test ("~", user_name, "");
+ one_test ("~", user_name, "/");
+ one_test ("~", user_name, "/a");
+ one_test ("~", user_name, "/*/*");
+ one_test ("~", user_name, "\\/");
+ one_test ("/~", user_name, "");
+ one_test ("*/~", user_name, "/a/b");
+ }
free (repeat);
diff --git a/scripts/backport-support.sh b/scripts/backport-support.sh
index 2ece7ce575e..4057e42d3c7 100644
--- a/scripts/backport-support.sh
+++ b/scripts/backport-support.sh
@@ -1,6 +1,6 @@
#!/bin/bash
# Create a patch which backports the support/ subdirectory.
-# Copyright (C) 2017 Free Software Foundation, Inc.
+# Copyright (C) 2017-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
diff --git a/support/Makefile b/support/Makefile
index 2ace3fa8cc5..1bda81e55e5 100644
--- a/support/Makefile
+++ b/support/Makefile
@@ -1,5 +1,5 @@
# Makefile for support library, used only at build and test time
-# Copyright (C) 2016-2017 Free Software Foundation, Inc.
+# Copyright (C) 2016-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
@@ -32,15 +32,18 @@ libsupport-routines = \
check_netent \
delayed_exit \
ignore_stderr \
+ next_to_fault \
oom_error \
resolv_test \
set_fortify_handler \
+ support-xfstat \
support-xstat \
support_become_root \
support_can_chroot \
support_capture_subprocess \
support_capture_subprocess_check \
support_chroot \
+ support_enter_mount_namespace \
support_enter_network_namespace \
support_format_address_family \
support_format_addrinfo \
@@ -52,6 +55,7 @@ libsupport-routines = \
support_record_failure \
support_run_diff \
support_shared_allocate \
+ support_test_compare_failure \
support_write_file_string \
support_test_main \
support_test_verify_impl \
@@ -65,12 +69,15 @@ libsupport-routines = \
xchroot \
xclose \
xconnect \
+ xdlfcn \
xdup2 \
xfclose \
xfopen \
xfork \
+ xftruncate \
xgetsockname \
xlisten \
+ xlseek \
xmalloc \
xmemstream \
xmkdir \
@@ -83,8 +90,8 @@ libsupport-routines = \
xpthread_attr_destroy \
xpthread_attr_init \
xpthread_attr_setdetachstate \
- xpthread_attr_setstacksize \
xpthread_attr_setguardsize \
+ xpthread_attr_setstacksize \
xpthread_barrier_destroy \
xpthread_barrier_init \
xpthread_barrier_wait \
@@ -108,19 +115,26 @@ libsupport-routines = \
xpthread_once \
xpthread_rwlock_init \
xpthread_rwlock_rdlock \
- xpthread_rwlock_wrlock \
xpthread_rwlock_unlock \
+ xpthread_rwlock_wrlock \
xpthread_rwlockattr_init \
xpthread_rwlockattr_setkind_np \
xpthread_sigmask \
xpthread_spin_lock \
xpthread_spin_unlock \
+ xraise \
+ xreadlink \
xrealloc \
xrecvfrom \
xsendto \
xsetsockopt \
+ xsigaction \
+ xsignal \
xsocket \
xstrdup \
+ xstrndup \
+ xsysconf \
+ xunlink \
xwaitpid \
xwrite \
@@ -137,6 +151,8 @@ tests = \
tst-support_capture_subprocess \
tst-support_format_dns_packet \
tst-support_record_failure \
+ tst-test_compare \
+ tst-xreadlink \
ifeq ($(run-built-tests),yes)
tests-special = \
diff --git a/support/capture_subprocess.h b/support/capture_subprocess.h
index 43caf9bce46..b0886ba1d16 100644
--- a/support/capture_subprocess.h
+++ b/support/capture_subprocess.h
@@ -1,5 +1,5 @@
/* Capture output from a subprocess.
- Copyright (C) 2017 Free Software Foundation, Inc.
+ Copyright (C) 2017-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
diff --git a/support/check.c b/support/check.c
index 592f2bc856e..78f2b3cde14 100644
--- a/support/check.c
+++ b/support/check.c
@@ -1,5 +1,5 @@
/* Support code for reporting test results.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
@@ -18,6 +18,7 @@
#include <support/check.h>
+#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
@@ -26,9 +27,11 @@
static void
print_failure (const char *file, int line, const char *format, va_list ap)
{
+ int saved_errno = errno;
printf ("error: %s:%d: ", file, line);
vprintf (format, ap);
puts ("");
+ errno = saved_errno;
}
int
diff --git a/support/check.h b/support/check.h
index bdcd12952af..2192f38941a 100644
--- a/support/check.h
+++ b/support/check.h
@@ -1,5 +1,5 @@
/* Functionality for reporting test results.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
@@ -86,6 +86,61 @@ void support_test_verify_exit_impl (int status, const char *file, int line,
does not support reporting failures from a DSO. */
void support_record_failure (void);
+/* Static assertion, under a common name for both C++ and C11. */
+#ifdef __cplusplus
+# define support_static_assert static_assert
+#else
+# define support_static_assert _Static_assert
+#endif
+
+/* Compare the two integers LEFT and RIGHT and report failure if they
+ are different. */
+#define TEST_COMPARE(left, right) \
+ ({ \
+ /* + applies the integer promotions, for bitfield support. */ \
+ typedef __typeof__ (+ (left)) __left_type; \
+ typedef __typeof__ (+ (right)) __right_type; \
+ __left_type __left_value = (left); \
+ __right_type __right_value = (right); \
+ int __left_is_positive = __left_value > 0; \
+ int __right_is_positive = __right_value > 0; \
+ /* Prevent use with floating-point types. */ \
+ support_static_assert ((__left_type) 1.0 == (__left_type) 1.5, \
+ "left value has floating-point type"); \
+ support_static_assert ((__right_type) 1.0 == (__right_type) 1.5, \
+ "right value has floating-point type"); \
+ /* Prevent accidental use with larger-than-long long types. */ \
+ support_static_assert (sizeof (__left_value) <= sizeof (long long), \
+ "left value fits into long long"); \
+ support_static_assert (sizeof (__right_value) <= sizeof (long long), \
+ "right value fits into long long"); \
+ /* Compare the value. */ \
+ if (__left_value != __right_value \
+ || __left_is_positive != __right_is_positive) \
+ /* Pass the sign for printing the correct value. */ \
+ support_test_compare_failure \
+ (__FILE__, __LINE__, \
+ #left, __left_value, __left_is_positive, sizeof (__left_type), \
+ #right, __right_value, __right_is_positive, sizeof (__right_type)); \
+ })
+
+/* Internal implementation of TEST_COMPARE. LEFT_POSITIVE and
+ RIGHT_POSITIVE are used to store the sign separately, so that both
+ unsigned long long and long long arguments fit into LEFT_VALUE and
+ RIGHT_VALUE, and the function can still print the original value.
+ LEFT_SIZE and RIGHT_SIZE specify the size of the argument in bytes,
+ for hexadecimal formatting. */
+void support_test_compare_failure (const char *file, int line,
+ const char *left_expr,
+ long long left_value,
+ int left_positive,
+ int left_size,
+ const char *right_expr,
+ long long right_value,
+ int right_positive,
+ int right_size);
+
+
/* Internal function called by the test driver. */
int support_report_failure (int status)
__attribute__ ((weak, warn_unused_result));
diff --git a/support/check_addrinfo.c b/support/check_addrinfo.c
index 55895ace3c7..91ad7c56bda 100644
--- a/support/check_addrinfo.c
+++ b/support/check_addrinfo.c
@@ -1,5 +1,5 @@
/* Compare struct addrinfo values against a formatted string.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
@@ -20,6 +20,7 @@
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include <support/check.h>
#include <support/format_nss.h>
#include <support/run_diff.h>
diff --git a/support/check_dns_packet.c b/support/check_dns_packet.c
index d2a31bed7b4..6c1277bd670 100644
--- a/support/check_dns_packet.c
+++ b/support/check_dns_packet.c
@@ -1,5 +1,5 @@
/* Check that a DNS packet buffer has the expected contents.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
@@ -20,6 +20,7 @@
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include <support/check.h>
#include <support/format_nss.h>
#include <support/run_diff.h>
diff --git a/support/check_hostent.c b/support/check_hostent.c
index 890d672d501..56384f9b03c 100644
--- a/support/check_hostent.c
+++ b/support/check_hostent.c
@@ -1,5 +1,5 @@
/* Compare struct hostent values against a formatted string.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
@@ -20,6 +20,7 @@
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include <support/check.h>
#include <support/format_nss.h>
#include <support/run_diff.h>
diff --git a/support/check_netent.c b/support/check_netent.c
index daa3083fd10..cbcbfb14e52 100644
--- a/support/check_netent.c
+++ b/support/check_netent.c
@@ -1,5 +1,5 @@
/* Compare struct netent values against a formatted string.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
@@ -20,6 +20,7 @@
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include <support/check.h>
#include <support/format_nss.h>
#include <support/run_diff.h>
diff --git a/support/check_nss.h b/support/check_nss.h
index 2893f2c2957..6aa28fa24e9 100644
--- a/support/check_nss.h
+++ b/support/check_nss.h
@@ -1,5 +1,5 @@
/* Test verification functions for NSS- and DNS-related data.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
diff --git a/support/delayed_exit.c b/support/delayed_exit.c
index 67442f95df3..2780d9a6fe6 100644
--- a/support/delayed_exit.c
+++ b/support/delayed_exit.c
@@ -1,5 +1,5 @@
/* Time-triggered process termination.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
diff --git a/support/format_nss.h b/support/format_nss.h
index fb4597c2384..e55354e7883 100644
--- a/support/format_nss.h
+++ b/support/format_nss.h
@@ -1,5 +1,5 @@
/* String formatting functions for NSS- and DNS-related data.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
diff --git a/support/ignore_stderr.c b/support/ignore_stderr.c
index 7b77a2cd568..450333ad38a 100644
--- a/support/ignore_stderr.c
+++ b/support/ignore_stderr.c
@@ -1,5 +1,5 @@
/* Avoid all the buffer overflow messages on stderr.
- Copyright (C) 2015-2017 Free Software Foundation, Inc.
+ Copyright (C) 2015-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
diff --git a/support/namespace.h b/support/namespace.h
index 9eddb1a0e90..3c3842a49bb 100644
--- a/support/namespace.h
+++ b/support/namespace.h
@@ -1,5 +1,5 @@
/* Entering namespaces for test case isolation.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
@@ -51,6 +51,11 @@ bool support_can_chroot (void);
has sufficient privileges. */
bool support_enter_network_namespace (void);
+/* Enter a mount namespace and mark / as private (not shared). If
+ this function returns true, mount operations in this process will
+ not affect the host system afterwards. */
+bool support_enter_mount_namespace (void);
+
/* Return true if support_enter_network_namespace managed to enter a
UTS namespace. */
bool support_in_uts_namespace (void);
diff --git a/support/next_to_fault.c b/support/next_to_fault.c
new file mode 100644
index 00000000000..1971bf7cd7d
--- /dev/null
+++ b/support/next_to_fault.c
@@ -0,0 +1,52 @@
+/* Memory allocation next to an unmapped page.
+ Copyright (C) 2017-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/next_to_fault.h>
+#include <support/xunistd.h>
+#include <sys/mman.h>
+#include <sys/param.h>
+
+struct support_next_to_fault
+support_next_to_fault_allocate (size_t size)
+{
+ long page_size = sysconf (_SC_PAGE_SIZE);
+ TEST_VERIFY_EXIT (page_size > 0);
+ struct support_next_to_fault result;
+ result.region_size = roundup (size, page_size) + page_size;
+ if (size + page_size <= size || result.region_size <= size)
+ FAIL_EXIT1 ("support_next_to_fault_allocate (%zu): overflow", size);
+ result.region_start
+ = xmmap (NULL, result.region_size, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1);
+ /* Unmap the page after the allocation. */
+ xmprotect (result.region_start + (result.region_size - page_size),
+ page_size, PROT_NONE);
+ /* Align the allocation within the region so that it ends just
+ before the PROT_NONE page. */
+ result.buffer = result.region_start + result.region_size - page_size - size;
+ result.length = size;
+ return result;
+}
+
+void
+support_next_to_fault_free (struct support_next_to_fault *ntf)
+{
+ xmunmap (ntf->region_start, ntf->region_size);
+ *ntf = (struct support_next_to_fault) { NULL, };
+}
diff --git a/support/next_to_fault.h b/support/next_to_fault.h
new file mode 100644
index 00000000000..75759b586c5
--- /dev/null
+++ b/support/next_to_fault.h
@@ -0,0 +1,48 @@
+/* Memory allocation next to an unmapped page.
+ Copyright (C) 2017-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_NEXT_TO_FAULT_H
+#define SUPPORT_NEXT_TO_FAULT_H
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+__BEGIN_DECLS
+
+/* The memory region created by next_to_fault_allocate. */
+struct support_next_to_fault
+{
+ /* The user data. */
+ char *buffer;
+ size_t length;
+
+ /* The entire allocated region. */
+ void *region_start;
+ size_t region_size;
+};
+
+/* Allocate a buffer of SIZE bytes just before a page which is mapped
+ with PROT_NONE (so that overrunning the buffer will cause a
+ fault). */
+struct support_next_to_fault support_next_to_fault_allocate (size_t size);
+
+/* Deallocate the memory region allocated by
+ next_to_fault_allocate. */
+void support_next_to_fault_free (struct support_next_to_fault *);
+
+#endif /* SUPPORT_NEXT_TO_FAULT_H */
diff --git a/support/oom_error.c b/support/oom_error.c
index 78169782736..fd87fe23059 100644
--- a/support/oom_error.c
+++ b/support/oom_error.c
@@ -1,5 +1,5 @@
/* Reporting out-of-memory errors.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
diff --git a/support/resolv_test.c b/support/resolv_test.c
index 1625dcf43a2..3f2a09f36f4 100644
--- a/support/resolv_test.c
+++ b/support/resolv_test.c
@@ -1,5 +1,5 @@
/* DNS test framework and libresolv redirection.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
@@ -43,15 +43,99 @@ enum
max_response_length = 65536
};
-/* List of pointers to be freed. The hash table implementation
- (struct hsearch_data) does not provide a way to deallocate all
- objects, so this approach is used to avoid memory leaks. */
-struct to_be_freed
+/* Used for locating domain names containing for the purpose of
+ forming compression references. */
+struct compressed_name
{
- struct to_be_freed *next;
- void *ptr;
+ uint16_t offset;
+ unsigned char length;
+ unsigned char name[]; /* Without terminating NUL. */
};
+static struct compressed_name *
+allocate_compressed_name (const unsigned char *encoded, unsigned int offset)
+{
+ /* Compute the length of the domain name. */
+ size_t length;
+ {
+ const unsigned char *p;
+ for (p = encoded; *p != '\0';)
+ {
+ /* No compression references are allowed. */
+ TEST_VERIFY (*p <= 63);
+ /* Skip over the label. */
+ p += 1 + *p;
+ }
+ length = p - encoded;
+ ++length; /* For the terminating NUL byte. */
+ }
+ TEST_VERIFY_EXIT (length <= 255);
+
+ struct compressed_name *result
+ = xmalloc (offsetof (struct compressed_name, name) + length);
+ result->offset = offset;
+ result->length = length;
+ memcpy (result->name, encoded, length);
+ return result;
+}
+
+/* Convert CH to lower case. Only change letters in the ASCII
+ range. */
+static inline unsigned char
+ascii_tolower (unsigned char ch)
+{
+ if ('A' <= ch && ch <= 'Z')
+ return ch - 'A' + 'a';
+ else
+ return ch;
+}
+
+/* Compare both names, for use with tsearch. The order is arbitrary,
+ but the comparison is case-insenstive. */
+static int
+compare_compressed_name (const void *left, const void *right)
+{
+ const struct compressed_name *crleft = left;
+ const struct compressed_name *crright = right;
+
+ if (crleft->length != crright->length)
+ /* The operands are converted to int before the subtraction. */
+ return crleft->length - crright->length;
+
+ const unsigned char *nameleft = crleft->name;
+ const unsigned char *nameright = crright->name;
+
+ while (true)
+ {
+ int lenleft = *nameleft++;
+ int lenright = *nameright++;
+
+ /* Labels must not e compression references. */
+ TEST_VERIFY (lenleft <= 63);
+ TEST_VERIFY (lenright <= 63);
+
+ if (lenleft != lenright)
+ return left - right;
+ if (lenleft == 0)
+ /* End of name reached without spotting a difference. */
+ return 0;
+ /* Compare the label in a case-insenstive manner. */
+ const unsigned char *endnameleft = nameleft + lenleft;
+ while (nameleft < endnameleft)
+ {
+ int l = *nameleft++;
+ int r = *nameright++;
+ if (l != r)
+ {
+ l = ascii_tolower (l);
+ r = ascii_tolower (r);
+ if (l != r)
+ return l - r;
+ }
+ }
+ }
+}
+
struct resolv_response_builder
{
const unsigned char *query_buffer;
@@ -67,11 +151,8 @@ struct resolv_response_builder
written RDATA sub-structure. 0 if no RDATA is being written. */
size_t current_rdata_offset;
- /* Hash table for locating targets for label compression. */
- struct hsearch_data compression_offsets;
- /* List of pointers which need to be freed. Used for domain names
- involved in label compression. */
- struct to_be_freed *to_be_freed;
+ /* tsearch tree for locating targets for label compression. */
+ void *compression_offsets;
/* Must be last. Not zeroed for performance reasons. */
unsigned char buffer[max_response_length];
@@ -79,18 +160,6 @@ struct resolv_response_builder
/* Response builder. */
-/* Add a pointer to the list of pointers to be freed when B is
- deallocated. */
-static void
-response_push_pointer_to_free (struct resolv_response_builder *b, void *ptr)
-{
- if (ptr == NULL)
- return;
- struct to_be_freed *e = xmalloc (sizeof (*e));
- *e = (struct to_be_freed) {b->to_be_freed, ptr};
- b->to_be_freed = e;
-}
-
void
resolv_response_init (struct resolv_response_builder *b,
struct resolv_response_flags flags)
@@ -194,120 +263,88 @@ void
resolv_response_add_name (struct resolv_response_builder *b,
const char *const origname)
{
- /* Normalized name. */
- char *name;
- /* Normalized name with case preserved. */
- char *name_case;
- {
- size_t namelen = strlen (origname);
- /* Remove trailing dots. FIXME: Handle trailing quoted dots. */
- while (namelen > 0 && origname[namelen - 1] == '.')
- --namelen;
- name = xmalloc (namelen + 1);
- name_case = xmalloc (namelen + 1);
- /* Copy and convert to lowercase. FIXME: This needs to normalize
- escaping as well. */
- for (size_t i = 0; i < namelen; ++i)
- {
- char ch = origname[i];
- name_case[i] = ch;
- if ('A' <= ch && ch <= 'Z')
- ch = ch - 'A' + 'a';
- name[i] = ch;
- }
- name[namelen] = 0;
- name_case[namelen] = 0;
- }
- char *name_start = name;
- char *name_case_start = name_case;
+ unsigned char encoded_name[NS_MAXDNAME];
+ if (ns_name_pton (origname, encoded_name, sizeof (encoded_name)) < 0)
+ FAIL_EXIT1 ("ns_name_pton (\"%s\"): %m", origname);
- bool compression = false;
- while (*name)
+ /* Copy the encoded name into the output buffer, apply compression
+ where possible. */
+ for (const unsigned char *name = encoded_name; ;)
{
- /* Search for a previous name we can reference. */
- ENTRY new_entry =
+ if (*name == '\0')
{
- .key = name,
- .data = (void *) (uintptr_t) b->offset,
- };
+ /* We have reached the end of the name. Add the terminating
+ NUL byte. */
+ response_add_byte (b, '\0');
+ break;
+ }
- /* If the label can be a compression target because it is at a
- reachable offset, add it to the hash table. */
- ACTION action;
- if (b->offset < (1 << 12))
- action = ENTER;
- else
- action = FIND;
+ /* Set to the compression target if compression is possible. */
+ struct compressed_name *crname_target;
- /* Search for known compression offsets in the hash table. */
- ENTRY *e;
- if (hsearch_r (new_entry, action, &e, &b->compression_offsets) == 0)
- {
- if (action == FIND && errno == ESRCH)
- /* Fall through. */
- e = NULL;
- else
- FAIL_EXIT1 ("hsearch_r failure in name compression: %m");
- }
+ /* Compression references can only reach the beginning of the
+ packet. */
+ enum { compression_limit = 1 << 12 };
+
+ {
+ /* The trailing part of the name to be looked up in the tree
+ with the compression targets. */
+ struct compressed_name *crname
+ = allocate_compressed_name (name, b->offset);
+
+ if (b->offset < compression_limit)
+ {
+ /* Add the name to the tree, for future compression
+ references. */
+ void **ptr = tsearch (crname, &b->compression_offsets,
+ compare_compressed_name);
+ if (ptr == NULL)
+ FAIL_EXIT1 ("tsearch out of memory");
+ crname_target = *ptr;
+
+ if (crname_target != crname)
+ /* The new name was not actually added to the tree.
+ Deallocate it. */
+ free (crname);
+ else
+ /* Signal that the tree did not yet contain the name,
+ but keep the allocation because it is now part of the
+ tree. */
+ crname_target = NULL;
+ }
+ else
+ {
+ /* This name cannot be reached by a compression reference.
+ No need to add it to the tree for future reference. */
+ void **ptr = tfind (crname, &b->compression_offsets,
+ compare_compressed_name);
+ if (ptr != NULL)
+ crname_target = *ptr;
+ else
+ crname_target = NULL;
+ TEST_VERIFY (crname_target != crname);
+ /* Not added to the tree. */
+ free (crname);
+ }
+ }
- /* The name is known. Reference the previous location. */
- if (e != NULL && e->data != new_entry.data)
+ if (crname_target != NULL)
{
- size_t old_offset = (uintptr_t) e->data;
+ /* The name is known. Reference the previous location. */
+ unsigned int old_offset = crname_target->offset;
+ TEST_VERIFY_EXIT (old_offset < compression_limit);
response_add_byte (b, 0xC0 | (old_offset >> 8));
response_add_byte (b, old_offset);
- compression = true;
break;
}
-
- /* The name does not exist yet. Write one label. First, add
- room for the label length. */
- size_t buffer_label_offset = b->offset;
- response_add_byte (b, 0);
-
- /* Copy the label. */
- while (true)
+ else
{
- char ch = *name_case;
- if (ch == '\0')
- break;
- ++name;
- ++name_case;
- if (ch == '.')
- break;
- /* FIXME: Handle escaping. */
- response_add_byte (b, ch);
+ /* The name is new. Add this label. */
+ unsigned int len = 1 + *name;
+ resolv_response_add_data (b, name, len);
+ name += len;
}
-
- /* Patch in the label length. */
- size_t label_length = b->offset - buffer_label_offset - 1;
- if (label_length == 0)
- FAIL_EXIT1 ("empty label in name compression: %s", origname);
- if (label_length > 63)
- FAIL_EXIT1 ("label too long in name compression: %s", origname);
- b->buffer[buffer_label_offset] = label_length;
-
- /* Continue with the tail of the name and the next label. */
- }
-
- if (compression)
- {
- /* If we found an immediate match for the name, we have not put
- it into the hash table, and can free it immediately. */
- if (name == name_start)
- free (name_start);
- else
- response_push_pointer_to_free (b, name_start);
- }
- else
- {
- /* Terminate the sequence of labels. With compression, this is
- implicit in the compression reference. */
- response_add_byte (b, 0);
- response_push_pointer_to_free (b, name_start);
}
-
- free (name_case_start);
}
void
@@ -403,22 +440,13 @@ response_builder_allocate
memset (b, 0, offsetof (struct resolv_response_builder, buffer));
b->query_buffer = query_buffer;
b->query_length = query_length;
- TEST_VERIFY_EXIT (hcreate_r (10000, &b->compression_offsets) != 0);
return b;
}
static void
response_builder_free (struct resolv_response_builder *b)
{
- struct to_be_freed *current = b->to_be_freed;
- while (current != NULL)
- {
- struct to_be_freed *next = current->next;
- free (current->ptr);
- free (current);
- current = next;
- }
- hdestroy_r (&b->compression_offsets);
+ tdestroy (b->compression_offsets, free);
free (b);
}
diff --git a/support/resolv_test.h b/support/resolv_test.h
index b953dc12000..4c2e6c1b417 100644
--- a/support/resolv_test.h
+++ b/support/resolv_test.h
@@ -1,5 +1,5 @@
/* DNS test framework and libresolv redirection.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
diff --git a/support/run_diff.h b/support/run_diff.h
index f65b5dd22cf..6e949226fa4 100644
--- a/support/run_diff.h
+++ b/support/run_diff.h
@@ -1,5 +1,5 @@
/* Invoke the system diff tool to compare two strings.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
diff --git a/support/set_fortify_handler.c b/support/set_fortify_handler.c
index f434a8082a2..c2dacbb179f 100644
--- a/support/set_fortify_handler.c
+++ b/support/set_fortify_handler.c
@@ -1,5 +1,5 @@
/* Set signal handler for use in fortify tests.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
diff --git a/support/support-xfstat.c b/support/support-xfstat.c
new file mode 100644
index 00000000000..f69253af099
--- /dev/null
+++ b/support/support-xfstat.c
@@ -0,0 +1,28 @@
+/* fstat64 with error checking.
+ Copyright (C) 2017-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/xunistd.h>
+#include <sys/stat.h>
+
+void
+xfstat (int fd, struct stat64 *result)
+{
+ if (fstat64 (fd, result) != 0)
+ FAIL_EXIT1 ("fstat64 (%d): %m", fd);
+}
diff --git a/support/support-xstat.c b/support/support-xstat.c
index 86a81ec6015..fc10c6dcb78 100644
--- a/support/support-xstat.c
+++ b/support/support-xstat.c
@@ -1,5 +1,5 @@
/* stat64 with error checking.
- Copyright (C) 2017 Free Software Foundation, Inc.
+ Copyright (C) 2017-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
diff --git a/support/support.h b/support/support.h
index 4b5f04c2ccc..bc5827ed87d 100644
--- a/support/support.h
+++ b/support/support.h
@@ -1,5 +1,5 @@
/* Common extra functions.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
@@ -68,6 +68,7 @@ void *xrealloc (void *p, size_t n);
char *xasprintf (const char *format, ...)
__attribute__ ((format (printf, 1, 2), malloc));
char *xstrdup (const char *);
+char *xstrndup (const char *, size_t);
__END_DECLS
diff --git a/support/support_become_root.c b/support/support_become_root.c
index 3fa0bd4ac05..6947dbaa807 100644
--- a/support/support_become_root.c
+++ b/support/support_become_root.c
@@ -1,5 +1,5 @@
/* Acquire root privileges.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
@@ -18,18 +18,80 @@
#include <support/namespace.h>
+#include <errno.h>
+#include <fcntl.h>
#include <sched.h>
#include <stdio.h>
+#include <string.h>
+#include <support/check.h>
+#include <support/xunistd.h>
#include <unistd.h>
+#ifdef CLONE_NEWUSER
+/* The necessary steps to allow file creation in user namespaces. */
+static void
+setup_uid_gid_mapping (uid_t original_uid, gid_t original_gid)
+{
+ int fd = open64 ("/proc/self/uid_map", O_WRONLY);
+ if (fd < 0)
+ {
+ printf ("warning: could not open /proc/self/uid_map: %m\n"
+ "warning: file creation may not be possible\n");
+ return;
+ }
+
+ /* We map our original UID to the same UID in the container so we
+ own our own files normally. Without that, file creation could
+ fail with EOVERFLOW (sic!). */
+ char buf[100];
+ int ret = snprintf (buf, sizeof (buf), "%llu %llu 1\n",
+ (unsigned long long) original_uid,
+ (unsigned long long) original_uid);
+ TEST_VERIFY_EXIT (ret < sizeof (buf));
+ xwrite (fd, buf, ret);
+ xclose (fd);
+
+ /* Linux 3.19 introduced the setgroups file. We need write "deny" to this
+ file otherwise writing to gid_map will fail with EPERM. */
+ fd = open64 ("/proc/self/setgroups", O_WRONLY, 0);
+ if (fd < 0)
+ {
+ if (errno != ENOENT)
+ FAIL_EXIT1 ("open64 (\"/proc/self/setgroups\", 0x%x, 0%o): %m",
+ O_WRONLY, 0);
+ /* This kernel doesn't expose the setgroups file so simply move on. */
+ }
+ else
+ {
+ xwrite (fd, "deny\n", strlen ("deny\n"));
+ xclose (fd);
+ }
+
+ /* Now map our own GID, like we did for the user ID. */
+ fd = xopen ("/proc/self/gid_map", O_WRONLY, 0);
+ ret = snprintf (buf, sizeof (buf), "%llu %llu 1\n",
+ (unsigned long long) original_gid,
+ (unsigned long long) original_gid);
+ TEST_VERIFY_EXIT (ret < sizeof (buf));
+ xwrite (fd, buf, ret);
+ xclose (fd);
+}
+#endif /* CLONE_NEWUSER */
+
bool
support_become_root (void)
{
#ifdef CLONE_NEWUSER
+ uid_t original_uid = getuid ();
+ gid_t original_gid = getgid ();
+
if (unshare (CLONE_NEWUSER | CLONE_NEWNS) == 0)
- /* Even if we do not have UID zero, we have extended privileges at
- this point. */
- return true;
+ {
+ setup_uid_gid_mapping (original_uid, original_gid);
+ /* Even if we do not have UID zero, we have extended privileges at
+ this point. */
+ return true;
+ }
#endif
if (setuid (0) != 0)
{
diff --git a/support/support_can_chroot.c b/support/support_can_chroot.c
index 0dfd2deb543..8922576d19a 100644
--- a/support/support_can_chroot.c
+++ b/support/support_can_chroot.c
@@ -1,5 +1,5 @@
/* Return true if the process can perform a chroot operation.
- Copyright (C) 2017 Free Software Foundation, Inc.
+ Copyright (C) 2017-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
@@ -21,9 +21,9 @@
#include <support/check.h>
#include <support/namespace.h>
#include <support/support.h>
+#include <support/xunistd.h>
#include <sys/stat.h>
#include <unistd.h>
-#include <xunistd.h>
static void
callback (void *closure)
diff --git a/support/support_capture_subprocess.c b/support/support_capture_subprocess.c
index 030f1242526..6d2029e13bd 100644
--- a/support/support_capture_subprocess.c
+++ b/support/support_capture_subprocess.c
@@ -1,5 +1,5 @@
/* Capture output from a subprocess.
- Copyright (C) 2017 Free Software Foundation, Inc.
+ Copyright (C) 2017-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
diff --git a/support/support_capture_subprocess_check.c b/support/support_capture_subprocess_check.c
index e1cf73b6a57..ff5ee89fb02 100644
--- a/support/support_capture_subprocess_check.c
+++ b/support/support_capture_subprocess_check.c
@@ -1,5 +1,5 @@
/* Verify capture output from a subprocess.
- Copyright (C) 2017 Free Software Foundation, Inc.
+ Copyright (C) 2017-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
diff --git a/support/support_chroot.c b/support/support_chroot.c
index f3ef551b053..6356b1af6cf 100644
--- a/support/support_chroot.c
+++ b/support/support_chroot.c
@@ -1,5 +1,5 @@
/* Setup a chroot environment for use within tests.
- Copyright (C) 2017 Free Software Foundation, Inc.
+ Copyright (C) 2017-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
@@ -45,11 +45,7 @@ struct support_chroot *
support_chroot_create (struct support_chroot_configuration conf)
{
struct support_chroot *chroot = xmalloc (sizeof (*chroot));
-
- chroot->path_chroot = xasprintf ("%s/tst-resolv-res_init-XXXXXX", test_dir);
- if (mkdtemp (chroot->path_chroot) == NULL)
- FAIL_EXIT1 ("mkdtemp (\"%s\"): %m", chroot->path_chroot);
- add_temp_file (chroot->path_chroot);
+ chroot->path_chroot = support_create_temp_directory ("tst-resolv-res_init-");
/* Create the /etc directory in the chroot environment. */
char *path_etc = xasprintf ("%s/etc", chroot->path_chroot);
diff --git a/support/support_enter_mount_namespace.c b/support/support_enter_mount_namespace.c
new file mode 100644
index 00000000000..ba68e990f27
--- /dev/null
+++ b/support/support_enter_mount_namespace.c
@@ -0,0 +1,47 @@
+/* Enter a mount namespace.
+ Copyright (C) 2017-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/namespace.h>
+
+#include <sched.h>
+#include <stdio.h>
+#ifdef CLONE_NEWNS
+# include <sys/mount.h>
+#endif /* CLONE_NEWNS */
+
+bool
+support_enter_mount_namespace (void)
+{
+#ifdef CLONE_NEWNS
+ if (unshare (CLONE_NEWNS) == 0)
+ {
+ /* On some systems, / is marked as MS_SHARED, which means that
+ mounts within the namespace leak to the rest of the system,
+ which is not what we want. */
+ if (mount ("none", "/", NULL, MS_REC | MS_PRIVATE, NULL) != 0)
+ {
+ printf ("warning: making the mount namespace private failed: %m\n");
+ return false;
+ }
+ return true;
+ }
+ else
+ printf ("warning: unshare (CLONE_NEWNS) failed: %m\n");
+#endif /* CLONE_NEWNS */
+ return false;
+}
diff --git a/support/support_enter_network_namespace.c b/support/support_enter_network_namespace.c
index 28b0ee29cff..1d874df8854 100644
--- a/support/support_enter_network_namespace.c
+++ b/support/support_enter_network_namespace.c
@@ -1,5 +1,5 @@
/* Enter a network namespace.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
diff --git a/support/support_format_address_family.c b/support/support_format_address_family.c
index 5d42c42a453..2acb9afffd4 100644
--- a/support/support_format_address_family.c
+++ b/support/support_format_address_family.c
@@ -1,5 +1,5 @@
/* Convert an address family to a string.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
diff --git a/support/support_format_addrinfo.c b/support/support_format_addrinfo.c
index eedb0305911..c5e00e516a8 100644
--- a/support/support_format_addrinfo.c
+++ b/support/support_format_addrinfo.c
@@ -1,5 +1,5 @@
/* Convert struct addrinfo values to a string.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
@@ -21,6 +21,7 @@
#include <arpa/inet.h>
#include <errno.h>
#include <stdio.h>
+#include <stdlib.h>
#include <support/support.h>
#include <support/xmemstream.h>
diff --git a/support/support_format_dns_packet.c b/support/support_format_dns_packet.c
index 2992c579717..1170eafb0f0 100644
--- a/support/support_format_dns_packet.c
+++ b/support/support_format_dns_packet.c
@@ -1,5 +1,5 @@
/* Convert a DNS packet to a human-readable representation.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
@@ -20,6 +20,7 @@
#include <arpa/inet.h>
#include <resolv.h>
+#include <stdbool.h>
#include <support/check.h>
#include <support/support.h>
#include <support/xmemstream.h>
diff --git a/support/support_format_herrno.c b/support/support_format_herrno.c
index 493d6ae962b..3d2dc8b27a5 100644
--- a/support/support_format_herrno.c
+++ b/support/support_format_herrno.c
@@ -1,5 +1,5 @@
/* Convert a h_errno error code to a string.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
diff --git a/support/support_format_hostent.c b/support/support_format_hostent.c
index 5b5f26082ef..a4a62afe0a2 100644
--- a/support/support_format_hostent.c
+++ b/support/support_format_hostent.c
@@ -1,5 +1,5 @@
/* Convert a struct hostent object to a string.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
@@ -19,7 +19,9 @@
#include <support/format_nss.h>
#include <arpa/inet.h>
+#include <errno.h>
#include <stdio.h>
+#include <stdlib.h>
#include <support/support.h>
#include <support/xmemstream.h>
@@ -41,10 +43,15 @@ support_format_hostent (struct hostent *h)
{
if (h == NULL)
{
- char *value = support_format_herrno (h_errno);
- char *result = xasprintf ("error: %s\n", value);
- free (value);
- return result;
+ if (h_errno == NETDB_INTERNAL)
+ return xasprintf ("error: NETDB_INTERNAL (errno %d, %m)\n", errno);
+ else
+ {
+ char *value = support_format_herrno (h_errno);
+ char *result = xasprintf ("error: %s\n", value);
+ free (value);
+ return result;
+ }
}
struct xmemstream mem;
diff --git a/support/support_format_netent.c b/support/support_format_netent.c
index 020f5720d92..0d15e784401 100644
--- a/support/support_format_netent.c
+++ b/support/support_format_netent.c
@@ -1,5 +1,5 @@
/* Convert a struct netent object to a string.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
@@ -20,6 +20,7 @@
#include <arpa/inet.h>
#include <stdio.h>
+#include <stdlib.h>
#include <support/support.h>
#include <support/xmemstream.h>
diff --git a/support/support_isolate_in_subprocess.c b/support/support_isolate_in_subprocess.c
index cf486143830..25edc003852 100644
--- a/support/support_isolate_in_subprocess.c
+++ b/support/support_isolate_in_subprocess.c
@@ -1,5 +1,5 @@
/* Run a function in a subprocess.
- Copyright (C) 2017 Free Software Foundation, Inc.
+ Copyright (C) 2017-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
diff --git a/support/support_record_failure.c b/support/support_record_failure.c
index 684055c7467..356798f5560 100644
--- a/support/support_record_failure.c
+++ b/support/support_record_failure.c
@@ -1,5 +1,5 @@
/* Global test failure counter.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
diff --git a/support/support_run_diff.c b/support/support_run_diff.c
index f5155de7274..f24f6c32811 100644
--- a/support/support_run_diff.c
+++ b/support/support_run_diff.c
@@ -1,5 +1,5 @@
/* Invoke the system diff tool to compare two strings.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
diff --git a/support/support_shared_allocate.c b/support/support_shared_allocate.c
index 61d088e8cf5..8ab43c4b380 100644
--- a/support/support_shared_allocate.c
+++ b/support/support_shared_allocate.c
@@ -1,5 +1,5 @@
/* Allocate a memory region shared across processes.
- Copyright (C) 2017 Free Software Foundation, Inc.
+ Copyright (C) 2017-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
diff --git a/support/support_test_compare_failure.c b/support/support_test_compare_failure.c
new file mode 100644
index 00000000000..8eb51c439df
--- /dev/null
+++ b/support/support_test_compare_failure.c
@@ -0,0 +1,58 @@
+/* Reporting a numeric comparison failure.
+ Copyright (C) 2017-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 <stdio.h>
+#include <support/check.h>
+
+static void
+report (const char *which, const char *expr, long long value, int positive,
+ int size)
+{
+ printf (" %s: ", which);
+ if (positive)
+ printf ("%llu", (unsigned long long) value);
+ else
+ printf ("%lld", value);
+ unsigned long long mask
+ = (~0ULL) >> (8 * (sizeof (unsigned long long) - size));
+ printf (" (0x%llx); from: %s\n", (unsigned long long) value & mask, expr);
+}
+
+void
+support_test_compare_failure (const char *file, int line,
+ const char *left_expr,
+ long long left_value,
+ int left_positive,
+ int left_size,
+ const char *right_expr,
+ long long right_value,
+ int right_positive,
+ int right_size)
+{
+ int saved_errno = errno;
+ support_record_failure ();
+ if (left_size != right_size)
+ printf ("%s:%d: numeric comparison failure (widths %d and %d)\n",
+ file, line, left_size * 8, right_size * 8);
+ else
+ printf ("%s:%d: numeric comparison failure\n", file, line);
+ report (" left", left_expr, left_value, left_positive, left_size);
+ report ("right", right_expr, right_value, right_positive, right_size);
+ errno = saved_errno;
+}
diff --git a/support/support_test_main.c b/support/support_test_main.c
index 3c411a467b0..396385729b6 100644
--- a/support/support_test_main.c
+++ b/support/support_test_main.c
@@ -1,5 +1,5 @@
/* Main worker function for the test driver.
- Copyright (C) 1998-2017 Free Software Foundation, Inc.
+ Copyright (C) 1998-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
diff --git a/support/support_test_verify_impl.c b/support/support_test_verify_impl.c
index 55ab2111b3d..5ff5555a6a6 100644
--- a/support/support_test_verify_impl.c
+++ b/support/support_test_verify_impl.c
@@ -1,5 +1,5 @@
/* Implementation of the TEST_VERIFY and TEST_VERIFY_EXIT macros.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
@@ -18,14 +18,17 @@
#include <support/check.h>
+#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
void
support_test_verify_impl (const char *file, int line, const char *expr)
{
+ int saved_errno = errno;
support_record_failure ();
printf ("error: %s:%d: not true: %s\n", file, line, expr);
+ errno = saved_errno;
}
void
diff --git a/support/support_write_file_string.c b/support/support_write_file_string.c
index 48e89597f39..7505679401e 100644
--- a/support/support_write_file_string.c
+++ b/support/support_write_file_string.c
@@ -1,5 +1,5 @@
/* Write a string to a file.
- Copyright (C) 2017 Free Software Foundation, Inc.
+ Copyright (C) 2017-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
@@ -19,7 +19,7 @@
#include <fcntl.h>
#include <string.h>
#include <support/check.h>
-#include <xunistd.h>
+#include <support/xunistd.h>
void
support_write_file_string (const char *path, const char *contents)
diff --git a/support/temp_file-internal.h b/support/temp_file-internal.h
index fb6cceb0658..4cee3c0c354 100644
--- a/support/temp_file-internal.h
+++ b/support/temp_file-internal.h
@@ -1,5 +1,5 @@
/* Internal weak declarations for temporary file handling.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
diff --git a/support/temp_file.c b/support/temp_file.c
index fdb2477ab9e..0bbc7f99726 100644
--- a/support/temp_file.c
+++ b/support/temp_file.c
@@ -1,5 +1,5 @@
/* Temporary file handling for tests.
- Copyright (C) 1998-2017 Free Software Foundation, Inc.
+ Copyright (C) 1998-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
@@ -86,6 +86,19 @@ create_temp_file (const char *base, char **filename)
return fd;
}
+char *
+support_create_temp_directory (const char *base)
+{
+ char *path = xasprintf ("%s/%sXXXXXX", test_dir, base);
+ if (mkdtemp (path) == NULL)
+ {
+ printf ("error: mkdtemp (\"%s\"): %m", path);
+ exit (1);
+ }
+ add_temp_file (path);
+ return path;
+}
+
/* Helper functions called by the test skeleton follow. */
void
diff --git a/support/temp_file.h b/support/temp_file.h
index 6fed8df1ea5..c7795cc577c 100644
--- a/support/temp_file.h
+++ b/support/temp_file.h
@@ -1,5 +1,5 @@
/* Declarations for temporary file handling.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
@@ -32,6 +32,11 @@ void add_temp_file (const char *name);
*FILENAME. */
int create_temp_file (const char *base, char **filename);
+/* Create a temporary directory and schedule it for deletion. BASE is
+ used as a prefix for the unique directory name, which the function
+ returns. The caller should free this string. */
+char *support_create_temp_directory (const char *base);
+
__END_DECLS
#endif /* SUPPORT_TEMP_FILE_H */
diff --git a/support/test-driver.c b/support/test-driver.c
index 47c387c2b48..09c8783e4f5 100644
--- a/support/test-driver.c
+++ b/support/test-driver.c
@@ -1,5 +1,5 @@
/* Main function for test programs.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
diff --git a/support/test-driver.h b/support/test-driver.h
index a8fe9c3565c..1708d68d608 100644
--- a/support/test-driver.h
+++ b/support/test-driver.h
@@ -1,5 +1,5 @@
/* Interfaces for the test driver.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
diff --git a/support/tst-support-namespace.c b/support/tst-support-namespace.c
index dbe7cc07c8f..e20423c4a30 100644
--- a/support/tst-support-namespace.c
+++ b/support/tst-support-namespace.c
@@ -1,5 +1,5 @@
/* Test entering namespaces.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
diff --git a/support/tst-support_capture_subprocess.c b/support/tst-support_capture_subprocess.c
index 5672fba0f7f..a6852560914 100644
--- a/support/tst-support_capture_subprocess.c
+++ b/support/tst-support_capture_subprocess.c
@@ -1,5 +1,5 @@
/* Test capturing output from a subprocess.
- Copyright (C) 2017 Free Software Foundation, Inc.
+ Copyright (C) 2017-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
diff --git a/support/tst-support_format_dns_packet.c b/support/tst-support_format_dns_packet.c
index 9c8589c09c1..b1135eebc6c 100644
--- a/support/tst-support_format_dns_packet.c
+++ b/support/tst-support_format_dns_packet.c
@@ -1,5 +1,5 @@
/* Tests for the support_format_dns_packet function.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
diff --git a/support/tst-support_record_failure-2.sh b/support/tst-support_record_failure-2.sh
index 2c9372cc291..09cd96290a0 100644
--- a/support/tst-support_record_failure-2.sh
+++ b/support/tst-support_record_failure-2.sh
@@ -1,6 +1,6 @@
#!/bin/sh
# Test failure recording (with and without --direct).
-# Copyright (C) 2016-2017 Free Software Foundation, Inc.
+# Copyright (C) 2016-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
diff --git a/support/tst-support_record_failure.c b/support/tst-support_record_failure.c
index e739e739c39..8757f2da029 100644
--- a/support/tst-support_record_failure.c
+++ b/support/tst-support_record_failure.c
@@ -1,5 +1,5 @@
/* Test support_record_failure state sharing.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
diff --git a/support/tst-test_compare.c b/support/tst-test_compare.c
new file mode 100644
index 00000000000..123ba1bc3c9
--- /dev/null
+++ b/support/tst-test_compare.c
@@ -0,0 +1,116 @@
+/* Basic test for the TEST_COMPARE macro.
+ Copyright (C) 2017-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/check.h>
+#include <support/capture_subprocess.h>
+
+static void
+subprocess (void *closure)
+{
+ char ch = 1;
+ /* These tests should fail. */
+ TEST_COMPARE (ch, -1); /* Line 28. */
+ TEST_COMPARE (2LL, -2LL); /* Line 29. */
+ TEST_COMPARE (3LL, (short) -3); /* Line 30. */
+}
+
+struct bitfield
+{
+ int i2 : 2;
+ int i3 : 3;
+ unsigned int u2 : 2;
+ unsigned int u3 : 3;
+ int i31 : 31;
+ unsigned int u31 : 31 ;
+ long long int i63 : 63;
+ unsigned long long int u63 : 63;
+};
+
+/* Functions which return signed sizes are common, so test that these
+ results can readily checked using TEST_COMPARE. */
+
+static int
+return_ssize_t (void)
+{
+ return 4;
+}
+
+static int
+return_int (void)
+{
+ return 4;
+}
+
+
+static int
+do_test (void)
+{
+ /* This should succeed. */
+ TEST_COMPARE (1, 1);
+ TEST_COMPARE (2LL, 2U);
+ {
+ char i8 = 3;
+ unsigned short u16 = 3;
+ TEST_COMPARE (i8, u16);
+ }
+ TEST_COMPARE (return_ssize_t (), sizeof (char[4]));
+ TEST_COMPARE (return_int (), sizeof (char[4]));
+
+ struct bitfield bitfield = { 0 };
+ TEST_COMPARE (bitfield.i2, bitfield.i3);
+ TEST_COMPARE (bitfield.u2, bitfield.u3);
+ TEST_COMPARE (bitfield.u2, bitfield.i3);
+ TEST_COMPARE (bitfield.u3, bitfield.i3);
+ TEST_COMPARE (bitfield.i2, bitfield.u3);
+ TEST_COMPARE (bitfield.i3, bitfield.u2);
+ TEST_COMPARE (bitfield.i63, bitfield.i63);
+ TEST_COMPARE (bitfield.u63, bitfield.u63);
+ TEST_COMPARE (bitfield.i31, bitfield.i63);
+ TEST_COMPARE (bitfield.i63, bitfield.i31);
+
+ struct support_capture_subprocess proc = support_capture_subprocess
+ (&subprocess, NULL);
+
+ /* Discard the reported error. */
+ support_record_failure_reset ();
+
+ puts ("info: *** subprocess output starts ***");
+ fputs (proc.out.buffer, stdout);
+ puts ("info: *** subprocess output ends ***");
+
+ TEST_VERIFY
+ (strcmp (proc.out.buffer,
+ "tst-test_compare.c:28: numeric comparison failure\n"
+ " left: 1 (0x1); from: ch\n"
+ " right: -1 (0xffffffff); from: -1\n"
+ "tst-test_compare.c:29: numeric comparison failure\n"
+ " left: 2 (0x2); from: 2LL\n"
+ " right: -2 (0xfffffffffffffffe); from: -2LL\n"
+ "tst-test_compare.c:30: numeric comparison failure"
+ " (widths 64 and 32)\n"
+ " left: 3 (0x3); from: 3LL\n"
+ " right: -3 (0xfffffffd); from: (short) -3\n") == 0);
+
+ /* Check that there is no output on standard error. */
+ support_capture_subprocess_check (&proc, "TEST_COMPARE", 0, sc_allow_stdout);
+
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/support/tst-xreadlink.c b/support/tst-xreadlink.c
new file mode 100644
index 00000000000..b1422072280
--- /dev/null
+++ b/support/tst-xreadlink.c
@@ -0,0 +1,72 @@
+/* Test the xreadlink function.
+ Copyright (C) 2017-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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <support/check.h>
+#include <support/support.h>
+#include <support/temp_file.h>
+#include <support/xunistd.h>
+
+static int
+do_test (void)
+{
+ char *dir = support_create_temp_directory ("tst-xreadlink-");
+ char *symlink_name = xasprintf ("%s/symlink", dir);
+ add_temp_file (symlink_name);
+
+ /* The limit 10000 is arbitrary and simply there to prevent an
+ attempt to exhaust all available disk space. */
+ for (int size = 1; size < 10000; ++size)
+ {
+ char *contents = xmalloc (size + 1);
+ for (int i = 0; i < size; ++i)
+ contents[i] = 'a' + (rand () % 26);
+ contents[size] = '\0';
+ if (symlink (contents, symlink_name) != 0)
+ {
+ if (errno == ENAMETOOLONG)
+ {
+ printf ("info: ENAMETOOLONG failure at %d bytes\n", size);
+ free (contents);
+ break;
+ }
+ FAIL_EXIT1 ("symlink (%d bytes): %m", size);
+ }
+
+ char *readlink_result = xreadlink (symlink_name);
+ TEST_VERIFY (strcmp (readlink_result, contents) == 0);
+ free (readlink_result);
+ xunlink (symlink_name);
+ free (contents);
+ }
+
+ /* Create an empty file to suppress the temporary file deletion
+ warning. */
+ xclose (xopen (symlink_name, O_WRONLY | O_CREAT, 0));
+
+ free (symlink_name);
+ free (dir);
+
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/support/write_message.c b/support/write_message.c
index f03ed931d6b..a3e2f90535a 100644
--- a/support/write_message.c
+++ b/support/write_message.c
@@ -1,5 +1,5 @@
/* Write a message to standard output.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
@@ -18,12 +18,15 @@
#include <support/support.h>
+#include <errno.h>
#include <string.h>
#include <unistd.h>
void
write_message (const char *message)
{
+ int saved_errno = errno;
ssize_t unused __attribute__ ((unused));
unused = write (STDOUT_FILENO, message, strlen (message));
+ errno = saved_errno;
}
diff --git a/support/xaccept.c b/support/xaccept.c
index 7b25af3b053..fd65fc6c3af 100644
--- a/support/xaccept.c
+++ b/support/xaccept.c
@@ -1,5 +1,5 @@
/* accept with error checking.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
diff --git a/support/xaccept4.c b/support/xaccept4.c
index 67dd95e9fbb..ada3c92267e 100644
--- a/support/xaccept4.c
+++ b/support/xaccept4.c
@@ -1,5 +1,5 @@
/* accept4 with error checking.
- Copyright (C) 2017 Free Software Foundation, Inc.
+ Copyright (C) 2017-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
diff --git a/support/xasprintf.c b/support/xasprintf.c
index 5157680fa25..e593ec5e82b 100644
--- a/support/xasprintf.c
+++ b/support/xasprintf.c
@@ -1,5 +1,5 @@
/* Error-checking wrapper for asprintf.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
diff --git a/support/xbind.c b/support/xbind.c
index cfc6dd8fa86..938e7c07d6d 100644
--- a/support/xbind.c
+++ b/support/xbind.c
@@ -1,5 +1,5 @@
/* bind with error checking.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
diff --git a/support/xcalloc.c b/support/xcalloc.c
index 135f42dab2d..403569041f6 100644
--- a/support/xcalloc.c
+++ b/support/xcalloc.c
@@ -1,5 +1,5 @@
/* Error-checking wrapper for calloc.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
diff --git a/support/xchroot.c b/support/xchroot.c
index abcc299e003..d4759a1bd1f 100644
--- a/support/xchroot.c
+++ b/support/xchroot.c
@@ -1,5 +1,5 @@
/* chroot with error checking.
- Copyright (C) 2017 Free Software Foundation, Inc.
+ Copyright (C) 2017-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
diff --git a/support/xclose.c b/support/xclose.c
index c931e084216..702bef6c6eb 100644
--- a/support/xclose.c
+++ b/support/xclose.c
@@ -1,5 +1,5 @@
/* close with error checking.
- Copyright (C) 2017 Free Software Foundation, Inc.
+ Copyright (C) 2017-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
diff --git a/support/xconnect.c b/support/xconnect.c
index 0266dbc643c..341805d80d8 100644
--- a/support/xconnect.c
+++ b/support/xconnect.c
@@ -1,5 +1,5 @@
/* connect with error checking.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
diff --git a/support/xdlfcn.c b/support/xdlfcn.c
new file mode 100644
index 00000000000..f34bb059c00
--- /dev/null
+++ b/support/xdlfcn.c
@@ -0,0 +1,59 @@
+/* Support functionality for using dlopen/dlclose/dlsym.
+ Copyright (C) 2017-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 <stddef.h>
+#include <support/check.h>
+#include <support/xdlfcn.h>
+
+void *
+xdlopen (const char *filename, int flags)
+{
+ void *dso = dlopen (filename, flags);
+
+ if (dso == NULL)
+ FAIL_EXIT1 ("error: dlopen: %s\n", dlerror ());
+
+ /* Clear any errors. */
+ dlerror ();
+
+ return dso;
+}
+
+void *
+xdlsym (void *handle, const char *symbol)
+{
+ void *sym = dlsym (handle, symbol);
+
+ if (sym == NULL)
+ FAIL_EXIT1 ("error: dlsym: %s\n", dlerror ());
+
+ /* Clear any errors. */
+ dlerror ();
+
+ return sym;
+}
+
+void
+xdlclose (void *handle)
+{
+ if (dlclose (handle) != 0)
+ FAIL_EXIT1 ("error: dlclose: %s\n", dlerror ());
+
+ /* Clear any errors. */
+ dlerror ();
+}
diff --git a/support/xdlfcn.h b/support/xdlfcn.h
new file mode 100644
index 00000000000..5ab7494e709
--- /dev/null
+++ b/support/xdlfcn.h
@@ -0,0 +1,34 @@
+/* Support functionality for using dlopen/dlclose/dlsym.
+ Copyright (C) 2017-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_DLOPEN_H
+#define SUPPORT_DLOPEN_H
+
+#include <dlfcn.h>
+
+__BEGIN_DECLS
+
+/* Each of these terminates process on failure with relevant error message. */
+void *xdlopen (const char *filename, int flags);
+void *xdlsym (void *handle, const char *symbol);
+void xdlclose (void *handle);
+
+
+__END_DECLS
+
+#endif /* SUPPORT_DLOPEN_H */
diff --git a/support/xdup2.c b/support/xdup2.c
index dc08c945182..b8c4c223fb7 100644
--- a/support/xdup2.c
+++ b/support/xdup2.c
@@ -1,5 +1,5 @@
/* dup2 with error checking.
- Copyright (C) 2017 Free Software Foundation, Inc.
+ Copyright (C) 2017-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
diff --git a/support/xfclose.c b/support/xfclose.c
index 2737f050449..39d46f042a7 100644
--- a/support/xfclose.c
+++ b/support/xfclose.c
@@ -1,5 +1,5 @@
/* fclose with error checking.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
diff --git a/support/xfopen.c b/support/xfopen.c
index 14532a09f3c..fb931cf22b4 100644
--- a/support/xfopen.c
+++ b/support/xfopen.c
@@ -1,5 +1,5 @@
/* fopen with error checking.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
diff --git a/support/xfork.c b/support/xfork.c
index aa52ba62c52..dffa2a13d06 100644
--- a/support/xfork.c
+++ b/support/xfork.c
@@ -1,5 +1,5 @@
/* fork with error checking.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
diff --git a/support/xftruncate.c b/support/xftruncate.c
new file mode 100644
index 00000000000..27c7e12ba2b
--- /dev/null
+++ b/support/xftruncate.c
@@ -0,0 +1,27 @@
+/* ftruncate with error checking.
+ Copyright (C) 2017-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/xunistd.h>
+
+void
+xftruncate (int fd, long long length)
+{
+ if (ftruncate64 (fd, length) != 0)
+ FAIL_EXIT1 ("ftruncate64 (%d, %lld): %m", fd, length);
+}
diff --git a/support/xgetsockname.c b/support/xgetsockname.c
index c3bd884f8db..797194f79d8 100644
--- a/support/xgetsockname.c
+++ b/support/xgetsockname.c
@@ -1,5 +1,5 @@
/* getsockname with error checking.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
diff --git a/support/xlisten.c b/support/xlisten.c
index 1953e5900a9..aa70091adb6 100644
--- a/support/xlisten.c
+++ b/support/xlisten.c
@@ -1,5 +1,5 @@
/* listen with error checking.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
diff --git a/support/xlseek.c b/support/xlseek.c
new file mode 100644
index 00000000000..24229399086
--- /dev/null
+++ b/support/xlseek.c
@@ -0,0 +1,29 @@
+/* lseek with error checking.
+ Copyright (C) 2017-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/xunistd.h>
+
+long long
+xlseek (int fd, long long offset, int whence)
+{
+ long long result = lseek64 (fd, offset, whence);
+ if (result < 0)
+ FAIL_EXIT1 ("lseek64 (%d, %lld, %d): %m", fd, offset, whence);
+ return result;
+}
diff --git a/support/xmalloc.c b/support/xmalloc.c
index 450f6997893..78317e2b127 100644
--- a/support/xmalloc.c
+++ b/support/xmalloc.c
@@ -1,5 +1,5 @@
/* Error-checking wrapper for malloc.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
diff --git a/support/xmemstream.c b/support/xmemstream.c
index bce6dc91700..df5fbc489a2 100644
--- a/support/xmemstream.c
+++ b/support/xmemstream.c
@@ -1,5 +1,5 @@
/* Error-checking wrappers for memstream functions.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
diff --git a/support/xmemstream.h b/support/xmemstream.h
index e5ba231e4d5..2d4a577f292 100644
--- a/support/xmemstream.h
+++ b/support/xmemstream.h
@@ -1,5 +1,5 @@
/* Error-checking wrappers for memstream functions.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
diff --git a/support/xmkdir.c b/support/xmkdir.c
index ea17d493918..7e67f783de6 100644
--- a/support/xmkdir.c
+++ b/support/xmkdir.c
@@ -1,5 +1,5 @@
/* mkdir with error checking.
- Copyright (C) 2017 Free Software Foundation, Inc.
+ Copyright (C) 2017-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
diff --git a/support/xmmap.c b/support/xmmap.c
index 435b1eb7333..d580c070138 100644
--- a/support/xmmap.c
+++ b/support/xmmap.c
@@ -1,5 +1,5 @@
/* mmap with error checking.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
diff --git a/support/xmprotect.c b/support/xmprotect.c
index 9410251c322..e6870988e0a 100644
--- a/support/xmprotect.c
+++ b/support/xmprotect.c
@@ -1,5 +1,5 @@
/* mprotect with error checking.
- Copyright (C) 2017 Free Software Foundation, Inc.
+ Copyright (C) 2017-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
diff --git a/support/xmunmap.c b/support/xmunmap.c
index 6ef5a4a4682..e8e5bc2d598 100644
--- a/support/xmunmap.c
+++ b/support/xmunmap.c
@@ -1,5 +1,5 @@
/* munmap with error checking.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
diff --git a/support/xopen.c b/support/xopen.c
index 7f033a03a7a..3d888e8862a 100644
--- a/support/xopen.c
+++ b/support/xopen.c
@@ -1,5 +1,5 @@
/* open64 with error checking.
- Copyright (C) 2017 Free Software Foundation, Inc.
+ Copyright (C) 2017-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
diff --git a/support/xpipe.c b/support/xpipe.c
index 89a64a55c1e..b8529df6208 100644
--- a/support/xpipe.c
+++ b/support/xpipe.c
@@ -1,5 +1,5 @@
/* pipe with error checking.
- Copyright (C) 2017 Free Software Foundation, Inc.
+ Copyright (C) 2017-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
diff --git a/support/xpoll.c b/support/xpoll.c
index bec2521ffc4..b24bf32fc55 100644
--- a/support/xpoll.c
+++ b/support/xpoll.c
@@ -1,5 +1,5 @@
/* poll with error checking.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
diff --git a/support/xpthread_attr_destroy.c b/support/xpthread_attr_destroy.c
index 664c809e9fc..52aa2602fe0 100644
--- a/support/xpthread_attr_destroy.c
+++ b/support/xpthread_attr_destroy.c
@@ -1,5 +1,5 @@
/* pthread_attr_destroy with error checking.
- Copyright (C) 2017 Free Software Foundation, Inc.
+ Copyright (C) 2017-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
diff --git a/support/xpthread_attr_init.c b/support/xpthread_attr_init.c
index 2e30ade9abd..c7aa903db2c 100644
--- a/support/xpthread_attr_init.c
+++ b/support/xpthread_attr_init.c
@@ -1,5 +1,5 @@
/* pthread_attr_init with error checking.
- Copyright (C) 2017 Free Software Foundation, Inc.
+ Copyright (C) 2017-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
diff --git a/support/xpthread_attr_setdetachstate.c b/support/xpthread_attr_setdetachstate.c
index b544dbaa429..6e845acc97d 100644
--- a/support/xpthread_attr_setdetachstate.c
+++ b/support/xpthread_attr_setdetachstate.c
@@ -1,5 +1,5 @@
/* pthread_attr_setdetachstate with error checking.
- Copyright (C) 2017 Free Software Foundation, Inc.
+ Copyright (C) 2017-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
diff --git a/support/xpthread_attr_setguardsize.c b/support/xpthread_attr_setguardsize.c
index 35fed5d9ec6..964ec058c9f 100644
--- a/support/xpthread_attr_setguardsize.c
+++ b/support/xpthread_attr_setguardsize.c
@@ -1,5 +1,5 @@
/* pthread_attr_setguardsize with error checking.
- Copyright (C) 2017 Free Software Foundation, Inc.
+ Copyright (C) 2017-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
diff --git a/support/xpthread_attr_setstacksize.c b/support/xpthread_attr_setstacksize.c
index 02d06310a9c..c5517c0c664 100644
--- a/support/xpthread_attr_setstacksize.c
+++ b/support/xpthread_attr_setstacksize.c
@@ -1,5 +1,5 @@
/* pthread_attr_setstacksize with error checking.
- Copyright (C) 2017 Free Software Foundation, Inc.
+ Copyright (C) 2017-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
diff --git a/support/xpthread_barrier_destroy.c b/support/xpthread_barrier_destroy.c
index efc0719a639..1dae148b465 100644
--- a/support/xpthread_barrier_destroy.c
+++ b/support/xpthread_barrier_destroy.c
@@ -1,5 +1,5 @@
/* pthread_barrier_destroy with error checking.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
diff --git a/support/xpthread_barrier_init.c b/support/xpthread_barrier_init.c
index b32dad1315e..4a2975ad124 100644
--- a/support/xpthread_barrier_init.c
+++ b/support/xpthread_barrier_init.c
@@ -1,5 +1,5 @@
/* pthread_barrier_init with error checking.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
diff --git a/support/xpthread_barrier_wait.c b/support/xpthread_barrier_wait.c
index 7cee44d0a32..61690c5e7c9 100644
--- a/support/xpthread_barrier_wait.c
+++ b/support/xpthread_barrier_wait.c
@@ -1,5 +1,5 @@
/* pthread_barrier_wait with error checking.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
diff --git a/support/xpthread_cancel.c b/support/xpthread_cancel.c
index 3af16f9b543..26e864ea3e8 100644
--- a/support/xpthread_cancel.c
+++ b/support/xpthread_cancel.c
@@ -1,5 +1,5 @@
/* pthread_cancel with error checking.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
diff --git a/support/xpthread_check_return.c b/support/xpthread_check_return.c
index 3094d82e9cb..1658db4b62a 100644
--- a/support/xpthread_check_return.c
+++ b/support/xpthread_check_return.c
@@ -1,5 +1,5 @@
/* Return value checking for pthread functions, exit variant.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
diff --git a/support/xpthread_cond_wait.c b/support/xpthread_cond_wait.c
index b0e9b2a2327..08ec683b660 100644
--- a/support/xpthread_cond_wait.c
+++ b/support/xpthread_cond_wait.c
@@ -1,5 +1,5 @@
/* pthread_cond_wait with error checking.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
diff --git a/support/xpthread_create.c b/support/xpthread_create.c
index 98c63e54c36..24b8456db9f 100644
--- a/support/xpthread_create.c
+++ b/support/xpthread_create.c
@@ -1,5 +1,5 @@
/* pthread_create with error checking.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
diff --git a/support/xpthread_detach.c b/support/xpthread_detach.c
index 2088af2f575..c65f2d7db11 100644
--- a/support/xpthread_detach.c
+++ b/support/xpthread_detach.c
@@ -1,5 +1,5 @@
/* pthread_detach with error checking.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
diff --git a/support/xpthread_join.c b/support/xpthread_join.c
index f23bb9a5aea..29acbd283a1 100644
--- a/support/xpthread_join.c
+++ b/support/xpthread_join.c
@@ -1,5 +1,5 @@
/* pthread_join with error checking.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
diff --git a/support/xpthread_mutex_consistent.c b/support/xpthread_mutex_consistent.c
index 52364be365d..d337163609a 100644
--- a/support/xpthread_mutex_consistent.c
+++ b/support/xpthread_mutex_consistent.c
@@ -1,5 +1,5 @@
/* pthread_mutex_consistent with error checking.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
diff --git a/support/xpthread_mutex_destroy.c b/support/xpthread_mutex_destroy.c
index f11f8f0acd0..d03f016629e 100644
--- a/support/xpthread_mutex_destroy.c
+++ b/support/xpthread_mutex_destroy.c
@@ -1,5 +1,5 @@
/* pthread_mutex_destroy with error checking.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
diff --git a/support/xpthread_mutex_init.c b/support/xpthread_mutex_init.c
index 2d16d1b9d94..40855954a8e 100644
--- a/support/xpthread_mutex_init.c
+++ b/support/xpthread_mutex_init.c
@@ -1,5 +1,5 @@
/* pthread_mutex_init with error checking.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
diff --git a/support/xpthread_mutex_lock.c b/support/xpthread_mutex_lock.c
index af727b45f35..4257960aaaf 100644
--- a/support/xpthread_mutex_lock.c
+++ b/support/xpthread_mutex_lock.c
@@ -1,5 +1,5 @@
/* pthread_mutex_lock with error checking.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
diff --git a/support/xpthread_mutex_unlock.c b/support/xpthread_mutex_unlock.c
index 161b41edf6d..5c385c69340 100644
--- a/support/xpthread_mutex_unlock.c
+++ b/support/xpthread_mutex_unlock.c
@@ -1,5 +1,5 @@
/* pthread_mutex_unlock with error checking.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
diff --git a/support/xpthread_mutexattr_destroy.c b/support/xpthread_mutexattr_destroy.c
index c699e32b410..f352a7ad933 100644
--- a/support/xpthread_mutexattr_destroy.c
+++ b/support/xpthread_mutexattr_destroy.c
@@ -1,5 +1,5 @@
/* pthread_mutexattr_destroy with error checking.
- Copyright (C) 2017 Free Software Foundation, Inc.
+ Copyright (C) 2017-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
diff --git a/support/xpthread_mutexattr_init.c b/support/xpthread_mutexattr_init.c
index fa93fab178e..fe231581e30 100644
--- a/support/xpthread_mutexattr_init.c
+++ b/support/xpthread_mutexattr_init.c
@@ -1,5 +1,5 @@
/* pthread_mutexattr_init with error checking.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
diff --git a/support/xpthread_mutexattr_setprotocol.c b/support/xpthread_mutexattr_setprotocol.c
index 353f75e3d77..e2f544d38cc 100644
--- a/support/xpthread_mutexattr_setprotocol.c
+++ b/support/xpthread_mutexattr_setprotocol.c
@@ -1,5 +1,5 @@
/* pthread_mutexattr_setprotocol with error checking.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
diff --git a/support/xpthread_mutexattr_setpshared.c b/support/xpthread_mutexattr_setpshared.c
index 242da1aeca8..2380560d796 100644
--- a/support/xpthread_mutexattr_setpshared.c
+++ b/support/xpthread_mutexattr_setpshared.c
@@ -1,5 +1,5 @@
/* pthread_mutexattr_setpshared with error checking.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
diff --git a/support/xpthread_mutexattr_setrobust.c b/support/xpthread_mutexattr_setrobust.c
index d7d6fa86301..7886c72a77b 100644
--- a/support/xpthread_mutexattr_setrobust.c
+++ b/support/xpthread_mutexattr_setrobust.c
@@ -1,5 +1,5 @@
/* pthread_mutexattr_setrobust with error checking.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
diff --git a/support/xpthread_mutexattr_settype.c b/support/xpthread_mutexattr_settype.c
index cf22170b56e..91f790c9e52 100644
--- a/support/xpthread_mutexattr_settype.c
+++ b/support/xpthread_mutexattr_settype.c
@@ -1,5 +1,5 @@
/* pthread_mutexattr_settype with error checking.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
diff --git a/support/xpthread_once.c b/support/xpthread_once.c
index 70d58dbab2a..b22c1ce3dd8 100644
--- a/support/xpthread_once.c
+++ b/support/xpthread_once.c
@@ -1,5 +1,5 @@
/* pthread_once with error checking.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
diff --git a/support/xpthread_rwlock_init.c b/support/xpthread_rwlock_init.c
index 824288c90eb..e6c38115d87 100644
--- a/support/xpthread_rwlock_init.c
+++ b/support/xpthread_rwlock_init.c
@@ -1,5 +1,5 @@
/* pthread_rwlock_init with error checking.
- Copyright (C) 2017 Free Software Foundation, Inc.
+ Copyright (C) 2017-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
diff --git a/support/xpthread_rwlock_rdlock.c b/support/xpthread_rwlock_rdlock.c
index 96330a5637d..a88068fc86f 100644
--- a/support/xpthread_rwlock_rdlock.c
+++ b/support/xpthread_rwlock_rdlock.c
@@ -1,5 +1,5 @@
/* pthread_rwlock_rdlock with error checking.
- Copyright (C) 2017 Free Software Foundation, Inc.
+ Copyright (C) 2017-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
diff --git a/support/xpthread_rwlock_unlock.c b/support/xpthread_rwlock_unlock.c
index eaa136b3ec1..7eb282fd182 100644
--- a/support/xpthread_rwlock_unlock.c
+++ b/support/xpthread_rwlock_unlock.c
@@ -1,5 +1,5 @@
/* pthread_rwlock_unlock with error checking.
- Copyright (C) 2017 Free Software Foundation, Inc.
+ Copyright (C) 2017-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
diff --git a/support/xpthread_rwlock_wrlock.c b/support/xpthread_rwlock_wrlock.c
index 8d25d5b818a..0de37146c39 100644
--- a/support/xpthread_rwlock_wrlock.c
+++ b/support/xpthread_rwlock_wrlock.c
@@ -1,5 +1,5 @@
/* pthread_rwlock_wrlock with error checking.
- Copyright (C) 2017 Free Software Foundation, Inc.
+ Copyright (C) 2017-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
diff --git a/support/xpthread_rwlockattr_init.c b/support/xpthread_rwlockattr_init.c
index 48baf247f3e..96ac47d777a 100644
--- a/support/xpthread_rwlockattr_init.c
+++ b/support/xpthread_rwlockattr_init.c
@@ -1,5 +1,5 @@
/* pthread_rwlockattr_init with error checking.
- Copyright (C) 2017 Free Software Foundation, Inc.
+ Copyright (C) 2017-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
diff --git a/support/xpthread_rwlockattr_setkind_np.c b/support/xpthread_rwlockattr_setkind_np.c
index 958aace9f68..34aa3df0a95 100644
--- a/support/xpthread_rwlockattr_setkind_np.c
+++ b/support/xpthread_rwlockattr_setkind_np.c
@@ -1,5 +1,5 @@
/* pthread_rwlockattr_setkind_np with error checking.
- Copyright (C) 2017 Free Software Foundation, Inc.
+ Copyright (C) 2017-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
diff --git a/support/xpthread_sigmask.c b/support/xpthread_sigmask.c
index 0ba9ca02dc6..1fb91dcc209 100644
--- a/support/xpthread_sigmask.c
+++ b/support/xpthread_sigmask.c
@@ -1,5 +1,5 @@
/* pthread_sigmask with error checking.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
diff --git a/support/xpthread_spin_lock.c b/support/xpthread_spin_lock.c
index 6975215b171..4cadbf70f9f 100644
--- a/support/xpthread_spin_lock.c
+++ b/support/xpthread_spin_lock.c
@@ -1,5 +1,5 @@
/* pthread_spin_lock with error checking.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
diff --git a/support/xpthread_spin_unlock.c b/support/xpthread_spin_unlock.c
index 4f19a44c48b..194613993af 100644
--- a/support/xpthread_spin_unlock.c
+++ b/support/xpthread_spin_unlock.c
@@ -1,5 +1,5 @@
/* pthread_spin_unlock with error checking.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
diff --git a/support/xraise.c b/support/xraise.c
new file mode 100644
index 00000000000..1901e741eb0
--- /dev/null
+++ b/support/xraise.c
@@ -0,0 +1,27 @@
+/* Error-checking wrapper for raise.
+ Copyright (C) 2017-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/xsignal.h>
+
+void
+xraise (int sig)
+{
+ if (raise (sig) != 0)
+ FAIL_EXIT1 ("raise (%d): %m" , sig);
+}
diff --git a/support/xreadlink.c b/support/xreadlink.c
new file mode 100644
index 00000000000..c6386491dbc
--- /dev/null
+++ b/support/xreadlink.c
@@ -0,0 +1,44 @@
+/* Error-checking, allocating wrapper for readlink.
+ Copyright (C) 2017-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 <scratch_buffer.h>
+#include <support/check.h>
+#include <support/support.h>
+#include <xunistd.h>
+
+char *
+xreadlink (const char *path)
+{
+ struct scratch_buffer buf;
+ scratch_buffer_init (&buf);
+
+ while (true)
+ {
+ ssize_t count = readlink (path, buf.data, buf.length);
+ if (count < 0)
+ FAIL_EXIT1 ("readlink (\"%s\"): %m", path);
+ if (count < buf.length)
+ {
+ char *result = xstrndup (buf.data, count);
+ scratch_buffer_free (&buf);
+ return result;
+ }
+ if (!scratch_buffer_grow (&buf))
+ FAIL_EXIT1 ("scratch_buffer_grow in xreadlink");
+ }
+}
diff --git a/support/xrealloc.c b/support/xrealloc.c
index 00c313880c1..4d9987c9bb5 100644
--- a/support/xrealloc.c
+++ b/support/xrealloc.c
@@ -1,5 +1,5 @@
/* Error-checking wrapper for realloc.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
diff --git a/support/xrecvfrom.c b/support/xrecvfrom.c
index 17809c4dd2c..a1011a50628 100644
--- a/support/xrecvfrom.c
+++ b/support/xrecvfrom.c
@@ -1,5 +1,5 @@
/* recvfrom with error checking.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
diff --git a/support/xsendto.c b/support/xsendto.c
index 20bddf69651..f51530793ec 100644
--- a/support/xsendto.c
+++ b/support/xsendto.c
@@ -1,5 +1,5 @@
/* sendto with error checking.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
diff --git a/support/xsetsockopt.c b/support/xsetsockopt.c
index 9931882e759..b7c07f21f99 100644
--- a/support/xsetsockopt.c
+++ b/support/xsetsockopt.c
@@ -1,5 +1,5 @@
/* setsockopt with error checking.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
diff --git a/support/xsigaction.c b/support/xsigaction.c
new file mode 100644
index 00000000000..51657de2b73
--- /dev/null
+++ b/support/xsigaction.c
@@ -0,0 +1,27 @@
+/* Error-checking wrapper for sigaction.
+ Copyright (C) 2017-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/xsignal.h>
+
+void
+xsigaction (int sig, const struct sigaction *newact, struct sigaction *oldact)
+{
+ if (sigaction (sig, newact, oldact))
+ FAIL_EXIT1 ("sigaction (%d): %m" , sig);
+}
diff --git a/support/xsignal.c b/support/xsignal.c
new file mode 100644
index 00000000000..e7369f0324b
--- /dev/null
+++ b/support/xsignal.c
@@ -0,0 +1,29 @@
+/* Error-checking wrapper for signal.
+ Copyright (C) 2017-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/xsignal.h>
+
+sighandler_t
+xsignal (int sig, sighandler_t handler)
+{
+ sighandler_t result = signal (sig, handler);
+ if (result == SIG_ERR)
+ FAIL_EXIT1 ("signal (%d, %p): %m", sig, handler);
+ return result;
+}
diff --git a/support/xsignal.h b/support/xsignal.h
index 3dc0d9d5ce6..9ab8d1bfddf 100644
--- a/support/xsignal.h
+++ b/support/xsignal.h
@@ -1,5 +1,5 @@
/* Support functionality for using signals.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
@@ -24,6 +24,14 @@
__BEGIN_DECLS
+/* The following functions call the corresponding libc functions and
+ terminate the process on error. */
+
+void xraise (int sig);
+sighandler_t xsignal (int sig, sighandler_t handler);
+void xsigaction (int sig, const struct sigaction *newact,
+ struct sigaction *oldact);
+
/* The following functions call the corresponding libpthread functions
and terminate the process on error. */
diff --git a/support/xsocket.c b/support/xsocket.c
index c1deaee9248..20282fb8100 100644
--- a/support/xsocket.c
+++ b/support/xsocket.c
@@ -1,5 +1,5 @@
/* socket with error checking.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
diff --git a/support/xsocket.h b/support/xsocket.h
index d6724948d8a..9673abdf54b 100644
--- a/support/xsocket.h
+++ b/support/xsocket.h
@@ -1,5 +1,5 @@
/* Error-checking wrappers for socket functions.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
diff --git a/support/xstdio.h b/support/xstdio.h
index bcc2e863bfc..e7d02744747 100644
--- a/support/xstdio.h
+++ b/support/xstdio.h
@@ -1,5 +1,5 @@
/* Error-checking wrappers for stdio functions.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
diff --git a/support/xstrdup.c b/support/xstrdup.c
index d6a8c04baf0..89eee8584e9 100644
--- a/support/xstrdup.c
+++ b/support/xstrdup.c
@@ -1,5 +1,5 @@
/* strdup with error checking.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
diff --git a/support/xstrndup.c b/support/xstrndup.c
new file mode 100644
index 00000000000..e85fddd439c
--- /dev/null
+++ b/support/xstrndup.c
@@ -0,0 +1,30 @@
+/* strndup with error checking.
+ Copyright (C) 2016-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/support.h>
+
+#include <string.h>
+
+char *
+xstrndup (const char *s, size_t length)
+{
+ char *p = strndup (s, length);
+ if (p == NULL)
+ oom_error ("strndup", length);
+ return p;
+}
diff --git a/support/xsysconf.c b/support/xsysconf.c
new file mode 100644
index 00000000000..afefc2d0984
--- /dev/null
+++ b/support/xsysconf.c
@@ -0,0 +1,36 @@
+/* Error-checking wrapper for sysconf.
+ Copyright (C) 2017-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 <support/check.h>
+#include <support/xunistd.h>
+
+long
+xsysconf (int name)
+{
+ /* Detect errors by a changed errno value, in case -1 is a valid
+ value. Make sure that the caller does not see the zero value for
+ errno. */
+ int old_errno = errno;
+ errno = 0;
+ long result = sysconf (name);
+ if (errno != 0)
+ FAIL_EXIT1 ("sysconf (%d): %m", name);
+ errno = old_errno;
+ return result;
+}
diff --git a/support/xthread.h b/support/xthread.h
index 472763ebe86..79358e7c99c 100644
--- a/support/xthread.h
+++ b/support/xthread.h
@@ -1,5 +1,5 @@
/* Support functionality for using threads.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
diff --git a/support/xunistd.h b/support/xunistd.h
index c947bfd8fb8..5fe5dae818d 100644
--- a/support/xunistd.h
+++ b/support/xunistd.h
@@ -1,5 +1,5 @@
/* POSIX-specific extra functions.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
@@ -36,8 +36,17 @@ void xpipe (int[2]);
void xdup2 (int, int);
int xopen (const char *path, int flags, mode_t);
void xstat (const char *path, struct stat64 *);
+void xfstat (int fd, struct stat64 *);
void xmkdir (const char *path, mode_t);
void xchroot (const char *path);
+void xunlink (const char *path);
+long xsysconf (int name);
+long long xlseek (int fd, long long offset, int whence);
+void xftruncate (int fd, long long length);
+
+/* Read the link at PATH. The caller should free the returned string
+ with free. */
+char *xreadlink (const char *path);
/* Close the file descriptor. Ignore EINTR errors, but terminate the
process on other errors. */
diff --git a/support/xunlink.c b/support/xunlink.c
new file mode 100644
index 00000000000..2ff9296fca8
--- /dev/null
+++ b/support/xunlink.c
@@ -0,0 +1,27 @@
+/* Error-checking wrapper for unlink.
+ Copyright (C) 2017-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/xunistd.h>
+
+void
+xunlink (const char *path)
+{
+ if (unlink (path) != 0)
+ FAIL_EXIT1 ("unlink (\"%s\"): %m", path);
+}
diff --git a/support/xwaitpid.c b/support/xwaitpid.c
index 204795e4c0d..1cb039ca177 100644
--- a/support/xwaitpid.c
+++ b/support/xwaitpid.c
@@ -1,5 +1,5 @@
/* waitpid with error checking.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
diff --git a/support/xwrite.c b/support/xwrite.c
index 134e8ee4c11..bbaae9130a3 100644
--- a/support/xwrite.c
+++ b/support/xwrite.c
@@ -1,5 +1,5 @@
/* write with error checking and retries.
- Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
diff --git a/sysdeps/aarch64/dl-machine.h b/sysdeps/aarch64/dl-machine.h
index 60472036f57..3fb00e6e2d4 100644
--- a/sysdeps/aarch64/dl-machine.h
+++ b/sysdeps/aarch64/dl-machine.h
@@ -51,40 +51,11 @@ elf_machine_load_address (void)
/* To figure out the load address we use the definition that for any symbol:
dynamic_addr(symbol) = static_addr(symbol) + load_addr
- The choice of symbol is arbitrary. The static address we obtain
- by constructing a non GOT reference to the symbol, the dynamic
- address of the symbol we compute using adrp/add to compute the
- symbol's address relative to the PC.
- This depends on 32/16bit relocations being resolved at link time
- and that the static address fits in the 32/16 bits. */
-
- ElfW(Addr) static_addr;
- ElfW(Addr) dynamic_addr;
-
- asm (" \n"
-" adrp %1, _dl_start; \n"
-#ifdef __LP64__
-" add %1, %1, #:lo12:_dl_start \n"
-#else
-" add %w1, %w1, #:lo12:_dl_start \n"
-#endif
-" ldr %w0, 1f \n"
-" b 2f \n"
-"1: \n"
-#ifdef __LP64__
-" .word _dl_start \n"
-#else
-# ifdef __AARCH64EB__
-" .short 0 \n"
-# endif
-" .short _dl_start \n"
-# ifndef __AARCH64EB__
-" .short 0 \n"
-# endif
-#endif
-"2: \n"
- : "=r" (static_addr), "=r" (dynamic_addr));
- return dynamic_addr - static_addr;
+ _DYNAMIC sysmbol is used here as its link-time address stored in
+ the special unrelocated first GOT entry. */
+
+ extern ElfW(Dyn) _DYNAMIC[] attribute_hidden;
+ return (ElfW(Addr)) &_DYNAMIC - elf_machine_dynamic ();
}
/* Set up the loaded object described by L so its unrelocated PLT
diff --git a/sysdeps/i386/fpu/libm-test-ulps b/sysdeps/i386/fpu/libm-test-ulps
index ed685de35dd..a269c7c343b 100644
--- a/sysdeps/i386/fpu/libm-test-ulps
+++ b/sysdeps/i386/fpu/libm-test-ulps
@@ -2693,30 +2693,30 @@ ldouble: 2
Function: "y1_downward":
double: 2
-float: 2
+float: 3
float128: 4
idouble: 2
-ifloat: 2
+ifloat: 3
ifloat128: 4
ildouble: 7
ldouble: 7
Function: "y1_towardzero":
double: 2
-float: 2
+float: 3
float128: 2
idouble: 2
-ifloat: 2
+ifloat: 3
ifloat128: 2
ildouble: 5
ldouble: 5
Function: "y1_upward":
double: 1
-float: 2
+float: 3
float128: 5
idouble: 1
-ifloat: 2
+ifloat: 3
ifloat128: 5
ildouble: 7
ldouble: 7
diff --git a/sysdeps/ia64/fpu/libm-test-ulps b/sysdeps/ia64/fpu/libm-test-ulps
index 2776ba7fae8..543cebcb63c 100644
--- a/sysdeps/ia64/fpu/libm-test-ulps
+++ b/sysdeps/ia64/fpu/libm-test-ulps
@@ -1,508 +1,2396 @@
# Begin of automatic generation
# Maximal error of functions:
+Function: "acos":
+double: 1
+float128: 1
+idouble: 1
+ifloat128: 1
+
+Function: "acos_downward":
+double: 1
+float: 1
+float128: 1
+idouble: 1
+ifloat: 1
+ifloat128: 1
+
+Function: "acos_towardzero":
+double: 1
+float: 1
+float128: 1
+idouble: 1
+ifloat: 1
+ifloat128: 1
+
+Function: "acos_upward":
+double: 1
+float: 1
+float128: 1
+idouble: 1
+ifloat: 1
+ifloat128: 1
+
+Function: "acosh":
+double: 1
+float128: 2
+idouble: 1
+ifloat128: 2
+ildouble: 1
+ldouble: 1
+
+Function: "acosh_downward":
+float128: 3
+ifloat128: 3
+
+Function: "acosh_towardzero":
+float128: 2
+ifloat128: 2
+
+Function: "acosh_upward":
+float128: 2
+ifloat128: 2
+
+Function: "asin":
+float128: 1
+ifloat128: 1
+
Function: "asin_downward":
double: 1
float: 1
+float128: 2
idouble: 1
ifloat: 1
+ifloat128: 2
ildouble: 1
ldouble: 1
Function: "asin_towardzero":
double: 1
float: 1
+float128: 1
idouble: 1
ifloat: 1
+ifloat128: 1
ildouble: 1
ldouble: 1
Function: "asin_upward":
double: 1
float: 1
+float128: 2
+idouble: 1
+ifloat: 1
+ifloat128: 2
+ildouble: 1
+ldouble: 1
+
+Function: "asinh":
+double: 1
+float128: 3
+idouble: 1
+ifloat128: 3
+
+Function: "asinh_downward":
+float128: 4
+ifloat128: 4
+
+Function: "asinh_towardzero":
+float128: 2
+ifloat128: 2
+
+Function: "asinh_upward":
+float128: 4
+ifloat128: 4
+
+Function: "atan":
+float128: 1
+ifloat128: 1
+
+Function: "atan2":
+float128: 1
+ifloat128: 1
+
+Function: "atan2_downward":
+double: 1
+float: 1
+float128: 2
+idouble: 1
+ifloat: 1
+ifloat128: 2
+ildouble: 1
+ldouble: 1
+
+Function: "atan2_towardzero":
+float: 1
+float128: 3
+ifloat: 1
+ifloat128: 3
+ildouble: 1
+ldouble: 1
+
+Function: "atan2_upward":
+double: 1
+float: 1
+float128: 2
+idouble: 1
+ifloat: 1
+ifloat128: 2
+ildouble: 1
+ldouble: 1
+
+Function: "atan_downward":
+double: 1
+float: 1
+float128: 2
+idouble: 1
+ifloat: 1
+ifloat128: 2
+ildouble: 1
+ldouble: 1
+
+Function: "atan_towardzero":
+float: 1
+float128: 1
+ifloat: 1
+ifloat128: 1
+ildouble: 1
+ldouble: 1
+
+Function: "atan_upward":
+double: 1
+float: 1
+float128: 2
+idouble: 1
+ifloat: 1
+ifloat128: 2
+ildouble: 1
+ldouble: 1
+
+Function: "atanh":
+float128: 3
+ifloat128: 3
+
+Function: "atanh_downward":
+float: 1
+float128: 4
+ifloat: 1
+ifloat128: 4
+
+Function: "atanh_towardzero":
+float: 1
+float128: 2
+ifloat: 1
+ifloat128: 2
+
+Function: "atanh_upward":
+float: 1
+float128: 4
+ifloat: 1
+ifloat128: 4
+
+Function: "cabs":
+float128: 1
+ifloat128: 1
+
+Function: "cabs_downward":
+double: 1
+float: 1
+float128: 1
+idouble: 1
+ifloat: 1
+ifloat128: 1
+ildouble: 1
+ldouble: 1
+
+Function: "cabs_towardzero":
+double: 1
+float: 1
+float128: 1
idouble: 1
ifloat: 1
+ifloat128: 1
+ildouble: 1
+ldouble: 1
+
+Function: "cabs_upward":
+double: 1
+float: 1
+float128: 1
+idouble: 1
+ifloat: 1
+ifloat128: 1
ildouble: 1
ldouble: 1
Function: Real part of "cacos":
double: 1
float: 2
+float128: 2
idouble: 1
ifloat: 2
+ifloat128: 2
ildouble: 1
ldouble: 1
Function: Imaginary part of "cacos":
-double: 1
+double: 2
float: 2
+float128: 2
+idouble: 2
+ifloat: 2
+ifloat128: 2
+ildouble: 2
+ldouble: 2
+
+Function: Real part of "cacos_downward":
+double: 1
+float: 1
+float128: 3
+idouble: 1
+ifloat: 1
+ifloat128: 3
+ildouble: 2
+ldouble: 2
+
+Function: Imaginary part of "cacos_downward":
+double: 5
+float: 6
+float128: 6
+idouble: 5
+ifloat: 6
+ifloat128: 6
+ildouble: 5
+ldouble: 5
+
+Function: Real part of "cacos_towardzero":
+double: 1
+float: 1
+float128: 3
idouble: 1
+ifloat: 1
+ifloat128: 3
+ildouble: 2
+ldouble: 2
+
+Function: Imaginary part of "cacos_towardzero":
+double: 4
+float: 5
+float128: 5
+idouble: 4
+ifloat: 5
+ifloat128: 5
+ildouble: 4
+ldouble: 4
+
+Function: Real part of "cacos_upward":
+double: 2
+float: 2
+float128: 3
+idouble: 2
ifloat: 2
+ifloat128: 3
ildouble: 2
ldouble: 2
+Function: Imaginary part of "cacos_upward":
+double: 5
+float: 5
+float128: 7
+idouble: 5
+ifloat: 5
+ifloat128: 7
+ildouble: 5
+ldouble: 5
+
Function: Real part of "cacosh":
-double: 1
+double: 2
float: 2
-idouble: 1
+float128: 2
+idouble: 2
ifloat: 2
+ifloat128: 2
ildouble: 2
ldouble: 2
Function: Imaginary part of "cacosh":
double: 1
float: 2
+float128: 2
idouble: 1
ifloat: 2
+ifloat128: 2
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "cacosh_downward":
+double: 4
+float: 5
+float128: 5
+idouble: 4
+ifloat: 5
+ifloat128: 5
+ildouble: 4
+ldouble: 4
+
+Function: Imaginary part of "cacosh_downward":
+double: 2
+float: 2
+float128: 4
+idouble: 2
+ifloat: 2
+ifloat128: 4
+ildouble: 3
+ldouble: 3
+
+Function: Real part of "cacosh_towardzero":
+double: 4
+float: 5
+float128: 5
+idouble: 4
+ifloat: 5
+ifloat128: 5
+ildouble: 4
+ldouble: 4
+
+Function: Imaginary part of "cacosh_towardzero":
+double: 1
+float: 1
+float128: 3
+idouble: 1
+ifloat: 1
+ifloat128: 3
+ildouble: 2
+ldouble: 2
+
+Function: Real part of "cacosh_upward":
+double: 4
+float: 3
+float128: 6
+idouble: 4
+ifloat: 3
+ifloat128: 6
+ildouble: 4
+ldouble: 4
+
+Function: Imaginary part of "cacosh_upward":
+double: 3
+float: 2
+float128: 4
+idouble: 3
+ifloat: 2
+ifloat128: 4
+ildouble: 3
+ldouble: 3
+
+Function: "carg":
+float128: 2
+ifloat128: 2
+
+Function: "carg_downward":
+double: 1
+float: 1
+float128: 2
+idouble: 1
+ifloat: 1
+ifloat128: 2
+ildouble: 1
+ldouble: 1
+
+Function: "carg_towardzero":
+float: 1
+float128: 3
+ifloat: 1
+ifloat128: 3
+ildouble: 1
+ldouble: 1
+
+Function: "carg_upward":
+double: 1
+float: 1
+float128: 2
+idouble: 1
+ifloat: 1
+ifloat128: 2
ildouble: 1
ldouble: 1
Function: Real part of "casin":
double: 1
float: 1
+float128: 2
idouble: 1
ifloat: 1
+ifloat128: 2
ildouble: 1
ldouble: 1
Function: Imaginary part of "casin":
-double: 1
+double: 2
float: 2
-idouble: 1
+float128: 2
+idouble: 2
ifloat: 2
+ifloat128: 2
ildouble: 2
ldouble: 2
+Function: Real part of "casin_downward":
+double: 3
+float: 2
+float128: 3
+idouble: 3
+ifloat: 2
+ifloat128: 3
+ildouble: 3
+ldouble: 3
+
+Function: Imaginary part of "casin_downward":
+double: 5
+float: 6
+float128: 6
+idouble: 5
+ifloat: 6
+ifloat128: 6
+ildouble: 5
+ldouble: 5
+
+Function: Real part of "casin_towardzero":
+double: 3
+float: 2
+float128: 3
+idouble: 3
+ifloat: 2
+ifloat128: 3
+ildouble: 3
+ldouble: 3
+
+Function: Imaginary part of "casin_towardzero":
+double: 4
+float: 5
+float128: 5
+idouble: 4
+ifloat: 5
+ifloat128: 5
+ildouble: 4
+ldouble: 4
+
+Function: Real part of "casin_upward":
+double: 2
+float: 1
+float128: 3
+idouble: 2
+ifloat: 1
+ifloat128: 3
+ildouble: 2
+ldouble: 2
+
+Function: Imaginary part of "casin_upward":
+double: 5
+float: 5
+float128: 7
+idouble: 5
+ifloat: 5
+ifloat128: 7
+ildouble: 5
+ldouble: 5
+
Function: Real part of "casinh":
-double: 1
+double: 2
float: 2
-idouble: 1
+float128: 2
+idouble: 2
ifloat: 2
+ifloat128: 2
ildouble: 2
ldouble: 2
Function: Imaginary part of "casinh":
double: 1
float: 1
+float128: 2
idouble: 1
ifloat: 1
+ifloat128: 2
ildouble: 1
ldouble: 1
+Function: Real part of "casinh_downward":
+double: 5
+float: 6
+float128: 6
+idouble: 5
+ifloat: 6
+ifloat128: 6
+ildouble: 5
+ldouble: 5
+
+Function: Imaginary part of "casinh_downward":
+double: 3
+float: 2
+float128: 3
+idouble: 3
+ifloat: 2
+ifloat128: 3
+ildouble: 3
+ldouble: 3
+
+Function: Real part of "casinh_towardzero":
+double: 4
+float: 5
+float128: 5
+idouble: 4
+ifloat: 5
+ifloat128: 5
+ildouble: 4
+ldouble: 4
+
+Function: Imaginary part of "casinh_towardzero":
+double: 3
+float: 2
+float128: 3
+idouble: 3
+ifloat: 2
+ifloat128: 3
+ildouble: 3
+ldouble: 3
+
+Function: Real part of "casinh_upward":
+double: 5
+float: 5
+float128: 7
+idouble: 5
+ifloat: 5
+ifloat128: 7
+ildouble: 5
+ldouble: 5
+
+Function: Imaginary part of "casinh_upward":
+double: 2
+float: 1
+float128: 3
+idouble: 2
+ifloat: 1
+ifloat128: 3
+ildouble: 2
+ldouble: 2
+
+Function: Real part of "catan":
+double: 1
+float128: 1
+idouble: 1
+ifloat128: 1
+
Function: Imaginary part of "catan":
double: 1
float: 1
+float128: 1
+idouble: 1
+ifloat: 1
+ifloat128: 1
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "catan_downward":
+double: 1
+float: 1
+float128: 2
+idouble: 1
+ifloat: 1
+ifloat128: 2
+ildouble: 1
+ldouble: 1
+
+Function: Imaginary part of "catan_downward":
+double: 2
+float: 1
+float128: 2
+idouble: 2
+ifloat: 1
+ifloat128: 2
+ildouble: 2
+ldouble: 2
+
+Function: Real part of "catan_towardzero":
+double: 1
+float: 1
+float128: 2
idouble: 1
ifloat: 1
+ifloat128: 2
ildouble: 1
ldouble: 1
+Function: Imaginary part of "catan_towardzero":
+double: 1
+float: 1
+float128: 2
+idouble: 1
+ifloat: 1
+ifloat128: 2
+ildouble: 2
+ldouble: 2
+
+Function: Real part of "catan_upward":
+double: 1
+float: 1
+float128: 2
+idouble: 1
+ifloat: 1
+ifloat128: 2
+ildouble: 1
+ldouble: 1
+
+Function: Imaginary part of "catan_upward":
+double: 2
+float: 2
+float128: 3
+idouble: 2
+ifloat: 2
+ifloat128: 3
+ildouble: 3
+ldouble: 3
+
Function: Real part of "catanh":
double: 1
float: 1
+float128: 1
+idouble: 1
+ifloat: 1
+ifloat128: 1
+ildouble: 1
+ldouble: 1
+
+Function: Imaginary part of "catanh":
+double: 1
+float128: 1
+idouble: 1
+ifloat128: 1
+
+Function: Real part of "catanh_downward":
+double: 2
+float: 1
+float128: 2
+idouble: 2
+ifloat: 1
+ifloat128: 2
+ildouble: 2
+ldouble: 2
+
+Function: Imaginary part of "catanh_downward":
+double: 1
+float: 1
+float128: 2
+idouble: 1
+ifloat: 1
+ifloat128: 2
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "catanh_towardzero":
+double: 1
+float: 1
+float128: 2
+idouble: 1
+ifloat: 1
+ifloat128: 2
+ildouble: 2
+ldouble: 2
+
+Function: Imaginary part of "catanh_towardzero":
+double: 1
+float: 1
+float128: 2
+idouble: 1
+ifloat: 1
+ifloat128: 2
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "catanh_upward":
+double: 4
+float: 4
+float128: 4
+idouble: 4
+ifloat: 4
+ifloat128: 4
+ildouble: 4
+ldouble: 4
+
+Function: Imaginary part of "catanh_upward":
+double: 1
+float: 1
+float128: 2
idouble: 1
ifloat: 1
+ifloat128: 2
+ildouble: 1
+ldouble: 1
+
+Function: "cbrt":
+float128: 1
+ifloat128: 1
+
+Function: "cbrt_downward":
+double: 1
+float128: 1
+idouble: 1
+ifloat128: 1
+ildouble: 1
+ldouble: 1
+
+Function: "cbrt_towardzero":
+float: 1
+float128: 1
+ifloat: 1
+ifloat128: 1
+
+Function: "cbrt_upward":
+float: 1
+float128: 1
+ifloat: 1
+ifloat128: 1
ildouble: 1
ldouble: 1
Function: Real part of "ccos":
double: 1
+float128: 1
idouble: 1
+ifloat128: 1
ildouble: 1
ldouble: 1
Function: Imaginary part of "ccos":
double: 1
float: 1
+float128: 1
idouble: 1
ifloat: 1
+ifloat128: 1
ildouble: 1
ldouble: 1
+Function: Real part of "ccos_downward":
+double: 3
+float: 1
+float128: 2
+idouble: 3
+ifloat: 1
+ifloat128: 2
+ildouble: 3
+ldouble: 3
+
+Function: Imaginary part of "ccos_downward":
+double: 3
+float: 3
+float128: 2
+idouble: 3
+ifloat: 3
+ifloat128: 2
+ildouble: 3
+ldouble: 3
+
+Function: Real part of "ccos_towardzero":
+double: 3
+float: 1
+float128: 2
+idouble: 3
+ifloat: 1
+ifloat128: 2
+ildouble: 3
+ldouble: 3
+
+Function: Imaginary part of "ccos_towardzero":
+double: 3
+float: 3
+float128: 2
+idouble: 3
+ifloat: 3
+ifloat128: 2
+ildouble: 3
+ldouble: 3
+
+Function: Real part of "ccos_upward":
+double: 1
+float: 2
+float128: 3
+idouble: 1
+ifloat: 2
+ifloat128: 3
+ildouble: 2
+ldouble: 2
+
+Function: Imaginary part of "ccos_upward":
+double: 2
+float: 2
+float128: 2
+idouble: 2
+ifloat: 2
+ifloat128: 2
+ildouble: 2
+ldouble: 2
+
Function: Real part of "ccosh":
double: 1
float: 1
+float128: 1
idouble: 1
ifloat: 1
+ifloat128: 1
Function: Imaginary part of "ccosh":
double: 1
float: 1
+float128: 1
idouble: 1
ifloat: 1
+ifloat128: 1
ildouble: 1
ldouble: 1
+Function: Real part of "ccosh_downward":
+double: 3
+float: 2
+float128: 2
+idouble: 3
+ifloat: 2
+ifloat128: 2
+ildouble: 3
+ldouble: 3
+
+Function: Imaginary part of "ccosh_downward":
+double: 3
+float: 3
+float128: 2
+idouble: 3
+ifloat: 3
+ifloat128: 2
+ildouble: 3
+ldouble: 3
+
+Function: Real part of "ccosh_towardzero":
+double: 3
+float: 2
+float128: 2
+idouble: 3
+ifloat: 2
+ifloat128: 2
+ildouble: 3
+ldouble: 3
+
+Function: Imaginary part of "ccosh_towardzero":
+double: 3
+float: 3
+float128: 2
+idouble: 3
+ifloat: 3
+ifloat128: 2
+ildouble: 3
+ldouble: 3
+
+Function: Real part of "ccosh_upward":
+double: 1
+float: 2
+float128: 3
+idouble: 1
+ifloat: 2
+ifloat128: 3
+ildouble: 2
+ldouble: 2
+
+Function: Imaginary part of "ccosh_upward":
+double: 2
+float: 2
+float128: 2
+idouble: 2
+ifloat: 2
+ifloat128: 2
+ildouble: 2
+ldouble: 2
+
Function: Real part of "cexp":
double: 2
float: 1
+float128: 1
idouble: 2
ifloat: 1
+ifloat128: 1
ildouble: 1
ldouble: 1
Function: Imaginary part of "cexp":
double: 1
float: 2
+float128: 1
idouble: 1
ifloat: 2
+ifloat128: 1
ildouble: 1
ldouble: 1
+Function: Real part of "cexp_downward":
+double: 4
+float: 2
+float128: 2
+idouble: 4
+ifloat: 2
+ifloat128: 2
+ildouble: 3
+ldouble: 3
+
+Function: Imaginary part of "cexp_downward":
+double: 3
+float: 3
+float128: 2
+idouble: 3
+ifloat: 3
+ifloat128: 2
+ildouble: 3
+ldouble: 3
+
+Function: Real part of "cexp_towardzero":
+double: 4
+float: 2
+float128: 2
+idouble: 4
+ifloat: 2
+ifloat128: 2
+ildouble: 3
+ldouble: 3
+
+Function: Imaginary part of "cexp_towardzero":
+double: 3
+float: 3
+float128: 2
+idouble: 3
+ifloat: 3
+ifloat128: 2
+ildouble: 3
+ldouble: 3
+
+Function: Real part of "cexp_upward":
+double: 2
+float: 2
+float128: 3
+idouble: 2
+ifloat: 2
+ifloat128: 3
+ildouble: 2
+ldouble: 2
+
+Function: Imaginary part of "cexp_upward":
+double: 3
+float: 2
+float128: 3
+idouble: 3
+ifloat: 2
+ifloat128: 3
+ildouble: 2
+ldouble: 2
+
Function: Real part of "clog":
-double: 1
-float: 1
-idouble: 1
-ifloat: 1
-ildouble: 1
-ldouble: 1
+double: 2
+float: 3
+float128: 2
+idouble: 2
+ifloat: 3
+ifloat128: 2
+ildouble: 2
+ldouble: 2
Function: Imaginary part of "clog":
double: 1
+float128: 1
idouble: 1
+ifloat128: 1
ildouble: 1
ldouble: 1
Function: Real part of "clog10":
+double: 3
+float: 4
+float128: 2
+idouble: 3
+ifloat: 4
+ifloat128: 2
+ildouble: 2
+ldouble: 2
+
+Function: Imaginary part of "clog10":
+double: 2
+float: 1
+float128: 2
+idouble: 2
+ifloat: 1
+ifloat128: 2
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "clog10_downward":
+double: 4
+float: 4
+float128: 3
+idouble: 4
+ifloat: 4
+ifloat128: 3
+ildouble: 4
+ldouble: 4
+
+Function: Imaginary part of "clog10_downward":
+double: 2
+float: 2
+float128: 3
+idouble: 2
+ifloat: 2
+ifloat128: 3
+ildouble: 2
+ldouble: 2
+
+Function: Real part of "clog10_towardzero":
+double: 5
+float: 5
+float128: 4
+idouble: 5
+ifloat: 5
+ifloat128: 4
+ildouble: 4
+ldouble: 4
+
+Function: Imaginary part of "clog10_towardzero":
+double: 2
+float: 2
+float128: 3
+idouble: 2
+ifloat: 2
+ifloat128: 3
+ildouble: 2
+ldouble: 2
+
+Function: Real part of "clog10_upward":
+double: 4
+float: 5
+float128: 4
+idouble: 4
+ifloat: 5
+ifloat128: 4
+ildouble: 4
+ldouble: 4
+
+Function: Imaginary part of "clog10_upward":
double: 2
float: 2
+float128: 3
idouble: 2
ifloat: 2
+ifloat128: 3
+ildouble: 2
+ldouble: 2
+
+Function: Real part of "clog_downward":
+double: 3
+float: 3
+float128: 3
+idouble: 3
+ifloat: 3
+ifloat128: 3
+ildouble: 3
+ldouble: 3
+
+Function: Imaginary part of "clog_downward":
+double: 1
+float: 1
+float128: 2
+idouble: 1
+ifloat: 1
+ifloat128: 2
ildouble: 1
ldouble: 1
-Function: Imaginary part of "clog10":
+Function: Real part of "clog_towardzero":
+double: 3
+float: 4
+float128: 3
+idouble: 3
+ifloat: 4
+ifloat128: 3
+ildouble: 3
+ldouble: 3
+
+Function: Imaginary part of "clog_towardzero":
double: 1
float: 1
+float128: 2
idouble: 1
ifloat: 1
+ifloat128: 2
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "clog_upward":
+double: 2
+float: 3
+float128: 4
+idouble: 2
+ifloat: 3
+ifloat128: 4
+ildouble: 3
+ldouble: 3
+
+Function: Imaginary part of "clog_upward":
+double: 1
+float: 1
+float128: 2
+idouble: 1
+ifloat: 1
+ifloat128: 2
ildouble: 1
ldouble: 1
Function: "cos":
double: 1
+float128: 1
idouble: 1
+ifloat128: 1
Function: "cos_downward":
double: 1
float: 1
+float128: 3
idouble: 1
ifloat: 1
+ifloat128: 3
ildouble: 1
ldouble: 1
Function: "cos_towardzero":
double: 1
float: 1
+float128: 1
idouble: 1
ifloat: 1
+ifloat128: 1
ildouble: 1
ldouble: 1
Function: "cos_upward":
+double: 1
+float128: 2
+idouble: 1
+ifloat128: 2
ildouble: 1
ldouble: 1
+Function: "cosh":
+float128: 1
+ifloat128: 1
+
+Function: "cosh_downward":
+float128: 2
+ifloat128: 1
+
+Function: "cosh_towardzero":
+float128: 2
+ifloat128: 1
+
+Function: "cosh_upward":
+float128: 3
+ifloat128: 1
+
Function: Real part of "cpow":
double: 2
float: 5
+float128: 4
idouble: 2
ifloat: 5
+ifloat128: 4
ildouble: 3
ldouble: 3
Function: Imaginary part of "cpow":
float: 2
+float128: 1
ifloat: 2
+ifloat128: 1
ildouble: 4
ldouble: 4
+Function: Real part of "cpow_downward":
+double: 5
+float: 8
+float128: 6
+idouble: 5
+ifloat: 8
+ifloat128: 6
+ildouble: 7
+ldouble: 7
+
+Function: Imaginary part of "cpow_downward":
+double: 2
+float: 2
+float128: 2
+idouble: 2
+ifloat: 2
+ifloat128: 2
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "cpow_towardzero":
+double: 5
+float: 8
+float128: 6
+idouble: 5
+ifloat: 8
+ifloat128: 6
+ildouble: 7
+ldouble: 7
+
+Function: Imaginary part of "cpow_towardzero":
+double: 2
+float: 2
+float128: 2
+idouble: 2
+ifloat: 2
+ifloat128: 2
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "cpow_upward":
+double: 4
+float: 1
+float128: 3
+idouble: 4
+ifloat: 1
+ifloat128: 3
+ildouble: 2
+ldouble: 2
+
+Function: Imaginary part of "cpow_upward":
+double: 2
+float: 2
+float128: 2
+idouble: 2
+ifloat: 2
+ifloat128: 2
+ildouble: 2
+ldouble: 2
+
Function: Real part of "csin":
double: 1
float: 1
+float128: 1
idouble: 1
ifloat: 1
+ifloat128: 1
ildouble: 1
ldouble: 1
Function: Imaginary part of "csin":
float: 1
+float128: 1
ifloat: 1
+ifloat128: 1
-Function: Real part of "csinh":
-double: 1
+Function: Real part of "csin_downward":
+double: 3
+float: 3
+float128: 2
+idouble: 3
+ifloat: 3
+ifloat128: 2
+ildouble: 3
+ldouble: 3
+
+Function: Imaginary part of "csin_downward":
+double: 3
float: 1
-idouble: 1
+float128: 2
+idouble: 3
ifloat: 1
+ifloat128: 2
+ildouble: 3
+ldouble: 3
+
+Function: Real part of "csin_towardzero":
+double: 3
+float: 3
+float128: 2
+idouble: 3
+ifloat: 3
+ifloat128: 2
+ildouble: 3
+ldouble: 3
+
+Function: Imaginary part of "csin_towardzero":
+double: 3
+float: 1
+float128: 2
+idouble: 3
+ifloat: 1
+ifloat128: 2
+ildouble: 3
+ldouble: 3
+
+Function: Real part of "csin_upward":
+double: 2
+float: 2
+float128: 2
+idouble: 2
+ifloat: 2
+ifloat128: 2
+ildouble: 2
+ldouble: 2
+
+Function: Imaginary part of "csin_upward":
+double: 1
+float: 2
+float128: 3
+idouble: 1
+ifloat: 2
+ifloat128: 3
ildouble: 1
ldouble: 1
-Function: Imaginary part of "csinh":
+Function: Real part of "csinh":
double: 1
float: 1
+float128: 1
idouble: 1
ifloat: 1
+ifloat128: 1
+ildouble: 1
+ldouble: 1
-Function: Real part of "csqrt":
+Function: Imaginary part of "csinh":
double: 1
float: 1
+float128: 1
idouble: 1
ifloat: 1
+ifloat128: 1
ildouble: 1
ldouble: 1
-Function: Imaginary part of "csqrt":
-double: 1
+Function: Real part of "csinh_downward":
+double: 3
float: 1
-idouble: 1
+float128: 2
+idouble: 3
ifloat: 1
+ifloat128: 2
+ildouble: 3
+ldouble: 3
+
+Function: Imaginary part of "csinh_downward":
+double: 3
+float: 3
+float128: 2
+idouble: 3
+ifloat: 3
+ifloat128: 2
+ildouble: 3
+ldouble: 3
+
+Function: Real part of "csinh_towardzero":
+double: 3
+float: 1
+float128: 2
+idouble: 3
+ifloat: 1
+ifloat128: 2
+ildouble: 3
+ldouble: 3
+
+Function: Imaginary part of "csinh_towardzero":
+double: 3
+float: 3
+float128: 2
+idouble: 3
+ifloat: 3
+ifloat128: 2
+ildouble: 3
+ldouble: 3
+
+Function: Real part of "csinh_upward":
+double: 1
+float: 2
+float128: 3
+idouble: 1
+ifloat: 2
+ifloat128: 3
ildouble: 1
ldouble: 1
+Function: Imaginary part of "csinh_upward":
+double: 2
+float: 2
+float128: 2
+idouble: 2
+ifloat: 2
+ifloat128: 2
+ildouble: 2
+ldouble: 2
+
+Function: Real part of "csqrt":
+double: 2
+float: 2
+float128: 2
+idouble: 2
+ifloat: 2
+ifloat128: 2
+ildouble: 2
+ldouble: 2
+
+Function: Imaginary part of "csqrt":
+double: 2
+float: 2
+float128: 2
+idouble: 2
+ifloat: 2
+ifloat128: 2
+ildouble: 2
+ldouble: 2
+
+Function: Real part of "csqrt_downward":
+double: 4
+float: 4
+float128: 4
+idouble: 4
+ifloat: 4
+ifloat128: 4
+ildouble: 4
+ldouble: 4
+
+Function: Imaginary part of "csqrt_downward":
+double: 3
+float: 3
+float128: 3
+idouble: 3
+ifloat: 3
+ifloat128: 3
+ildouble: 3
+ldouble: 3
+
+Function: Real part of "csqrt_towardzero":
+double: 3
+float: 3
+float128: 3
+idouble: 3
+ifloat: 3
+ifloat128: 3
+ildouble: 3
+ldouble: 3
+
+Function: Imaginary part of "csqrt_towardzero":
+double: 3
+float: 3
+float128: 3
+idouble: 3
+ifloat: 3
+ifloat128: 3
+ildouble: 3
+ldouble: 3
+
+Function: Real part of "csqrt_upward":
+double: 4
+float: 4
+float128: 4
+idouble: 4
+ifloat: 4
+ifloat128: 4
+ildouble: 4
+ldouble: 4
+
+Function: Imaginary part of "csqrt_upward":
+double: 3
+float: 2
+float128: 3
+idouble: 3
+ifloat: 2
+ifloat128: 3
+ildouble: 3
+ldouble: 3
+
Function: Real part of "ctan":
double: 1
float: 1
+float128: 3
idouble: 1
ifloat: 1
+ifloat128: 3
ildouble: 2
ldouble: 2
Function: Imaginary part of "ctan":
double: 2
float: 1
+float128: 3
idouble: 2
ifloat: 1
+ifloat128: 3
ildouble: 2
ldouble: 2
Function: Real part of "ctan_downward":
double: 4
float: 4
+float128: 4
idouble: 4
ifloat: 4
+ifloat128: 4
ildouble: 2
ldouble: 2
Function: Imaginary part of "ctan_downward":
double: 3
float: 2
+float128: 5
idouble: 3
ifloat: 2
+ifloat128: 5
ildouble: 2
ldouble: 2
Function: Real part of "ctan_towardzero":
double: 2
-float: 1
+float: 2
+float128: 4
idouble: 2
-ifloat: 1
+ifloat: 2
+ifloat128: 4
ildouble: 2
ldouble: 2
Function: Imaginary part of "ctan_towardzero":
double: 3
float: 2
+float128: 5
idouble: 3
ifloat: 2
+ifloat128: 5
ildouble: 4
ldouble: 4
Function: Real part of "ctan_upward":
double: 2
float: 3
+float128: 5
idouble: 2
ifloat: 3
+ifloat128: 5
ildouble: 5
ldouble: 5
Function: Imaginary part of "ctan_upward":
double: 6
float: 2
+float128: 5
idouble: 6
ifloat: 2
+ifloat128: 5
ildouble: 7
ldouble: 7
Function: Real part of "ctanh":
double: 2
float: 1
+float128: 3
idouble: 2
ifloat: 1
+ifloat128: 3
ildouble: 1
ldouble: 1
Function: Imaginary part of "ctanh":
double: 2
float: 1
+float128: 3
idouble: 2
ifloat: 1
+ifloat128: 3
ildouble: 2
ldouble: 2
Function: Real part of "ctanh_downward":
double: 3
float: 2
+float128: 5
idouble: 3
ifloat: 2
+ifloat128: 5
ildouble: 1
ldouble: 1
Function: Imaginary part of "ctanh_downward":
double: 4
float: 4
+float128: 4
idouble: 4
ifloat: 4
+ifloat128: 4
ildouble: 2
ldouble: 2
Function: Real part of "ctanh_towardzero":
double: 3
float: 2
+float128: 5
idouble: 3
ifloat: 2
+ifloat128: 5
ildouble: 4
ldouble: 4
Function: Imaginary part of "ctanh_towardzero":
double: 2
float: 1
+float128: 3
idouble: 2
ifloat: 1
+ifloat128: 3
ildouble: 1
ldouble: 1
Function: Real part of "ctanh_upward":
double: 6
float: 2
+float128: 5
idouble: 6
ifloat: 2
+ifloat128: 5
ildouble: 7
ldouble: 7
Function: Imaginary part of "ctanh_upward":
double: 2
float: 3
+float128: 5
idouble: 2
ifloat: 3
+ifloat128: 5
ildouble: 5
ldouble: 5
+Function: "erf":
+float128: 1
+ifloat128: 1
+
+Function: "erf_downward":
+float128: 2
+ifloat128: 2
+
+Function: "erf_towardzero":
+float128: 1
+ifloat128: 1
+
+Function: "erf_upward":
+float128: 2
+ifloat128: 2
+
+Function: "erfc":
+float128: 2
+ifloat128: 2
+
+Function: "erfc_downward":
+double: 1
+float128: 5
+idouble: 1
+ifloat128: 5
+
+Function: "erfc_towardzero":
+double: 1
+float128: 4
+idouble: 1
+ifloat128: 4
+
+Function: "erfc_upward":
+double: 1
+float128: 5
+idouble: 1
+ifloat128: 5
+
+Function: "exp":
+float: 1
+float128: 1
+ifloat: 1
+ifloat128: 1
+
+Function: "exp10":
+float128: 2
+ifloat128: 2
+
+Function: "exp10_downward":
+float128: 3
+ifloat128: 3
+
+Function: "exp10_towardzero":
+float128: 3
+ifloat128: 3
+
+Function: "exp10_upward":
+float128: 3
+ifloat128: 3
+
+Function: "exp2":
+double: 1
+float128: 1
+idouble: 1
+ifloat128: 1
+ildouble: 1
+ldouble: 1
+
+Function: "exp2_downward":
+double: 1
+float128: 1
+idouble: 1
+ifloat128: 1
+ildouble: 1
+ldouble: 1
+
+Function: "exp2_towardzero":
+double: 1
+float128: 1
+idouble: 1
+ifloat128: 1
+ildouble: 1
+ldouble: 1
+
+Function: "exp2_upward":
+double: 1
+float128: 2
+idouble: 1
+ifloat128: 2
+ildouble: 1
+ldouble: 1
+
Function: "expm1":
+double: 1
+float128: 1
+idouble: 1
+ifloat128: 1
ildouble: 1
ldouble: 1
Function: "expm1_downward":
+float128: 2
+ifloat128: 2
+ildouble: 1
+ldouble: 1
+
+Function: "expm1_towardzero":
+float128: 4
+ifloat128: 4
+
+Function: "expm1_upward":
+float128: 3
+ifloat128: 3
+
+Function: "gamma":
+float: 1
+ifloat: 1
+
+Function: "gamma_downward":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: "gamma_towardzero":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: "gamma_upward":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: "hypot":
+float128: 1
+ifloat128: 1
+
+Function: "hypot_downward":
+double: 1
+float: 1
+float128: 1
+idouble: 1
+ifloat: 1
+ifloat128: 1
+ildouble: 1
+ldouble: 1
+
+Function: "hypot_towardzero":
+double: 1
+float: 1
+float128: 1
+idouble: 1
+ifloat: 1
+ifloat128: 1
+ildouble: 1
+ldouble: 1
+
+Function: "hypot_upward":
+double: 1
+float: 1
+float128: 1
+idouble: 1
+ifloat: 1
+ifloat128: 1
ildouble: 1
ldouble: 1
Function: "j0":
double: 2
float: 2
+float128: 2
idouble: 2
ifloat: 2
+ifloat128: 2
ildouble: 2
ldouble: 2
+Function: "j0_downward":
+double: 6
+float: 4
+float128: 4
+idouble: 6
+ifloat: 4
+ifloat128: 4
+ildouble: 3
+ldouble: 3
+
+Function: "j0_towardzero":
+double: 2
+float: 1
+float128: 2
+idouble: 2
+ifloat: 1
+ifloat128: 2
+ildouble: 5
+ldouble: 5
+
+Function: "j0_upward":
+double: 3
+float: 2
+float128: 5
+idouble: 3
+ifloat: 2
+ifloat128: 5
+ildouble: 5
+ldouble: 5
+
Function: "j1":
double: 1
float: 2
+float128: 4
idouble: 1
ifloat: 2
+ifloat128: 4
ildouble: 1
ldouble: 1
+Function: "j1_downward":
+double: 3
+float: 2
+float128: 4
+idouble: 3
+ifloat: 2
+ifloat128: 4
+ildouble: 4
+ldouble: 4
+
+Function: "j1_towardzero":
+double: 3
+float: 2
+float128: 4
+idouble: 3
+ifloat: 2
+ifloat128: 4
+ildouble: 4
+ldouble: 4
+
+Function: "j1_upward":
+double: 3
+float: 4
+float128: 3
+idouble: 3
+ifloat: 4
+ifloat128: 3
+ildouble: 3
+ldouble: 3
+
Function: "jn":
double: 4
float: 4
+float128: 7
idouble: 4
ifloat: 4
+ifloat128: 7
ildouble: 4
ldouble: 4
+Function: "jn_downward":
+double: 4
+float: 5
+float128: 8
+idouble: 4
+ifloat: 5
+ifloat128: 8
+ildouble: 4
+ldouble: 4
+
+Function: "jn_towardzero":
+double: 4
+float: 5
+float128: 8
+idouble: 4
+ifloat: 5
+ifloat128: 8
+ildouble: 5
+ldouble: 5
+
+Function: "jn_upward":
+double: 5
+float: 4
+float128: 7
+idouble: 5
+ifloat: 4
+ifloat128: 7
+ildouble: 5
+ldouble: 5
+
+Function: "lgamma":
+float: 1
+float128: 5
+ifloat: 1
+ifloat128: 5
+
+Function: "lgamma_downward":
+double: 1
+float: 1
+float128: 8
+idouble: 1
+ifloat: 1
+ifloat128: 8
+
+Function: "lgamma_towardzero":
+double: 1
+float: 1
+float128: 5
+idouble: 1
+ifloat: 1
+ifloat128: 5
+
+Function: "lgamma_upward":
+double: 1
+float: 1
+float128: 8
+idouble: 1
+ifloat: 1
+ifloat128: 8
+
+Function: "log":
+float128: 1
+ifloat128: 1
+
+Function: "log10":
+float128: 1
+ifloat128: 1
+
+Function: "log10_downward":
+double: 1
+float128: 1
+idouble: 1
+ifloat128: 1
+ildouble: 1
+ldouble: 1
+
+Function: "log10_towardzero":
+double: 1
+float128: 1
+idouble: 1
+ifloat128: 1
+ildouble: 1
+ldouble: 1
+
+Function: "log10_upward":
+double: 1
+float: 1
+float128: 1
+idouble: 1
+ifloat: 1
+ifloat128: 1
+ildouble: 1
+ldouble: 1
+
+Function: "log1p":
+float128: 2
+ifloat128: 2
+
+Function: "log1p_downward":
+double: 1
+float128: 3
+idouble: 1
+ifloat128: 3
+
+Function: "log1p_towardzero":
+double: 1
+float128: 3
+idouble: 1
+ifloat128: 3
+
+Function: "log1p_upward":
+double: 1
+float128: 2
+idouble: 1
+ifloat128: 2
+
+Function: "log2":
+float128: 2
+ifloat128: 2
+
+Function: "log2_downward":
+float128: 3
+ifloat128: 3
+
+Function: "log2_towardzero":
+float128: 1
+ifloat128: 1
+
+Function: "log2_upward":
+float128: 1
+ifloat128: 1
+
+Function: "log_downward":
+double: 1
+float128: 1
+idouble: 1
+ifloat128: 1
+
+Function: "log_towardzero":
+double: 1
+float128: 2
+idouble: 1
+ifloat128: 2
+
+Function: "log_upward":
+double: 1
+float128: 1
+idouble: 1
+ifloat128: 1
+
+Function: "pow":
+float128: 2
+ifloat128: 2
+
Function: "pow_downward":
double: 1
float: 1
+float128: 2
idouble: 1
ifloat: 1
+ifloat128: 2
+ildouble: 1
+ldouble: 1
Function: "pow_towardzero":
double: 1
float: 1
+float128: 2
idouble: 1
ifloat: 1
+ifloat128: 2
+ildouble: 1
+ldouble: 1
Function: "pow_upward":
double: 1
float: 1
+float128: 2
idouble: 1
ifloat: 1
+ifloat128: 2
ildouble: 1
ldouble: 1
Function: "sin":
double: 1
+float128: 1
idouble: 1
+ifloat128: 1
Function: "sin_downward":
double: 1
+float: 1
+float128: 3
idouble: 1
+ifloat: 1
+ifloat128: 3
ildouble: 1
ldouble: 1
Function: "sin_towardzero":
double: 1
+float: 1
+float128: 2
idouble: 1
+ifloat: 1
+ifloat128: 2
ildouble: 1
ldouble: 1
Function: "sin_upward":
double: 1
+float: 1
+float128: 3
idouble: 1
+ifloat: 1
+ifloat128: 3
ildouble: 1
ldouble: 1
Function: "sincos":
double: 1
+float128: 1
idouble: 1
+ifloat128: 1
+
+Function: "sincos_downward":
+double: 1
+float: 1
+float128: 3
+idouble: 1
+ifloat: 1
+ifloat128: 3
+
+Function: "sincos_towardzero":
+double: 1
+float: 1
+float128: 2
+idouble: 1
+ifloat: 1
+ifloat128: 2
+
+Function: "sincos_upward":
+double: 1
+float: 1
+float128: 3
+idouble: 1
+ifloat: 1
+ifloat128: 3
+
+Function: "sinh":
+float128: 2
+ifloat128: 2
+
+Function: "sinh_downward":
+float128: 3
+ifloat128: 3
+
+Function: "sinh_towardzero":
+float128: 3
+ifloat128: 3
+
+Function: "sinh_upward":
+float128: 4
+ifloat128: 4
+
+Function: "tan":
+float128: 1
+ifloat128: 1
+ildouble: 1
+ldouble: 1
Function: "tan_downward":
+float128: 1
+ifloat128: 1
ildouble: 1
ldouble: 1
Function: "tan_towardzero":
+float128: 1
+ifloat128: 1
ildouble: 1
ldouble: 1
Function: "tan_upward":
+float128: 1
+ifloat128: 1
ildouble: 1
ldouble: 1
+Function: "tanh":
+float128: 2
+ifloat128: 2
+
+Function: "tanh_downward":
+float128: 4
+ifloat128: 4
+
+Function: "tanh_towardzero":
+float128: 3
+ifloat128: 3
+
+Function: "tanh_upward":
+float128: 3
+ifloat128: 3
+
Function: "tgamma":
+float128: 4
+ifloat128: 4
+ildouble: 1
+ldouble: 1
+
+Function: "tgamma_downward":
+double: 1
+float: 1
+float128: 5
+idouble: 1
+ifloat: 1
+ifloat128: 5
+ildouble: 1
+ldouble: 1
+
+Function: "tgamma_towardzero":
+double: 1
+float: 1
+float128: 5
+idouble: 1
+ifloat: 1
+ifloat128: 5
+ildouble: 1
+ldouble: 1
+
+Function: "tgamma_upward":
+double: 1
+float: 1
+float128: 4
+idouble: 1
+ifloat: 1
+ifloat128: 4
ildouble: 1
ldouble: 1
Function: "y0":
double: 2
float: 1
+float128: 3
idouble: 2
ifloat: 1
+ifloat128: 3
ildouble: 1
ldouble: 1
+Function: "y0_downward":
+double: 4
+float: 4
+float128: 4
+idouble: 4
+ifloat: 4
+ifloat128: 4
+ildouble: 4
+ldouble: 4
+
+Function: "y0_towardzero":
+double: 3
+float: 3
+float128: 3
+idouble: 3
+ifloat: 3
+ifloat128: 3
+ildouble: 5
+ldouble: 5
+
+Function: "y0_upward":
+double: 4
+float: 5
+float128: 3
+idouble: 4
+ifloat: 5
+ifloat128: 3
+ildouble: 3
+ldouble: 3
+
Function: "y1":
double: 3
float: 2
+float128: 2
idouble: 3
ifloat: 2
+ifloat128: 2
ildouble: 2
ldouble: 2
+Function: "y1_downward":
+double: 9
+float: 2
+float128: 4
+idouble: 9
+ifloat: 2
+ifloat128: 4
+ildouble: 3
+ldouble: 3
+
+Function: "y1_towardzero":
+double: 3
+float: 2
+float128: 2
+idouble: 3
+ifloat: 2
+ifloat128: 2
+ildouble: 3
+ldouble: 3
+
+Function: "y1_upward":
+double: 4
+float: 2
+float128: 5
+idouble: 4
+ifloat: 2
+ifloat128: 5
+ildouble: 7
+ldouble: 7
+
Function: "yn":
double: 3
float: 3
+float128: 5
idouble: 3
ifloat: 3
-ildouble: 2
-ldouble: 2
+ifloat128: 5
+ildouble: 3
+ldouble: 3
+
+Function: "yn_downward":
+double: 4
+float: 4
+float128: 5
+idouble: 4
+ifloat: 4
+ifloat128: 5
+ildouble: 4
+ldouble: 4
+
+Function: "yn_towardzero":
+double: 3
+float: 3
+float128: 5
+idouble: 3
+ifloat: 3
+ifloat128: 5
+ildouble: 5
+ldouble: 5
+
+Function: "yn_upward":
+double: 4
+float: 5
+float128: 5
+idouble: 4
+ifloat: 5
+ifloat128: 5
+ildouble: 3
+ldouble: 3
# end of automatic generation
diff --git a/sysdeps/ia64/memchr.S b/sysdeps/ia64/memchr.S
index d60cf7bd87f..9a0abc6f0a4 100644
--- a/sysdeps/ia64/memchr.S
+++ b/sysdeps/ia64/memchr.S
@@ -67,6 +67,10 @@ ENTRY(__memchr)
.body
mov ret0 = str
add last = str, in2 // last byte
+ ;;
+ cmp.ltu p6, p0 = last, str
+ ;;
+(p6) mov last = -1
and tmp = 7, str // tmp = str % 8
cmp.ne p7, p0 = r0, r0 // clear p7
extr.u chr = in1, 0, 8 // chr = (unsigned char) in1
diff --git a/sysdeps/nptl/unwind-forcedunwind.c b/sysdeps/nptl/unwind-forcedunwind.c
index 33a1975f5e6..ace58b2468d 100644
--- a/sysdeps/nptl/unwind-forcedunwind.c
+++ b/sysdeps/nptl/unwind-forcedunwind.c
@@ -49,7 +49,7 @@ pthread_cancel_init (void)
return;
}
- handle = __libc_dlopen (LIBGCC_S_SO);
+ handle = __libc_dlopen_mode (LIBGCC_S_SO, RTLD_NOW | __RTLD_DLOPEN);
if (handle == NULL
|| (resume = __libc_dlsym (handle, "_Unwind_Resume")) == NULL
diff --git a/sysdeps/powerpc/powerpc32/sysdep.h b/sysdeps/powerpc/powerpc32/sysdep.h
index 965ea43c94e..7a8e86831db 100644
--- a/sysdeps/powerpc/powerpc32/sysdep.h
+++ b/sysdeps/powerpc/powerpc32/sysdep.h
@@ -91,7 +91,7 @@ GOT_LABEL: ; \
ASM_SIZE_DIRECTIVE(name)
#if ! IS_IN(rtld) && defined (ENABLE_LOCK_ELISION)
-# define ABORT_TRANSACTION \
+# define ABORT_TRANSACTION_IMPL \
cmpwi 2,0; \
beq 1f; \
lwz 0,TM_CAPABLE(2); \
@@ -102,8 +102,9 @@ GOT_LABEL: ; \
.align 4; \
1:
#else
-# define ABORT_TRANSACTION
+# define ABORT_TRANSACTION_IMPL
#endif
+#define ABORT_TRANSACTION ABORT_TRANSACTION_IMPL
#define DO_CALL(syscall) \
ABORT_TRANSACTION \
diff --git a/sysdeps/powerpc/powerpc64/sysdep.h b/sysdeps/powerpc/powerpc64/sysdep.h
index ab5f395cfd0..6a49a8ba1f0 100644
--- a/sysdeps/powerpc/powerpc64/sysdep.h
+++ b/sysdeps/powerpc/powerpc64/sysdep.h
@@ -264,7 +264,7 @@ LT_LABELSUFFIX(name,_name_end): ; \
END_2(name)
#if !IS_IN(rtld) && defined (ENABLE_LOCK_ELISION)
-# define ABORT_TRANSACTION \
+# define ABORT_TRANSACTION_IMPL \
cmpdi 13,0; \
beq 1f; \
lwz 0,TM_CAPABLE(13); \
@@ -275,8 +275,9 @@ LT_LABELSUFFIX(name,_name_end): ; \
.p2align 4; \
1:
#else
-# define ABORT_TRANSACTION
+# define ABORT_TRANSACTION_IMPL
#endif
+#define ABORT_TRANSACTION ABORT_TRANSACTION_IMPL
#define DO_CALL(syscall) \
ABORT_TRANSACTION \
diff --git a/sysdeps/powerpc/powerpc64le/Makefile b/sysdeps/powerpc/powerpc64le/Makefile
index f554a791b77..7f83a19b9aa 100644
--- a/sysdeps/powerpc/powerpc64le/Makefile
+++ b/sysdeps/powerpc/powerpc64le/Makefile
@@ -17,9 +17,14 @@ $(foreach suf,$(all-object-suffixes),$(objpfx)test-float128%$(suf)): CFLAGS += -
$(foreach suf,$(all-object-suffixes),$(objpfx)test-ifloat128%$(suf)): CFLAGS += -mfloat128
CFLAGS-libm-test-support-float128.c += -mfloat128
CFLAGS-test-math-iscanonical.cc += -mfloat128
+CFLAGS-test-math-iseqsig.cc += -mfloat128
CFLAGS-test-math-issignaling.cc += -mfloat128
CFLAGS-test-math-iszero.cc += -mfloat128
-$(objpfx)test-float128% $(objpfx)test-ifloat128% $(objpfx)test-math-iszero: \
+$(foreach test, \
+ test-float128% test-ifloat128% \
+ test-math-iscanonical test-math-iseqsig test-math-issignaling \
+ test-math-iszero, \
+ $(objpfx)$(test)): \
gnulib-tests += $(f128-loader-link)
endif
diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile
index dbe6a36c57c..b1fe960d008 100644
--- a/sysdeps/unix/sysv/linux/Makefile
+++ b/sysdeps/unix/sysv/linux/Makefile
@@ -50,7 +50,8 @@ sysdep_headers += sys/mount.h sys/acct.h sys/sysctl.h \
bits/siginfo-arch.h bits/siginfo-consts-arch.h
tests += tst-clone tst-clone2 tst-clone3 tst-fanotify tst-personality \
- tst-quota tst-sync_file_range test-errno-linux tst-sysconf-iov_max
+ tst-quota tst-sync_file_range tst-sysconf-iov_max tst-ttyname \
+ test-errno-linux
# Generate the list of SYS_* macros for the system calls (__NR_* macros).
diff --git a/sysdeps/unix/sysv/linux/getcwd.c b/sysdeps/unix/sysv/linux/getcwd.c
index 3b556fd4502..f485de88a54 100644
--- a/sysdeps/unix/sysv/linux/getcwd.c
+++ b/sysdeps/unix/sysv/linux/getcwd.c
@@ -76,7 +76,7 @@ __getcwd (char *buf, size_t size)
int retval;
retval = INLINE_SYSCALL (getcwd, 2, path, alloc_size);
- if (retval >= 0)
+ if (retval > 0 && path[0] == '/')
{
#ifndef NO_ALLOCATION
if (buf == NULL && size == 0)
@@ -92,10 +92,10 @@ __getcwd (char *buf, size_t size)
return buf;
}
- /* The system call cannot handle paths longer than a page.
- Neither can the magic symlink in /proc/self. Just use the
+ /* The system call either cannot handle paths longer than a page
+ or can succeed without returning an absolute path. Just use the
generic implementation right away. */
- if (errno == ENAMETOOLONG)
+ if (retval >= 0 || errno == ENAMETOOLONG)
{
#ifndef NO_ALLOCATION
if (buf == NULL && size == 0)
diff --git a/sysdeps/unix/sysv/linux/ia64/ipc_priv.h b/sysdeps/unix/sysv/linux/ia64/ipc_priv.h
new file mode 100644
index 00000000000..e602eea4556
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/ia64/ipc_priv.h
@@ -0,0 +1,21 @@
+/* Old SysV permission definition for Linux. IA64 version.
+ Copyright (C) 2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <sys/ipc.h> /* For __key_t */
+
+#define __IPC_64 0x0
diff --git a/sysdeps/unix/sysv/linux/ia64/mmap_internal.h b/sysdeps/unix/sysv/linux/ia64/mmap_internal.h
new file mode 100644
index 00000000000..dbaaa3f9044
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/ia64/mmap_internal.h
@@ -0,0 +1,29 @@
+/* Common mmap definition for Linux implementation. Linux/ia64 version.
+ Copyright (C) 2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef MMAP_IA64_INTERNAL_LINUX_H
+#define MMAP_IA64_INTERNAL_LINUX_H
+
+/* Linux allows PAGE_SHIFT in range of [12-16] and expect
+ mmap2 offset to be provided in based on the configured pagesize.
+ Determine the shift dynamically with getpagesize. */
+#define MMAP2_PAGE_UNIT -1
+
+#include_next <mmap_internal.h>
+
+#endif
diff --git a/sysdeps/unix/sysv/linux/m68k/mmap_internal.h b/sysdeps/unix/sysv/linux/m68k/mmap_internal.h
index bd8bd3843b4..9fe9d9127d5 100644
--- a/sysdeps/unix/sysv/linux/m68k/mmap_internal.h
+++ b/sysdeps/unix/sysv/linux/m68k/mmap_internal.h
@@ -22,7 +22,7 @@
/* ColdFire and Sun 3 kernels have PAGE_SHIFT set to 13 and expect
mmap2 offset to be provided in 8K pages. Determine the shift
dynamically with getpagesize. */
-#define MMAP2_PAGE_SHIFT -1
+#define MMAP2_PAGE_UNIT -1
#include_next <mmap_internal.h>
diff --git a/sysdeps/unix/sysv/linux/mmap.c b/sysdeps/unix/sysv/linux/mmap.c
index 98c2f88eb8b..59292b6d790 100644
--- a/sysdeps/unix/sysv/linux/mmap.c
+++ b/sysdeps/unix/sysv/linux/mmap.c
@@ -21,9 +21,9 @@
#include <sys/mman.h>
#include <sysdep.h>
#include <stdint.h>
-#include <mmap_internal.h>
#ifndef __OFF_T_MATCHES_OFF64_T
+# include <mmap_internal.h>
/* An architecture may override this. */
# ifndef MMAP_ADJUST_OFFSET
diff --git a/sysdeps/unix/sysv/linux/mmap_internal.h b/sysdeps/unix/sysv/linux/mmap_internal.h
index 499e3896050..47c099183cc 100644
--- a/sysdeps/unix/sysv/linux/mmap_internal.h
+++ b/sysdeps/unix/sysv/linux/mmap_internal.h
@@ -27,13 +27,13 @@
#endif
#if MMAP2_PAGE_UNIT == -1
-static int page_unit;
-
+static uint64_t page_unit;
# define MMAP_CHECK_PAGE_UNIT() \
if (page_unit == 0) \
page_unit = __getpagesize ();
+# undef MMAP2_PAGE_UNIT
+# define MMAP2_PAGE_UNIT page_unit
#else
-# define page_unit MMAP2_PAGE_UNIT
# define MMAP_CHECK_PAGE_UNIT()
#endif
diff --git a/sysdeps/unix/sysv/linux/powerpc/not-errno.h b/sysdeps/unix/sysv/linux/powerpc/not-errno.h
new file mode 100644
index 00000000000..27da21bdf16
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/powerpc/not-errno.h
@@ -0,0 +1,30 @@
+/* Syscall wrapper that do not set errno. Linux powerpc version.
+ Copyright (C) 2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+/* __access_noerrno is used during process initialization in elf/dl-tunables.c
+ before the TCB is initialized, prohibiting the usage of
+ ABORT_TRANSACTION. */
+#undef ABORT_TRANSACTION
+#define ABORT_TRANSACTION
+
+#include "sysdeps/unix/sysv/linux/not-errno.h"
+
+/* Recover ABORT_TRANSACTION's previous value, in order to not affect
+ other syscalls. */
+#undef ABORT_TRANSACTION
+#define ABORT_TRANSACTION ABORT_TRANSACTION_IMPL
diff --git a/sysdeps/unix/sysv/linux/tst-ttyname.c b/sysdeps/unix/sysv/linux/tst-ttyname.c
new file mode 100644
index 00000000000..6848a6d3e28
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/tst-ttyname.c
@@ -0,0 +1,577 @@
+/* Copyright (C) 2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If
+ not, see <http://www.gnu.org/licenses/>. */
+
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <sched.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mount.h>
+#include <sys/prctl.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <unistd.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/xunistd.h>
+
+/* generic utilities */
+
+#define VERIFY(expr) \
+ do { \
+ if (!(expr)) \
+ { \
+ printf ("error: %s:%d: %s: %m\n", \
+ __FILE__, __LINE__, #expr); \
+ exit (1); \
+ } \
+ } while (0)
+
+static void
+touch (const char *path, mode_t mode)
+{
+ xclose (xopen (path, O_WRONLY|O_CREAT|O_NOCTTY, mode));
+}
+
+static size_t
+trim_prefix (char *str, size_t str_len, const char *prefix)
+{
+ size_t prefix_len = strlen (prefix);
+ if (str_len > prefix_len && memcmp (str, prefix, prefix_len) == 0)
+ {
+ memmove (str, str + prefix_len, str_len - prefix_len);
+ return str_len - prefix_len;
+ }
+ return str_len;
+}
+
+/* returns a pointer to static storage */
+static char *
+proc_fd_readlink (const char *linkname)
+{
+ static char target[PATH_MAX+1];
+ ssize_t target_len = readlink (linkname, target, PATH_MAX);
+ VERIFY (target_len > 0);
+ target_len = trim_prefix (target, target_len, "(unreachable)");
+ target[target_len] = '\0';
+ return target;
+}
+
+/* plain ttyname runner */
+
+struct result
+{
+ const char *name;
+ int err;
+};
+
+/* strings in result structure are in static storage */
+static struct result
+run_ttyname (int fd)
+{
+ struct result ret;
+ errno = 0;
+ ret.name = ttyname (fd);
+ ret.err = errno;
+ return ret;
+}
+
+static bool
+eq_ttyname (struct result actual, struct result expected)
+{
+ char *actual_name, *expected_name;
+
+ if ((actual.err == expected.err) &&
+ (!actual.name == !expected.name) &&
+ (actual.name ? strcmp (actual.name, expected.name) == 0 : true))
+ {
+ if (expected.name)
+ expected_name = xasprintf ("\"%s\"", expected.name);
+ else
+ expected_name = xstrdup ("NULL");
+
+ printf ("info: ttyname: PASS {name=%s, errno=%d}\n",
+ expected_name, expected.err);
+
+ free (expected_name);
+ return true;
+ }
+
+ if (actual.name)
+ actual_name = xasprintf ("\"%s\"", actual.name);
+ else
+ actual_name = xstrdup ("NULL");
+
+ if (expected.name)
+ expected_name = xasprintf ("\"%s\"", expected.name);
+ else
+ expected_name = xstrdup ("NULL");
+
+ printf ("error: ttyname: actual {name=%s, errno=%d} != expected {name=%s, errno=%d}\n",
+ actual_name, actual.err,
+ expected_name, expected.err);
+
+ free (actual_name);
+ free (expected_name);
+ return false;
+}
+
+/* ttyname_r runner */
+
+struct result_r
+{
+ const char *name;
+ int ret;
+ int err;
+};
+
+/* strings in result structure are in static storage */
+static struct result_r
+run_ttyname_r (int fd)
+{
+ static char buf[TTY_NAME_MAX];
+
+ struct result_r ret;
+ errno = 0;
+ ret.ret = ttyname_r (fd, buf, TTY_NAME_MAX);
+ ret.err = errno;
+ if (ret.ret == 0)
+ ret.name = buf;
+ else
+ ret.name = NULL;
+ return ret;
+}
+
+static bool
+eq_ttyname_r (struct result_r actual, struct result_r expected)
+{
+ char *actual_name, *expected_name;
+
+ if ((actual.err == expected.err) &&
+ (actual.ret == expected.ret) &&
+ (!actual.name == !expected.name) &&
+ (actual.name ? strcmp (actual.name, expected.name) == 0 : true))
+ {
+ if (expected.name)
+ expected_name = xasprintf ("\"%s\"", expected.name);
+ else
+ expected_name = xstrdup ("NULL");
+
+ printf ("info: ttyname_r: PASS {name=%s, ret=%d, errno=%d}\n",
+ expected_name, expected.ret, expected.err);
+
+ free (expected_name);
+ return true;
+ }
+
+ if (actual.name)
+ actual_name = xasprintf ("\"%s\"", actual.name);
+ else
+ actual_name = xstrdup ("NULL");
+
+ if (expected.name)
+ expected_name = xasprintf ("\"%s\"", expected.name);
+ else
+ expected_name = xstrdup ("NULL");
+
+ printf ("error: ttyname_r: actual {name=%s, ret=%d, errno=%d} != expected {name=%s, ret=%d, errno=%d}\n",
+ actual_name, actual.ret, actual.err,
+ expected_name, expected.ret, expected.err);
+
+ free (actual_name);
+ free (expected_name);
+ return false;
+}
+
+/* combined runner */
+
+static bool
+doit (int fd, const char *testname, struct result_r expected_r)
+{
+ struct result expected = {.name=expected_r.name, .err=expected_r.ret};
+ bool ret = true;
+
+ printf ("info: testcase: %s\n", testname);
+
+ if (!eq_ttyname (run_ttyname (fd), expected))
+ ret = false;
+ if (!eq_ttyname_r (run_ttyname_r (fd), expected_r))
+ ret = false;
+
+ if (!ret)
+ support_record_failure ();
+
+ return ret;
+}
+
+/* chroot setup */
+
+static char *chrootdir;
+
+static void
+prepare (int argc, char **argv)
+{
+ chrootdir = xasprintf ("%s/tst-ttyname-XXXXXX", test_dir);
+ if (mkdtemp (chrootdir) == NULL)
+ FAIL_EXIT1 ("mkdtemp (\"%s\"): %m", chrootdir);
+ add_temp_file (chrootdir);
+}
+#define PREPARE prepare
+
+/* These chroot setup functions put the TTY at at "/console" (where it
+ won't be found by ttyname), and create "/dev/console" as an
+ ordinary file. This way, it's easier to write test-cases that
+ expect ttyname to fail; test-cases that expect it to succeed need
+ to explicitly remount it at "/dev/console". */
+
+static int
+do_in_chroot_1 (int (*cb)(const char *, int))
+{
+ printf ("info: entering chroot 1\n");
+
+ /* Open the PTS that we'll be testing on. */
+ int master;
+ char *slavename;
+ master = posix_openpt (O_RDWR|O_NOCTTY|O_NONBLOCK);
+ if (master < 0)
+ {
+ if (errno == ENOENT)
+ FAIL_UNSUPPORTED ("posix_openpt: %m");
+ else
+ FAIL_EXIT1 ("posix_openpt: %m");
+ }
+ VERIFY ((slavename = ptsname (master)));
+ VERIFY (unlockpt (master) == 0);
+ if (strncmp (slavename, "/dev/pts/", 9) != 0)
+ FAIL_UNSUPPORTED ("slave pseudo-terminal is not under /dev/pts/: %s",
+ slavename);
+ int slave = xopen (slavename, O_RDWR, 0);
+ if (!doit (slave, "basic smoketest",
+ (struct result_r){.name=slavename, .ret=0, .err=0}))
+ return 1;
+
+ pid_t pid = xfork ();
+ if (pid == 0)
+ {
+ xclose (master);
+
+ if (!support_enter_mount_namespace ())
+ FAIL_UNSUPPORTED ("could not enter new mount namespace");
+
+ VERIFY (mount ("tmpfs", chrootdir, "tmpfs", 0, "mode=755") == 0);
+ VERIFY (chdir (chrootdir) == 0);
+
+ xmkdir ("proc", 0755);
+ xmkdir ("dev", 0755);
+ xmkdir ("dev/pts", 0755);
+
+ VERIFY (mount ("/proc", "proc", NULL, MS_BIND|MS_REC, NULL) == 0);
+ VERIFY (mount ("devpts", "dev/pts", "devpts",
+ MS_NOSUID|MS_NOEXEC,
+ "newinstance,ptmxmode=0666,mode=620") == 0);
+ VERIFY (symlink ("pts/ptmx", "dev/ptmx") == 0);
+
+ touch ("console", 0);
+ touch ("dev/console", 0);
+ VERIFY (mount (slavename, "console", NULL, MS_BIND, NULL) == 0);
+
+ xchroot (".");
+
+ char *linkname = xasprintf ("/proc/self/fd/%d", slave);
+ char *target = proc_fd_readlink (linkname);
+ VERIFY (strcmp (target, slavename) == 0);
+ free (linkname);
+
+ _exit (cb (slavename, slave));
+ }
+ int status;
+ xwaitpid (pid, &status, 0);
+ VERIFY (WIFEXITED (status));
+ xclose (master);
+ xclose (slave);
+ return WEXITSTATUS (status);
+}
+
+static int
+do_in_chroot_2 (int (*cb)(const char *, int))
+{
+ printf ("info: entering chroot 2\n");
+
+ int pid_pipe[2];
+ xpipe (pid_pipe);
+ int exit_pipe[2];
+ xpipe (exit_pipe);
+
+ /* Open the PTS that we'll be testing on. */
+ int master;
+ char *slavename;
+ VERIFY ((master = posix_openpt (O_RDWR|O_NOCTTY|O_NONBLOCK)) >= 0);
+ VERIFY ((slavename = ptsname (master)));
+ VERIFY (unlockpt (master) == 0);
+ if (strncmp (slavename, "/dev/pts/", 9) != 0)
+ FAIL_UNSUPPORTED ("slave pseudo-terminal is not under /dev/pts/: %s",
+ slavename);
+ /* wait until in a new mount ns to open the slave */
+
+ /* enable `wait`ing on grandchildren */
+ VERIFY (prctl (PR_SET_CHILD_SUBREAPER, 1) == 0);
+
+ pid_t pid = xfork (); /* outer child */
+ if (pid == 0)
+ {
+ xclose (master);
+ xclose (pid_pipe[0]);
+ xclose (exit_pipe[1]);
+
+ if (!support_enter_mount_namespace ())
+ FAIL_UNSUPPORTED ("could not enter new mount namespace");
+
+ int slave = xopen (slavename, O_RDWR, 0);
+ if (!doit (slave, "basic smoketest",
+ (struct result_r){.name=slavename, .ret=0, .err=0}))
+ _exit (1);
+
+ VERIFY (mount ("tmpfs", chrootdir, "tmpfs", 0, "mode=755") == 0);
+ VERIFY (chdir (chrootdir) == 0);
+
+ xmkdir ("proc", 0755);
+ xmkdir ("dev", 0755);
+ xmkdir ("dev/pts", 0755);
+
+ VERIFY (mount ("devpts", "dev/pts", "devpts",
+ MS_NOSUID|MS_NOEXEC,
+ "newinstance,ptmxmode=0666,mode=620") == 0);
+ VERIFY (symlink ("pts/ptmx", "dev/ptmx") == 0);
+
+ touch ("console", 0);
+ touch ("dev/console", 0);
+ VERIFY (mount (slavename, "console", NULL, MS_BIND, NULL) == 0);
+
+ xchroot (".");
+
+ if (unshare (CLONE_NEWNS | CLONE_NEWPID) < 0)
+ FAIL_UNSUPPORTED ("could not enter new PID namespace");
+ pid = xfork (); /* inner child */
+ if (pid == 0)
+ {
+ xclose (pid_pipe[1]);
+
+ /* wait until the outer child has exited */
+ char c;
+ VERIFY (read (exit_pipe[0], &c, 1) == 0);
+ xclose (exit_pipe[0]);
+
+ VERIFY (mount ("proc", "/proc", "proc",
+ MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL) == 0);
+
+ char *linkname = xasprintf ("/proc/self/fd/%d", slave);
+ char *target = proc_fd_readlink (linkname);
+ VERIFY (strcmp (target, strrchr (slavename, '/')) == 0);
+ free (linkname);
+
+ _exit (cb (slavename, slave));
+ }
+ xwrite (pid_pipe[1], &pid, sizeof pid);
+ _exit (0);
+ }
+ xclose (pid_pipe[1]);
+ xclose (exit_pipe[0]);
+ xclose (exit_pipe[1]);
+
+ /* wait for the outer child */
+ int status;
+ xwaitpid (pid, &status, 0);
+ VERIFY (WIFEXITED (status));
+ int ret = WEXITSTATUS (status);
+ if (ret != 0)
+ return ret;
+
+ /* set 'pid' to the inner child */
+ VERIFY (read (pid_pipe[0], &pid, sizeof pid) == sizeof pid);
+ xclose (pid_pipe[0]);
+
+ /* wait for the inner child */
+ xwaitpid (pid, &status, 0);
+ VERIFY (WIFEXITED (status));
+ xclose (master);
+ return WEXITSTATUS (status);
+}
+
+/* main test */
+
+static int
+run_chroot_tests (const char *slavename, int slave)
+{
+ struct stat st;
+ bool ok = true;
+
+ /* There are 3 groups of tests here. The first group fairly
+ generically does things known to mess up ttyname, and verifies
+ that ttyname copes correctly. The remaining groups are
+ increasingly convoluted, as we target specific parts of ttyname
+ to try to confuse. */
+
+ /* Basic tests that it doesn't get confused by multiple devpts
+ instances. */
+ {
+ VERIFY (stat (slavename, &st) < 0); /* sanity check */
+ if (!doit (slave, "no conflict, no match",
+ (struct result_r){.name=NULL, .ret=ENODEV, .err=ENODEV}))
+ ok = false;
+ VERIFY (mount ("/console", "/dev/console", NULL, MS_BIND, NULL) == 0);
+ if (!doit (slave, "no conflict, console",
+ (struct result_r){.name="/dev/console", .ret=0, .err=0}))
+ ok = false;
+ VERIFY (umount ("/dev/console") == 0);
+
+ /* keep creating PTYs until we we get a name collision */
+ while (stat (slavename, &st) < 0)
+ posix_openpt (O_RDWR|O_NOCTTY|O_NONBLOCK);
+ VERIFY (stat (slavename, &st) == 0);
+
+ if (!doit (slave, "conflict, no match",
+ (struct result_r){.name=NULL, .ret=ENODEV, .err=ENODEV}))
+ ok = false;
+ VERIFY (mount ("/console", "/dev/console", NULL, MS_BIND, NULL) == 0);
+ if (!doit (slave, "conflict, console",
+ (struct result_r){.name="/dev/console", .ret=0, .err=0}))
+ ok = false;
+ VERIFY (umount ("/dev/console") == 0);
+ }
+
+ /* The first tests kinda assumed that they hit certain code-paths
+ based on assuming that the readlink target is 'slavename', but
+ that's not quite always true. They're still a good preliminary
+ sanity check, so keep them, but let's add tests that make sure
+ that those code-paths are hit by doing a readlink ourself. */
+ {
+ char *linkname = xasprintf ("/proc/self/fd/%d", slave);
+ char *target = proc_fd_readlink (linkname);
+ free (linkname);
+ /* Depeding on how we set up the chroot, the kernel may or may not
+ trim the leading path to the target (it may give us "/6",
+ instead of "/dev/pts/6"). We test it both ways (do_in_chroot_1
+ and do_in_chroot_2). This test group relies on the target
+ existing, so guarantee that it does exist by creating it if
+ necessary. */
+ if (stat (target, &st) < 0)
+ {
+ VERIFY (errno == ENOENT);
+ touch (target, 0);
+ }
+
+ VERIFY (mount ("/console", "/dev/console", NULL, MS_BIND, NULL) == 0);
+ VERIFY (mount ("/console", target, NULL, MS_BIND, NULL) == 0);
+ if (!doit (slave, "with readlink target",
+ (struct result_r){.name=target, .ret=0, .err=0}))
+ ok = false;
+ VERIFY (umount (target) == 0);
+ VERIFY (umount ("/dev/console") == 0);
+
+ VERIFY (mount ("/console", "/dev/console", NULL, MS_BIND, NULL) == 0);
+ VERIFY (mount (slavename, target, NULL, MS_BIND, NULL) == 0);
+ if (!doit (slave, "with readlink trap; fallback",
+ (struct result_r){.name="/dev/console", .ret=0, .err=0}))
+ ok = false;
+ VERIFY (umount (target) == 0);
+ VERIFY (umount ("/dev/console") == 0);
+
+ VERIFY (mount (slavename, target, NULL, MS_BIND, NULL) == 0);
+ if (!doit (slave, "with readlink trap; no fallback",
+ (struct result_r){.name=NULL, .ret=ENODEV, .err=ENODEV}))
+ ok = false;
+ VERIFY (umount (target) == 0);
+ }
+
+ /* This test makes sure that everything still works OK if readdir
+ finds a pseudo-match before and/or after the actual match. Now,
+ to do that, we need to control that readdir finds the
+ pseudo-matches before and after the actual match; and there's no
+ good way to control that order in absence of whitebox testing.
+ So, just create 3 files, then use opendir/readdir to see what
+ order they are in, and assign meaning based on that order, not by
+ name; assigning the first to be a pseudo-match, the second to be
+ the actual match, and the third to be a pseudo-match. This
+ assumes that (on tmpfs) ordering within the directory is stable
+ in the absence of modification, which seems reasonably safe. */
+ {
+ /* since we're testing the fallback search, disable the readlink
+ happy-path */
+ VERIFY (umount2 ("/proc", MNT_DETACH) == 0);
+
+ touch ("/dev/console1", 0);
+ touch ("/dev/console2", 0);
+ touch ("/dev/console3", 0);
+
+ char *c[3];
+ int ci = 0;
+ DIR *dirstream = opendir ("/dev");
+ VERIFY (dirstream != NULL);
+ struct dirent *d;
+ while ((d = readdir (dirstream)) != NULL && ci < 3)
+ {
+ if (strcmp (d->d_name, "console1") &&
+ strcmp (d->d_name, "console2") &&
+ strcmp (d->d_name, "console3") )
+ continue;
+ c[ci++] = xasprintf ("/dev/%s", d->d_name);
+ }
+ VERIFY (ci == 3);
+ VERIFY (closedir (dirstream) == 0);
+
+ VERIFY (mount (slavename, c[0], NULL, MS_BIND, NULL) == 0);
+ VERIFY (mount ("/console", c[1], NULL, MS_BIND, NULL) == 0);
+ VERIFY (mount (slavename, c[2], NULL, MS_BIND, NULL) == 0);
+ VERIFY (umount2 ("/dev/pts", MNT_DETACH) == 0);
+ if (!doit (slave, "with search-path trap",
+ (struct result_r){.name=c[1], .ret=0, .err=0}))
+ ok = false;
+ for (int i = 0; i < 3; i++)
+ {
+ VERIFY (umount (c[i]) == 0);
+ VERIFY (unlink (c[i]) == 0);
+ free (c[i]);
+ }
+ }
+
+ return ok ? 0 : 1;
+}
+
+static int
+do_test (void)
+{
+ support_become_root ();
+
+ int ret1 = do_in_chroot_1 (run_chroot_tests);
+ if (ret1 == EXIT_UNSUPPORTED)
+ return ret1;
+
+ int ret2 = do_in_chroot_2 (run_chroot_tests);
+ if (ret2 == EXIT_UNSUPPORTED)
+ return ret2;
+
+ return ret1 | ret2;
+}
+
+#include <support/test-driver.c>
diff --git a/sysdeps/unix/sysv/linux/ttyname.c b/sysdeps/unix/sysv/linux/ttyname.c
index 5909cb765f7..f4c955f25b4 100644
--- a/sysdeps/unix/sysv/linux/ttyname.c
+++ b/sysdeps/unix/sysv/linux/ttyname.c
@@ -35,16 +35,14 @@
char *__ttyname;
#endif
-static char *getttyname (const char *dev, dev_t mydev,
- ino64_t myino, int save, int *dostat)
- internal_function;
-
+static char *getttyname (const char *dev, const struct stat64 *mytty,
+ int save, int *dostat);
libc_freeres_ptr (static char *getttyname_name);
static char *
-internal_function attribute_compat_text_section
-getttyname (const char *dev, dev_t mydev, ino64_t myino, int save, int *dostat)
+attribute_compat_text_section
+getttyname (const char *dev, const struct stat64 *mytty, int save, int *dostat)
{
static size_t namelen;
struct stat64 st;
@@ -65,7 +63,7 @@ getttyname (const char *dev, dev_t mydev, ino64_t myino, int save, int *dostat)
*((char *) __mempcpy (getttyname_name, dev, devlen - 1)) = '/';
while ((d = __readdir64 (dirstream)) != NULL)
- if ((d->d_fileno == myino || *dostat)
+ if ((d->d_fileno == mytty->st_ino || *dostat)
&& strcmp (d->d_name, "stdin")
&& strcmp (d->d_name, "stdout")
&& strcmp (d->d_name, "stderr"))
@@ -87,12 +85,7 @@ getttyname (const char *dev, dev_t mydev, ino64_t myino, int save, int *dostat)
}
memcpy (&getttyname_name[devlen], d->d_name, dlen);
if (__xstat64 (_STAT_VER, getttyname_name, &st) == 0
-#ifdef _STATBUF_ST_RDEV
- && S_ISCHR (st.st_mode) && st.st_rdev == mydev
-#else
- && d->d_fileno == myino && st.st_dev == mydev
-#endif
- )
+ && is_mytty (mytty, &st))
{
(void) __closedir (dirstream);
#if 0
@@ -122,6 +115,7 @@ ttyname (int fd)
char procname[30];
struct stat64 st, st1;
int dostat = 0;
+ int doispty = 0;
char *name;
int save = errno;
struct termios term;
@@ -169,30 +163,15 @@ ttyname (int fd)
/* Verify readlink result, fall back on iterating through devices. */
if (ttyname_buf[0] == '/'
&& __xstat64 (_STAT_VER, ttyname_buf, &st1) == 0
-#ifdef _STATBUF_ST_RDEV
- && S_ISCHR (st1.st_mode)
- && st1.st_rdev == st.st_rdev
-#endif
- && st1.st_ino == st.st_ino
- && st1.st_dev == st.st_dev)
+ && is_mytty (&st, &st1))
return ttyname_buf;
- /* If the link doesn't exist, then it points to a device in another
- namespace. */
- if (is_pty (&st))
- {
- __set_errno (ENODEV);
- return NULL;
- }
+ doispty = 1;
}
if (__xstat64 (_STAT_VER, "/dev/pts", &st1) == 0 && S_ISDIR (st1.st_mode))
{
-#ifdef _STATBUF_ST_RDEV
- name = getttyname ("/dev/pts", st.st_rdev, st.st_ino, save, &dostat);
-#else
- name = getttyname ("/dev/pts", st.st_dev, st.st_ino, save, &dostat);
-#endif
+ name = getttyname ("/dev/pts", &st, save, &dostat);
}
else
{
@@ -202,21 +181,23 @@ ttyname (int fd)
if (!name && dostat != -1)
{
-#ifdef _STATBUF_ST_RDEV
- name = getttyname ("/dev", st.st_rdev, st.st_ino, save, &dostat);
-#else
- name = getttyname ("/dev", st.st_dev, st.st_ino, save, &dostat);
-#endif
+ name = getttyname ("/dev", &st, save, &dostat);
}
if (!name && dostat != -1)
{
dostat = 1;
-#ifdef _STATBUF_ST_RDEV
- name = getttyname ("/dev", st.st_rdev, st.st_ino, save, &dostat);
-#else
- name = getttyname ("/dev", st.st_dev, st.st_ino, save, &dostat);
-#endif
+ name = getttyname ("/dev", &st, save, &dostat);
+ }
+
+ if (!name && doispty && is_pty (&st))
+ {
+ /* We failed to figure out the TTY's name, but we can at least
+ signal that we did verify that it really is a PTY slave.
+ This happens when we have inherited the file descriptor from
+ a different mount namespace. */
+ __set_errno (ENODEV);
+ return NULL;
}
return name;
diff --git a/sysdeps/unix/sysv/linux/ttyname.h b/sysdeps/unix/sysv/linux/ttyname.h
index 2e415e4e9cc..48181330a9d 100644
--- a/sysdeps/unix/sysv/linux/ttyname.h
+++ b/sysdeps/unix/sysv/linux/ttyname.h
@@ -16,13 +16,15 @@
not, see <http://www.gnu.org/licenses/>. */
#include <unistd.h>
+#include <stdbool.h>
#include <sys/sysmacros.h>
#include <sys/types.h>
#include <sys/stat.h>
/* Return true if this is a UNIX98 pty device, as defined in
- linux/Documentation/devices.txt. */
-static inline int
+ linux/Documentation/devices.txt (on linux < 4.10) or
+ linux/Documentation/admin-guide/devices.txt (on linux >= 4.10). */
+static inline bool
is_pty (struct stat64 *sb)
{
#ifdef _STATBUF_ST_RDEV
@@ -32,3 +34,15 @@ is_pty (struct stat64 *sb)
return false;
#endif
}
+
+static inline bool
+is_mytty (const struct stat64 *mytty, const struct stat64 *maybe)
+{
+ return (maybe->st_ino == mytty->st_ino
+ && maybe->st_dev == mytty->st_dev
+#ifdef _STATBUF_ST_RDEV
+ && S_ISCHR (maybe->st_mode)
+ && maybe->st_rdev == mytty->st_rdev
+#endif
+ );
+}
diff --git a/sysdeps/unix/sysv/linux/ttyname_r.c b/sysdeps/unix/sysv/linux/ttyname_r.c
index dc863526ba7..00eefc2c5c9 100644
--- a/sysdeps/unix/sysv/linux/ttyname_r.c
+++ b/sysdeps/unix/sysv/linux/ttyname_r.c
@@ -31,12 +31,12 @@
#include "ttyname.h"
static int getttyname_r (char *buf, size_t buflen,
- dev_t mydev, ino64_t myino, int save,
- int *dostat) internal_function;
+ const struct stat64 *mytty, int save,
+ int *dostat);
static int
-internal_function attribute_compat_text_section
-getttyname_r (char *buf, size_t buflen, dev_t mydev, ino64_t myino,
+attribute_compat_text_section
+getttyname_r (char *buf, size_t buflen, const struct stat64 *mytty,
int save, int *dostat)
{
struct stat64 st;
@@ -52,7 +52,7 @@ getttyname_r (char *buf, size_t buflen, dev_t mydev, ino64_t myino,
}
while ((d = __readdir64 (dirstream)) != NULL)
- if ((d->d_fileno == myino || *dostat)
+ if ((d->d_fileno == mytty->st_ino || *dostat)
&& strcmp (d->d_name, "stdin")
&& strcmp (d->d_name, "stdout")
&& strcmp (d->d_name, "stderr"))
@@ -72,12 +72,7 @@ getttyname_r (char *buf, size_t buflen, dev_t mydev, ino64_t myino,
cp[0] = '\0';
if (__xstat64 (_STAT_VER, buf, &st) == 0
-#ifdef _STATBUF_ST_RDEV
- && S_ISCHR (st.st_mode) && st.st_rdev == mydev
-#else
- && d->d_fileno == myino && st.st_dev == mydev
-#endif
- )
+ && is_mytty (mytty, &st))
{
(void) __closedir (dirstream);
__set_errno (save);
@@ -100,6 +95,7 @@ __ttyname_r (int fd, char *buf, size_t buflen)
char procname[30];
struct stat64 st, st1;
int dostat = 0;
+ int doispty = 0;
int save = errno;
/* Test for the absolute minimal size. This makes life easier inside
@@ -151,22 +147,10 @@ __ttyname_r (int fd, char *buf, size_t buflen)
/* Verify readlink result, fall back on iterating through devices. */
if (buf[0] == '/'
&& __xstat64 (_STAT_VER, buf, &st1) == 0
-#ifdef _STATBUF_ST_RDEV
- && S_ISCHR (st1.st_mode)
- && st1.st_rdev == st.st_rdev
-#endif
- && st1.st_ino == st.st_ino
- && st1.st_dev == st.st_dev)
+ && is_mytty (&st, &st1))
return 0;
- /* If the link doesn't exist, then it points to a device in another
- * namespace.
- */
- if (is_pty (&st))
- {
- __set_errno (ENODEV);
- return ENODEV;
- }
+ doispty = 1;
}
/* Prepare the result buffer. */
@@ -175,13 +159,8 @@ __ttyname_r (int fd, char *buf, size_t buflen)
if (__xstat64 (_STAT_VER, buf, &st1) == 0 && S_ISDIR (st1.st_mode))
{
-#ifdef _STATBUF_ST_RDEV
- ret = getttyname_r (buf, buflen, st.st_rdev, st.st_ino, save,
+ ret = getttyname_r (buf, buflen, &st, save,
&dostat);
-#else
- ret = getttyname_r (buf, buflen, st.st_dev, st.st_ino, save,
- &dostat);
-#endif
}
else
{
@@ -193,26 +172,26 @@ __ttyname_r (int fd, char *buf, size_t buflen)
{
buf[sizeof ("/dev/") - 1] = '\0';
buflen += sizeof ("pts/") - 1;
-#ifdef _STATBUF_ST_RDEV
- ret = getttyname_r (buf, buflen, st.st_rdev, st.st_ino, save,
- &dostat);
-#else
- ret = getttyname_r (buf, buflen, st.st_dev, st.st_ino, save,
+ ret = getttyname_r (buf, buflen, &st, save,
&dostat);
-#endif
}
if (ret && dostat != -1)
{
buf[sizeof ("/dev/") - 1] = '\0';
dostat = 1;
-#ifdef _STATBUF_ST_RDEV
- ret = getttyname_r (buf, buflen, st.st_rdev, st.st_ino,
+ ret = getttyname_r (buf, buflen, &st,
save, &dostat);
-#else
- ret = getttyname_r (buf, buflen, st.st_dev, st.st_ino,
- save, &dostat);
-#endif
+ }
+
+ if (ret && doispty && is_pty (&st))
+ {
+ /* We failed to figure out the TTY's name, but we can at least
+ signal that we did verify that it really is a PTY slave.
+ This happens when we have inherited the file descriptor from
+ a different mount namespace. */
+ __set_errno (ENODEV);
+ return ENODEV;
}
return ret;
diff --git a/sysdeps/x86_64/dl-trampoline.h b/sysdeps/x86_64/dl-trampoline.h
index 9ddaafee17b..5fdc391d08e 100644
--- a/sysdeps/x86_64/dl-trampoline.h
+++ b/sysdeps/x86_64/dl-trampoline.h
@@ -440,8 +440,16 @@ _dl_runtime_profile:
# ifdef RESTORE_AVX
/* sizeof(La_x86_64_retval). Need extra space for 2 SSE
registers to detect if xmm0/xmm1 registers are changed
- by audit module. */
- sub $(LRV_SIZE + XMM_SIZE*2), %RSP_LP
+ by audit module. Since rsp is aligned to VEC_SIZE, we
+ need to make sure that the address of La_x86_64_retval +
+ LRV_VECTOR0_OFFSET is aligned to VEC_SIZE. */
+# define LRV_SPACE (LRV_SIZE + XMM_SIZE*2)
+# define LRV_MISALIGNED ((LRV_SIZE + LRV_VECTOR0_OFFSET) & (VEC_SIZE - 1))
+# if LRV_MISALIGNED == 0
+ sub $LRV_SPACE, %RSP_LP
+# else
+ sub $(LRV_SPACE + VEC_SIZE - LRV_MISALIGNED), %RSP_LP
+# endif
# else
sub $LRV_SIZE, %RSP_LP # sizeof(La_x86_64_retval)
# endif