diff options
author | Tulio Magno Quites Machado Filho <tuliom@linux.vnet.ibm.com> | 2018-02-02 15:18:56 -0200 |
---|---|---|
committer | Tulio Magno Quites Machado Filho <tuliom@linux.vnet.ibm.com> | 2018-02-02 15:18:56 -0200 |
commit | 400747ec4ff4c0b8bc094437c2e8cc8da42ee452 (patch) | |
tree | 6c17c1adc37ca84e8354d33cd2dde31ca004a41e | |
parent | 962a4b638fe0dbffba9de7a408eedb1a27be1096 (diff) | |
parent | bbabb868cd248763373d0db763bacd84ce27ede8 (diff) | |
download | glibc-400747ec4ff4c0b8bc094437c2e8cc8da42ee452.tar.gz glibc-400747ec4ff4c0b8bc094437c2e8cc8da42ee452.tar.xz glibc-400747ec4ff4c0b8bc094437c2e8cc8da42ee452.zip |
Merge branch 'release/2.26/master' into ibm/2.26/master
191 files changed, 5393 insertions, 912 deletions
diff --git a/ChangeLog b/ChangeLog index 812c5380f1..e6add48bf5 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 e7b62a8d46..3f2cb5915f 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 c1b6d4ba0f..7397c1882c 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 0000000000..cb4a8b2a56 --- /dev/null +++ b/include/array_length.h @@ -0,0 +1,36 @@ +/* The array_length and array_end macros. + Copyright (C) 2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <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 2f26bf56db..f0bdc838bb 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 0000000000..3a3636f2ed --- /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 dc14fae152..afd423240a 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 1d80be20d2..2c6cebc889 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 dd9f699d97..6a52c288de 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 31a58bd026..d942c6e536 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 82f473806c..51a5f4e83c 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 96acaed206..8ab67562d7 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 4fef5045b8..4aace48b14 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 3c19567a28..b09e3fe791 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 2c17c68eda..1039985ea6 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 ba26624835..5a282b8c6b 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 0000000000..48e8f1e799 --- /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 9ca6d01b8c..0b01e18106 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 dff5d3469e..e351ce9d99 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 c83b17b674..82dab056e2 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 869e926f17..e5c0bdfbeb 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 16c05c3a58..791587218b 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 06093b3d92..210a3f8a1f 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 0000000000..a306320e88 --- /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 0000000000..9c7e9a4dfe --- /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 0000000000..b0a897b0c6 --- /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 0000000000..b9be25a65b --- /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 c761c0861d..b2273ea7bc 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 9518b4a6f8..6886f4371f 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 2ece7ce575..4057e42d3c 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 2ace3fa8cc..1bda81e55e 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 43caf9bce4..b0886ba1d1 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 592f2bc856..78f2b3cde1 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 bdcd12952a..2192f38941 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 55895ace3c..91ad7c56bd 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 d2a31bed7b..6c1277bd67 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 890d672d50..56384f9b03 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 daa3083fd1..cbcbfb14e5 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 2893f2c295..6aa28fa24e 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 67442f95df..2780d9a6fe 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 fb4597c238..e55354e788 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 7b77a2cd56..450333ad38 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 9eddb1a0e9..3c3842a49b 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 0000000000..1971bf7cd7 --- /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 0000000000..75759b586c --- /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 7816978273..fd87fe2305 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 1625dcf43a..3f2a09f36f 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 b953dc1200..4c2e6c1b41 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 f65b5dd22c..6e949226fa 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 f434a8082a..c2dacbb179 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 0000000000..f69253af09 --- /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 86a81ec601..fc10c6dcb7 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 4b5f04c2cc..bc5827ed87 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 3fa0bd4ac0..6947dbaa80 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 0dfd2deb54..8922576d19 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 030f124252..6d2029e13b 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 e1cf73b6a5..ff5ee89fb0 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 f3ef551b05..6356b1af6c 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 0000000000..ba68e990f2 --- /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 28b0ee29cf..1d874df885 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 5d42c42a45..2acb9afffd 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 eedb030591..c5e00e516a 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 2992c57971..1170eafb0f 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 493d6ae962..3d2dc8b27a 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 5b5f26082e..a4a62afe0a 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 020f5720d9..0d15e78440 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 cf48614383..25edc00385 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 684055c746..356798f556 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 f5155de727..f24f6c3281 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 61d088e8cf..8ab43c4b38 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 0000000000..8eb51c439d --- /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 3c411a467b..396385729b 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 55ab2111b3..5ff5555a6a 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 48e89597f3..7505679401 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 fb6cceb065..4cee3c0c35 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 fdb2477ab9..0bbc7f9972 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 6fed8df1ea..c7795cc577 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 47c387c2b4..09c8783e4f 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 a8fe9c3565..1708d68d60 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 dbe7cc07c8..e20423c4a3 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 5672fba0f7..a685256091 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 9c8589c09c..b1135eebc6 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 2c9372cc29..09cd96290a 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 e739e739c3..8757f2da02 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 0000000000..123ba1bc3c --- /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 0000000000..b142207228 --- /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 f03ed931d6..a3e2f90535 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 7b25af3b05..fd65fc6c3a 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 67dd95e9fb..ada3c92267 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 5157680fa2..e593ec5e82 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 cfc6dd8fa8..938e7c07d6 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 135f42dab2..403569041f 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 abcc299e00..d4759a1bd1 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 c931e08421..702bef6c6e 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 0266dbc643..341805d80d 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 0000000000..f34bb059c0 --- /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 0000000000..5ab7494e70 --- /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 dc08c94518..b8c4c223fb 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 2737f05044..39d46f042a 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 14532a09f3..fb931cf22b 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 aa52ba62c5..dffa2a13d0 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 0000000000..27c7e12ba2 --- /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 c3bd884f8d..797194f79d 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 1953e5900a..aa70091adb 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 0000000000..2422939908 --- /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 450f699789..78317e2b12 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 bce6dc9170..df5fbc489a 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 e5ba231e4d..2d4a577f29 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 ea17d49391..7e67f783de 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 435b1eb733..d580c07013 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 9410251c32..e6870988e0 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 6ef5a4a468..e8e5bc2d59 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 7f033a03a7..3d888e8862 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 89a64a55c1..b8529df620 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 bec2521ffc..b24bf32fc5 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 664c809e9f..52aa2602fe 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 2e30ade9ab..c7aa903db2 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 b544dbaa42..6e845acc97 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 35fed5d9ec..964ec058c9 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 02d06310a9..c5517c0c66 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 efc0719a63..1dae148b46 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 b32dad1315..4a2975ad12 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 7cee44d0a3..61690c5e7c 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 3af16f9b54..26e864ea3e 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 3094d82e9c..1658db4b62 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 b0e9b2a232..08ec683b66 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 98c63e54c3..24b8456db9 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 2088af2f57..c65f2d7db1 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 f23bb9a5ae..29acbd283a 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 52364be365..d337163609 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 f11f8f0acd..d03f016629 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 2d16d1b9d9..40855954a8 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 af727b45f3..4257960aaa 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 161b41edf6..5c385c6934 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 c699e32b41..f352a7ad93 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 fa93fab178..fe231581e3 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 353f75e3d7..e2f544d38c 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 242da1aeca..2380560d79 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 d7d6fa8630..7886c72a77 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 cf22170b56..91f790c9e5 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 70d58dbab2..b22c1ce3dd 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 824288c90e..e6c38115d8 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 96330a5637..a88068fc86 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 eaa136b3ec..7eb282fd18 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 8d25d5b818..0de37146c3 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 48baf247f3..96ac47d777 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 958aace9f6..34aa3df0a9 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 0ba9ca02dc..1fb91dcc20 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 6975215b17..4cadbf70f9 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 4f19a44c48..194613993a 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 0000000000..1901e741eb --- /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 0000000000..c6386491db --- /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 00c313880c..4d9987c9bb 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 17809c4dd2..a1011a5062 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 20bddf6965..f51530793e 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 9931882e75..b7c07f21f9 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 0000000000..51657de2b7 --- /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 0000000000..e7369f0324 --- /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 3dc0d9d5ce..9ab8d1bfdd 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 c1deaee924..20282fb810 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 d6724948d8..9673abdf54 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 bcc2e863bf..e7d0274474 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 d6a8c04baf..89eee8584e 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 0000000000..e85fddd439 --- /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 0000000000..afefc2d098 --- /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 472763ebe8..79358e7c99 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 c947bfd8fb..5fe5dae818 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 0000000000..2ff9296fca --- /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 204795e4c0..1cb039ca17 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 134e8ee4c1..bbaae9130a 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 60472036f5..3fb00e6e2d 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 ed685de35d..a269c7c343 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 2776ba7fae..543cebcb63 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 d60cf7bd87..9a0abc6f0a 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 33a1975f5e..ace58b2468 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 965ea43c94..7a8e86831d 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 ab5f395cfd..6a49a8ba1f 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 f554a791b7..7f83a19b9a 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 dbe6a36c57..b1fe960d00 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 3b556fd450..f485de88a5 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 0000000000..e602eea455 --- /dev/null +++ b/sysdeps/unix/sysv/linux/ia64/ipc_priv.h @@ -0,0 +1,21 @@ +/* Old SysV permission definition for Linux. IA64 version. + Copyright (C) 2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <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 0000000000..dbaaa3f904 --- /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 bd8bd3843b..9fe9d9127d 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 98c2f88eb8..59292b6d79 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 499e389605..47c099183c 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 0000000000..27da21bdf1 --- /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 0000000000..6848a6d3e2 --- /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 5909cb765f..f4c955f25b 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 2e415e4e9c..48181330a9 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 dc863526ba..00eefc2c5c 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 9ddaafee17..5fdc391d08 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 |