diff options
author | Tavian Barnes | 2019-02-02 21:32:14 -0500 |
---|---|---|
committer | Tavian Barnes | 2019-02-02 21:32:14 -0500 |
commit | 586531ebc2484888c06ca7001e6756db29ba66cc (patch) | |
tree | 5864485d22357c5ed274cb4422a0c4b0fc95dad9 | |
parent | 52d06be9bab3f2432858015c32ca79d087875a36 (diff) | |
download | aur-586531ebc2484888c06ca7001e6756db29ba66cc.tar.gz |
Bump to 2.28-5
-rw-r--r-- | .SRCINFO | 22 | ||||
-rw-r--r-- | PKGBUILD | 16 | ||||
-rw-r--r-- | bz20338.patch | 114 | ||||
-rw-r--r-- | glibc-5a74abda201907cafbdabd1debf98890313ff71e.patch | 1798 |
4 files changed, 1817 insertions, 133 deletions
@@ -1,17 +1,17 @@ # Generated by mksrcinfo v8 -# Fri May 11 17:47:38 UTC 2018 +# Sun Feb 3 02:32:08 UTC 2019 pkgbase = arm-linux-gnueabihf-glibc pkgdesc = GNU C Library (arm-linux-gnueabihf) - pkgver = 2.27 - pkgrel = 3 + pkgver = 2.28 + pkgrel = 5 url = http://www.gnu.org/software/libc/ arch = any license = GPL license = LGPL - makedepends = arm-linux-gnueabihf-gcc-stage2>=8.1.0-1 + makedepends = arm-linux-gnueabihf-gcc-stage2>=8.2.1+20181127 makedepends = gperf - depends = arm-linux-gnueabihf-linux-api-headers>=4.16.1-1 - provides = arm-linux-gnueabihf-glibc-headers=2.27 + depends = arm-linux-gnueabihf-linux-api-headers>=4.17.11-1 + provides = arm-linux-gnueabihf-glibc-headers=2.28 provides = arm-linux-gnueabihf-eglibc conflicts = arm-linux-gnueabihf-glibc-headers conflicts = arm-linux-gnueabihf-eglibc @@ -19,12 +19,12 @@ pkgbase = arm-linux-gnueabihf-glibc options = !buildflags options = !strip options = staticlibs - source = https://ftp.gnu.org/gnu/glibc/glibc-2.27.tar.xz - source = https://ftp.gnu.org/gnu/glibc/glibc-2.27.tar.xz.sig - source = bz20338.patch - md5sums = 898cd5656519ffbc3a03fe811dd89e82 + source = https://ftp.gnu.org/gnu/glibc/glibc-2.28.tar.xz + source = https://ftp.gnu.org/gnu/glibc/glibc-2.28.tar.xz.sig + source = glibc-5a74abda201907cafbdabd1debf98890313ff71e.patch + md5sums = c81d2388896379997bc359d4f2084239 md5sums = SKIP - md5sums = dc0d3ad59aeaaf591b085a77de6e03e9 + md5sums = b64d9921601d1e25cca2c802f15d6dcf pkgname = arm-linux-gnueabihf-glibc @@ -7,26 +7,26 @@ _target="arm-linux-gnueabihf" pkgname=${_target}-glibc -pkgver=2.27 -pkgrel=3 +pkgver=2.28 +pkgrel=5 pkgdesc="GNU C Library (${_target})" arch=('any') url="http://www.gnu.org/software/libc/" license=(GPL LGPL) -depends=("${_target}-linux-api-headers>=4.16.1-1") -makedepends=("${_target}-gcc-stage2>=8.1.0-1" gperf) +depends=("${_target}-linux-api-headers>=4.17.11-1") +makedepends=("${_target}-gcc-stage2>=8.2.1+20181127" gperf) provides=("${_target}-glibc-headers=${pkgver}" "${_target}-eglibc") conflicts=("${_target}-glibc-headers" "${_target}-eglibc") replaces=("${_target}-glibc-headers") options=(!buildflags !strip staticlibs) -_commit=23158b08a0908f381459f273a984c6fd328363cb +_commit=5a74abda201907cafbdabd1debf98890313ff71e #source=(git+https://sourceware.org/git/glibc.git#commit=$_commit source=(https://ftp.gnu.org/gnu/glibc/glibc-$pkgver.tar.xz{,.sig} - bz20338.patch) + glibc-${_commit}.patch) validpgpkeys=(7273542B39962DF7B299931416792B4EA25340F8) # Carlos O'Donell -md5sums=('898cd5656519ffbc3a03fe811dd89e82' +md5sums=('c81d2388896379997bc359d4f2084239' 'SKIP' - 'dc0d3ad59aeaaf591b085a77de6e03e9') + 'b64d9921601d1e25cca2c802f15d6dcf') prepare() { mkdir -p glibc-build diff --git a/bz20338.patch b/bz20338.patch deleted file mode 100644 index d223e9f08882..000000000000 --- a/bz20338.patch +++ /dev/null @@ -1,114 +0,0 @@ -From 74250a7cdf106d4ca7d9506e6d5dc7c448dc3434 Mon Sep 17 00:00:00 2001 -From: David Michael <david.michael@coreos.com> -Date: Thu, 15 Dec 2016 15:22:57 -0800 -Subject: [PATCH] gshadow: Sync fgetsgent_r.c with grp/fgetgrent_r.c - - [BZ #20338] - * gshadow/fgetsgent_r.c: Include <libio/iolibio.h>. - (flockfile): New macro. - (funlockfile): Likewise. - (__fgetsgent_r): Sync with __fgetgrent_r. - * nss/nss_files/files-sgrp.c: Fix "fgetsgent_r.c" typo. ---- - gshadow/fgetsgent_r.c | 35 ++++++++++++++++++++++++----------- - nss/nss_files/files-sgrp.c | 2 +- - 2 files changed, 25 insertions(+), 12 deletions(-) - -diff --git a/gshadow/fgetsgent_r.c b/gshadow/fgetsgent_r.c -index b70f6fa..02cd33a 100644 ---- a/gshadow/fgetsgent_r.c -+++ b/gshadow/fgetsgent_r.c -@@ -20,39 +20,44 @@ - #include <gshadow.h> - #include <stdio.h> - -+#include <libio/iolibio.h> -+#define flockfile(s) _IO_flockfile (s) -+#define funlockfile(s) _IO_funlockfile (s) -+ - /* Define a line parsing function using the common code - used in the nss_files module. */ - - #define STRUCTURE sgrp - #define ENTNAME sgent --#define EXTERN_PARSER 1 -+#define EXTERN_PARSER 1 - struct sgent_data {}; - - #include <nss/nss_files/files-parse.c> - - --/* Read one shadow entry from the given stream. */ -+/* Read one entry from the given stream. */ - int - __fgetsgent_r (FILE *stream, struct sgrp *resbuf, char *buffer, size_t buflen, - struct sgrp **result) - { - char *p; -+ int parse_result; - -- _IO_flockfile (stream); -+ flockfile (stream); - do - { - buffer[buflen - 1] = '\xff'; - p = fgets_unlocked (buffer, buflen, stream); -- if (p == NULL && feof_unlocked (stream)) -+ if (__builtin_expect (p == NULL, 0) && feof_unlocked (stream)) - { -- _IO_funlockfile (stream); -+ funlockfile (stream); - *result = NULL; - __set_errno (ENOENT); - return errno; - } -- if (p == NULL || buffer[buflen - 1] != '\xff') -+ if (__builtin_expect (p == NULL, 0) || buffer[buflen - 1] != '\xff') - { -- _IO_funlockfile (stream); -+ funlockfile (stream); - *result = NULL; - __set_errno (ERANGE); - return errno; -@@ -61,13 +66,21 @@ __fgetsgent_r (FILE *stream, struct sgrp *resbuf, char *buffer, size_t buflen, - /* Skip leading blanks. */ - while (isspace (*p)) - ++p; -- } while (*p == '\0' || *p == '#' || /* Ignore empty and comment lines. */ -+ } while (*p == '\0' || *p == '#' /* Ignore empty and comment lines. */ - /* Parse the line. If it is invalid, loop to - get the next line of the file to parse. */ -- ! parse_line (buffer, (void *) resbuf, (void *) buffer, buflen, -- &errno)); -+ || ! (parse_result = parse_line (p, resbuf, -+ (void *) buffer, buflen, -+ &errno))); -+ -+ funlockfile (stream); - -- _IO_funlockfile (stream); -+ if (__builtin_expect (parse_result, 0) == -1) -+ { -+ /* The parser ran out of space. */ -+ *result = NULL; -+ return errno; -+ } - - *result = resbuf; - return 0; -diff --git a/nss/nss_files/files-sgrp.c b/nss/nss_files/files-sgrp.c -index 15dc659..05c3805 100644 ---- a/nss/nss_files/files-sgrp.c -+++ b/nss/nss_files/files-sgrp.c -@@ -23,7 +23,7 @@ - #define DATABASE "gshadow" - struct sgent_data {}; - --/* Our parser function is already defined in sgetspent_r.c, so use that -+/* Our parser function is already defined in sgetsgent_r.c, so use that - to parse lines from the database file. */ - #define EXTERN_PARSER - #include "files-parse.c" --- -2.7.4 - diff --git a/glibc-5a74abda201907cafbdabd1debf98890313ff71e.patch b/glibc-5a74abda201907cafbdabd1debf98890313ff71e.patch new file mode 100644 index 000000000000..a80eacfd2c78 --- /dev/null +++ b/glibc-5a74abda201907cafbdabd1debf98890313ff71e.patch @@ -0,0 +1,1798 @@ +diff --git a/ChangeLog b/ChangeLog +index 08b42bd2f5..7f4c6a48bc 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,159 @@ ++2018-10-09 H.J. Lu <hongjiu.lu@intel.com> ++ ++ [BZ #23716] ++ * sysdeps/i386/dl-cet.c: Removed. ++ * sysdeps/i386/dl-machine.h (_dl_runtime_resolve_shstk): New ++ prototype. ++ (_dl_runtime_profile_shstk): Likewise. ++ (elf_machine_runtime_setup): Use _dl_runtime_profile_shstk or ++ _dl_runtime_resolve_shstk if SHSTK is enabled by kernel. ++ ++2018-10-09 Rafal Luzynski <digitalfreak@lingonborough.com> ++ ++ [BZ #20209] ++ * localedata/locales/kl_GL: (abday): Fix spelling of Sun (Sunday), ++ should be "sap" rather than "sab". ++ (day): Fix spelling of Sunday, should be "sapaat" rather than ++ "sabaat". ++ ++2018-09-28 Adhemerval Zanella <adhemerval.zanella@linaro.org> ++ ++ [BZ #23579] ++ * misc/tst-preadvwritev2-common.c (do_test_with_invalid_fd, ++ do_test_with_invalid_iov): New tests. ++ * misc/tst-preadvwritev2.c, misc/tst-preadvwritev64v2.c (do_test): ++ Call do_test_with_invalid_fd and do_test_with_invalid_iov. ++ * sysdeps/unix/sysv/linux/preadv2.c (preadv2): Use fallback code iff ++ errno is ENOSYS. ++ * sysdeps/unix/sysv/linux/preadv64v2.c (preadv64v2): Likewise. ++ * sysdeps/unix/sysv/linux/pwritev2.c (pwritev2): Likewise. ++ * sysdeps/unix/sysv/linux/pwritev64v2.c (pwritev64v2): Likewise. ++ * NEWS: Add bug fixed. ++ ++2018-09-27 Andreas Schwab <schwab@suse.de> ++ ++ [BZ #23717] ++ * stdlib/tst-setcontext9.c (f1a): Make st2 static. ++ (do_test): Make st1 static. ++ ++2018-09-21 H.J. Lu <hongjiu.lu@intel.com> ++ Xuepeng Guo <xuepeng.guo@intel.com> ++ ++ [BZ #23606] ++ * sysdeps/i386/start.S: Include <sysdep.h> ++ (_start): Use ENTRY/END to insert ENDBR32 at entry when CET is ++ enabled. Add cfi_undefined (eip). ++ ++2018-09-19 Wilco Dijkstra <wdijkstr@arm.com> ++ ++ [BZ #23637] ++ * string/test-strstr.c (pr23637): New function. ++ (test_main): Add tests with longer needles. ++ * string/strcasestr.c (AVAILABLE): Fix readahead distance. ++ * string/strstr.c (AVAILABLE): Likewise. ++ ++2018-09-19 Carlos O'Donell <carlos@redhat.com> ++ ++ * stdlib/tst-setcontext9.c (f1): Rename to... ++ (f1a): ... this. ++ (f1b): New function implementing lower half of f1 in alternate stack. ++ ++2018-09-20 Florian Weimer <fweimer@redhat.com> ++ ++ * misc/tst-gethostid.c: New file. ++ * misc/Makefile [$(build-shared)] (tests): Add tst-gethostid. ++ (tst-gethostid): Link with -ldl. ++ ++2018-09-20 Mingli Yu <Mingli.Yu@windriver.com> ++ ++ * sysdeps/unix/sysv/linux/gethostid.c (gethostid): Check for NULL ++ value from gethostbyname_r. ++ ++2018-09-06 Stefan Liebler <stli@linux.ibm.com> ++ ++ * sysdeps/unix/sysv/linux/spawni.c (maybe_script_execute): ++ Increment size of new_argv by one. ++ ++2018-08-28 Florian Weimer <fweimer@redhat.com> ++ ++ [BZ #23578] ++ * posix/tst-regcomp-truncated.c: New file. ++ * posix/Makefile (tests): Add it. ++ (tst-regcomp-truncated.out): Depend on generated locales. ++ ++2018-08-25 Paul Eggert <eggert@cs.ucla.edu> ++ ++ [BZ #23578] ++ regex: fix uninitialized memory access ++ I introduced this bug into gnulib in commit ++ 8335a4d6c7b4448cd0bcb6d0bebf1d456bcfdb17 dated 2006-04-10; ++ eventually it was merged into glibc. The bug was found by ++ project-repo <bugs@feusi.co> and reported here: ++ https://lists.gnu.org/r/sed-devel/2018-08/msg00017.html ++ Diagnosis and draft fix reported by Assaf Gordon here: ++ https://lists.gnu.org/r/bug-gnulib/2018-08/msg00071.html ++ https://lists.gnu.org/r/bug-gnulib/2018-08/msg00142.html ++ * posix/regex_internal.c (build_wcs_upper_buffer): ++ Fix bug when mbrtowc returns 0. ++ ++2018-08-27 Martin Kuchta <martin.kuchta@netapp.com> ++ Torvald Riegel <triegel@redhat.com> ++ ++ [BZ #23538] ++ * nptl/pthread_cond_common.c (__condvar_quiesce_and_switch_g1): ++ Update r to include the set wake-request flag if waiters are ++ remaining after spinning. ++ ++2018-08-03 DJ Delorie <dj@redhat.com> ++ ++ * sysdeps/riscv/rvf/math_private.h (libc_feholdexcept_setround_riscv): ++ Move libc_fesetround_riscv after libc_feholdexcept_riscv. ++ ++ * sysdeps/riscv/rv64/rvd/libm-test-ulps: Update. ++ ++2018-08-14 Florian Weimer <fweimer@redhat.com> ++ ++ [BZ #23521] ++ [BZ #23522] ++ * nss/nss_files/files-alias.c (get_next_alias): During :include: ++ processing, bail out if no room, and close the stream before ++ returning ERANGE. ++ * nss/Makefile (tests): Add tst-nss-files-alias-leak. ++ (tst-nss-files-alias-leak): Link with libdl. ++ (tst-nss-files-alias-leak.out): Depend on nss_files. ++ ++ * nss/tst-nss-files-alias-leak.c: New file. ++ ++2018-08-14 Florian Weimer <fweimer@redhat.com> ++ ++ * nscd/nscd_conf.c (nscd_parse_file): Deallocate old storage for ++ server_user, stat_user. ++ ++2018-08-13 Florian Weimer <fweimer@redhat.com> ++ ++ * misc/error.c (error): Add missing va_end call. ++ (error_at_line): Likewise. ++ ++2018-08-10 Florian Weimer <fweimer@redhat.com> ++ ++ [BZ #23497] ++ * sysdeps/unix/sysv/linux/getdents64.c (handle_overflow): New ++ function. ++ (__old_getdents64): Use getdents64. Convert entries without ++ moving them. ++ * sysdeps/unix/sysv/linux/tst-readdir64-compat.c: New file. ++ * sysdeps/unix/sysv/linux/Makefile (tests-internal): Add ++ tst-readdir64-compat. ++ ++2018-08-08 Samuel Thibault <samuel.thibault@ens-lyon.org> ++ ++ * htl/Versions (__pthread_getspecific, __pthread_setspecific): Add ++ symbols. ++ * sysdeps/htl/pthreadP.h [IS_IN (libpthread)] (__pthread_getspecific, ++ __pthread_setspecific): Add hidden proto. ++ * sysdeps/htl/pt-getspecific.c (__pthread_getspecific): Add hidden def. ++ * sysdeps/htl/pt-setspecific.c (__pthread_setspecific): Add hidden def. ++ + 2018-08-01 Carlos O'Donel <carlos@redhat.com> + + * version.h (RELEASE): Set to "stable". +diff --git a/NEWS b/NEWS +index 154ab22d7c..594cecfc75 100644 +--- a/NEWS ++++ b/NEWS +@@ -5,6 +5,21 @@ See the end for copying conditions. + Please send GNU C library bug reports via <https://sourceware.org/bugzilla/> + using `glibc' in the "product" field. + ++Version 2.28.1 ++ ++The following bugs are resolved with this release: ++ ++ [20209] localedata: Spelling mistake for Sunday in Greenlandic kl_GL ++ [23497] readdir64@GLIBC_2.1 cannot parse the kernel directory stream ++ [23521] nss_files aliases database file stream leak ++ [23538] pthread_cond_broadcast: Fix waiters-after-spinning case ++ [23578] regex: Fix memory overread in re_compile_pattern ++ [23579] libc: Errors misreported in preadv2 ++ [23606] Missing ENDBR32 in sysdeps/i386/start.S ++ [23679] gethostid: Missing NULL check for gethostbyname_r result ++ [23717] Fix stack overflow in stdlib/tst-setcontext9 ++ ++ + Version 2.28 + + Major new features: +diff --git a/htl/Versions b/htl/Versions +index 6a63a1b8a1..c5a616da10 100644 +--- a/htl/Versions ++++ b/htl/Versions +@@ -150,6 +150,8 @@ libpthread { + __cthread_keycreate; + __cthread_getspecific; + __cthread_setspecific; ++ __pthread_getspecific; ++ __pthread_setspecific; + __pthread_getattr_np; + __pthread_attr_getstack; + } +diff --git a/localedata/locales/kl_GL b/localedata/locales/kl_GL +index 5ab14a31aa..5723ce7dcf 100644 +--- a/localedata/locales/kl_GL ++++ b/localedata/locales/kl_GL +@@ -70,11 +70,11 @@ copy "da_DK" + END LC_NUMERIC + + LC_TIME +-abday "sab";"ata";/ ++abday "sap";"ata";/ + "mar";"pin";/ + "sis";"tal";/ + "arf" +-day "sabaat";/ ++day "sapaat";/ + "ataasinngorneq";/ + "marlunngorneq";/ + "pingasunngorneq";/ +diff --git a/misc/Makefile b/misc/Makefile +index b7be2bc19a..c9f81515ac 100644 +--- a/misc/Makefile ++++ b/misc/Makefile +@@ -86,6 +86,11 @@ tests := tst-dirname tst-tsearch tst-fdset tst-efgcvt tst-mntent tst-hsearch \ + tst-preadvwritev tst-preadvwritev64 tst-makedev tst-empty \ + tst-preadvwritev2 tst-preadvwritev64v2 + ++# Tests which need libdl. ++ifeq (yes,$(build-shared)) ++tests += tst-gethostid ++endif ++ + tests-internal := tst-atomic tst-atomic-long tst-allocate_once + tests-static := tst-empty + +@@ -145,3 +150,5 @@ tst-allocate_once-ENV = MALLOC_TRACE=$(objpfx)tst-allocate_once.mtrace + $(objpfx)tst-allocate_once-mem.out: $(objpfx)tst-allocate_once.out + $(common-objpfx)malloc/mtrace $(objpfx)tst-allocate_once.mtrace > $@; \ + $(evaluate-test) ++ ++$(objpfx)tst-gethostid: $(libdl) +diff --git a/misc/error.c b/misc/error.c +index b4e8b6c938..03378e2f2a 100644 +--- a/misc/error.c ++++ b/misc/error.c +@@ -319,6 +319,7 @@ error (int status, int errnum, const char *message, ...) + + va_start (args, message); + error_tail (status, errnum, message, args); ++ va_end (args); + + #ifdef _LIBC + _IO_funlockfile (stderr); +@@ -390,6 +391,7 @@ error_at_line (int status, int errnum, const char *file_name, + + va_start (args, message); + error_tail (status, errnum, message, args); ++ va_end (args); + + #ifdef _LIBC + _IO_funlockfile (stderr); +diff --git a/misc/tst-gethostid.c b/misc/tst-gethostid.c +new file mode 100644 +index 0000000000..1490aaf3f5 +--- /dev/null ++++ b/misc/tst-gethostid.c +@@ -0,0 +1,108 @@ ++/* Basic test for gethostid. ++ Copyright (C) 2018 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ <http://www.gnu.org/licenses/>. */ ++ ++#include <gnu/lib-names.h> ++#include <nss.h> ++#include <stdio.h> ++#include <stdlib.h> ++#include <string.h> ++#include <support/namespace.h> ++#include <support/support.h> ++#include <support/temp_file.h> ++#include <support/xdlfcn.h> ++#include <support/xstdio.h> ++#include <support/xunistd.h> ++#include <unistd.h> ++ ++/* Initial test is run outside a chroot, to increase the likelihood of ++ success. */ ++static void ++outside_chroot (void *closure) ++{ ++ long id = gethostid (); ++ printf ("info: host ID outside chroot: 0x%lx\n", id); ++} ++ ++/* The same, but this time perform a chroot operation. */ ++static void ++in_chroot (void *closure) ++{ ++ const char *chroot_path = closure; ++ xchroot (chroot_path); ++ long id = gethostid (); ++ printf ("info: host ID in chroot: 0x%lx\n", id); ++} ++ ++static int ++do_test (void) ++{ ++ support_isolate_in_subprocess (outside_chroot, NULL); ++ ++ /* Now run the test inside a chroot. */ ++ support_become_root (); ++ if (!support_can_chroot ()) ++ /* Cannot perform further tests. */ ++ return 0; ++ ++ /* Only use nss_files. */ ++ __nss_configure_lookup ("hosts", "files"); ++ ++ /* Load the DSO outside of the chroot. */ ++ xdlopen (LIBNSS_FILES_SO, RTLD_LAZY); ++ ++ char *chroot_dir = support_create_temp_directory ("tst-gethostid-"); ++ support_isolate_in_subprocess (in_chroot, chroot_dir); ++ ++ /* Tests with /etc/hosts in the chroot. */ ++ { ++ char *path = xasprintf ("%s/etc", chroot_dir); ++ add_temp_file (path); ++ xmkdir (path, 0777); ++ free (path); ++ path = xasprintf ("%s/etc/hosts", chroot_dir); ++ add_temp_file (path); ++ ++ FILE *fp = xfopen (path, "w"); ++ xfclose (fp); ++ printf ("info: chroot test with an empty /etc/hosts file\n"); ++ support_isolate_in_subprocess (in_chroot, chroot_dir); ++ ++ char hostname[1024]; ++ int ret = gethostname (hostname, sizeof (hostname)); ++ if (ret < 0) ++ printf ("warning: invalid result from gethostname: %d\n", ret); ++ else if (strlen (hostname) == 0) ++ puts ("warning: gethostname returned empty string"); ++ else ++ { ++ printf ("info: chroot test with IPv6 address in /etc/hosts for: %s\n", ++ hostname); ++ fp = xfopen (path, "w"); ++ /* Use an IPv6 address to induce another lookup failure. */ ++ fprintf (fp, "2001:db8::1 %s\n", hostname); ++ xfclose (fp); ++ support_isolate_in_subprocess (in_chroot, chroot_dir); ++ } ++ free (path); ++ } ++ free (chroot_dir); ++ ++ return 0; ++} ++ ++#include <support/test-driver.c> +diff --git a/misc/tst-preadvwritev2-common.c b/misc/tst-preadvwritev2-common.c +index f889a21544..50b9da3fea 100644 +--- a/misc/tst-preadvwritev2-common.c ++++ b/misc/tst-preadvwritev2-common.c +@@ -19,9 +19,6 @@ + #include <limits.h> + #include <support/check.h> + +-static void +-do_test_with_invalid_flags (void) +-{ + #ifndef RWF_HIPRI + # define RWF_HIPRI 0 + #endif +@@ -39,6 +36,68 @@ do_test_with_invalid_flags (void) + #endif + #define RWF_SUPPORTED (RWF_HIPRI | RWF_DSYNC | RWF_SYNC | RWF_NOWAIT \ + | RWF_APPEND) ++ ++static void ++do_test_with_invalid_fd (void) ++{ ++ char buf[256]; ++ struct iovec iov = { buf, sizeof buf }; ++ ++ /* Check with flag being 0 to use the fallback code which calls pwritev ++ or writev. */ ++ TEST_VERIFY (preadv2 (-1, &iov, 1, -1, 0) == -1); ++ TEST_COMPARE (errno, EBADF); ++ TEST_VERIFY (pwritev2 (-1, &iov, 1, -1, 0) == -1); ++ TEST_COMPARE (errno, EBADF); ++ ++ /* Same tests as before but with flags being different than 0. Since ++ there is no emulation for any flag value, fallback code returns ++ ENOTSUP. This is different running on a kernel with preadv2/pwritev2 ++ support, where EBADF is returned). */ ++ TEST_VERIFY (preadv2 (-1, &iov, 1, 0, RWF_HIPRI) == -1); ++ TEST_VERIFY (errno == EBADF || errno == ENOTSUP); ++ TEST_VERIFY (pwritev2 (-1, &iov, 1, 0, RWF_HIPRI) == -1); ++ TEST_VERIFY (errno == EBADF || errno == ENOTSUP); ++} ++ ++static void ++do_test_with_invalid_iov (void) ++{ ++ { ++ char buf[256]; ++ struct iovec iov; ++ ++ iov.iov_base = buf; ++ iov.iov_len = (size_t)SSIZE_MAX + 1; ++ ++ TEST_VERIFY (preadv2 (temp_fd, &iov, 1, 0, 0) == -1); ++ TEST_COMPARE (errno, EINVAL); ++ TEST_VERIFY (pwritev2 (temp_fd, &iov, 1, 0, 0) == -1); ++ TEST_COMPARE (errno, EINVAL); ++ ++ /* Same as for invalid file descriptor tests, emulation fallback ++ first checks for flag value and return ENOTSUP. */ ++ TEST_VERIFY (preadv2 (temp_fd, &iov, 1, 0, RWF_HIPRI) == -1); ++ TEST_VERIFY (errno == EINVAL || errno == ENOTSUP); ++ TEST_VERIFY (pwritev2 (temp_fd, &iov, 1, 0, RWF_HIPRI) == -1); ++ TEST_VERIFY (errno == EINVAL || errno == ENOTSUP); ++ } ++ ++ { ++ /* An invalid iovec buffer should trigger an invalid memory access ++ or an error (Linux for instance returns EFAULT). */ ++ struct iovec iov[IOV_MAX+1] = { 0 }; ++ ++ TEST_VERIFY (preadv2 (temp_fd, iov, IOV_MAX + 1, 0, RWF_HIPRI) == -1); ++ TEST_VERIFY (errno == EINVAL || errno == ENOTSUP); ++ TEST_VERIFY (pwritev2 (temp_fd, iov, IOV_MAX + 1, 0, RWF_HIPRI) == -1); ++ TEST_VERIFY (errno == EINVAL || errno == ENOTSUP); ++ } ++} ++ ++static void ++do_test_with_invalid_flags (void) ++{ + /* Set the next bit from the mask of all supported flags. */ + int invalid_flag = RWF_SUPPORTED != 0 ? __builtin_clz (RWF_SUPPORTED) : 2; + invalid_flag = 0x1 << ((sizeof (int) * CHAR_BIT) - invalid_flag); +diff --git a/misc/tst-preadvwritev2.c b/misc/tst-preadvwritev2.c +index be22802dbe..cb58cbe41e 100644 +--- a/misc/tst-preadvwritev2.c ++++ b/misc/tst-preadvwritev2.c +@@ -30,6 +30,8 @@ do_test (void) + { + do_test_with_invalid_flags (); + do_test_without_offset (); ++ do_test_with_invalid_fd (); ++ do_test_with_invalid_iov (); + + return do_test_with_offset (0); + } +diff --git a/misc/tst-preadvwritev64v2.c b/misc/tst-preadvwritev64v2.c +index 8d3cc32b28..6a9de54c78 100644 +--- a/misc/tst-preadvwritev64v2.c ++++ b/misc/tst-preadvwritev64v2.c +@@ -32,6 +32,8 @@ do_test (void) + { + do_test_with_invalid_flags (); + do_test_without_offset (); ++ do_test_with_invalid_fd (); ++ do_test_with_invalid_iov (); + + return do_test_with_offset (0); + } +diff --git a/nptl/pthread_cond_common.c b/nptl/pthread_cond_common.c +index 8e425eb01e..479e54febb 100644 +--- a/nptl/pthread_cond_common.c ++++ b/nptl/pthread_cond_common.c +@@ -405,8 +405,12 @@ __condvar_quiesce_and_switch_g1 (pthread_cond_t *cond, uint64_t wseq, + { + /* There is still a waiter after spinning. Set the wake-request + flag and block. Relaxed MO is fine because this is just about +- this futex word. */ +- r = atomic_fetch_or_relaxed (cond->__data.__g_refs + g1, 1); ++ this futex word. ++ ++ Update r to include the set wake-request flag so that the upcoming ++ futex_wait only blocks if the flag is still set (otherwise, we'd ++ violate the basic client-side futex protocol). */ ++ r = atomic_fetch_or_relaxed (cond->__data.__g_refs + g1, 1) | 1; + + if ((r >> 1) > 0) + futex_wait_simple (cond->__data.__g_refs + g1, r, private); +diff --git a/nscd/nscd_conf.c b/nscd/nscd_conf.c +index 265a02434d..7293b795b6 100644 +--- a/nscd/nscd_conf.c ++++ b/nscd/nscd_conf.c +@@ -190,7 +190,10 @@ nscd_parse_file (const char *fname, struct database_dyn dbs[lastdb]) + if (!arg1) + error (0, 0, _("Must specify user name for server-user option")); + else +- server_user = xstrdup (arg1); ++ { ++ free ((char *) server_user); ++ server_user = xstrdup (arg1); ++ } + } + else if (strcmp (entry, "stat-user") == 0) + { +@@ -198,6 +201,7 @@ nscd_parse_file (const char *fname, struct database_dyn dbs[lastdb]) + error (0, 0, _("Must specify user name for stat-user option")); + else + { ++ free ((char *) stat_user); + stat_user = xstrdup (arg1); + + struct passwd *pw = getpwnam (stat_user); +diff --git a/nss/Makefile b/nss/Makefile +index 66fac7f5b8..5209fc0456 100644 +--- a/nss/Makefile ++++ b/nss/Makefile +@@ -65,6 +65,7 @@ ifeq (yes,$(build-shared)) + tests += tst-nss-files-hosts-erange + tests += tst-nss-files-hosts-multi + tests += tst-nss-files-hosts-getent ++tests += tst-nss-files-alias-leak + endif + + # If we have a thread library then we can test cancellation against +@@ -171,3 +172,5 @@ endif + $(objpfx)tst-nss-files-hosts-erange: $(libdl) + $(objpfx)tst-nss-files-hosts-multi: $(libdl) + $(objpfx)tst-nss-files-hosts-getent: $(libdl) ++$(objpfx)tst-nss-files-alias-leak: $(libdl) ++$(objpfx)tst-nss-files-alias-leak.out: $(objpfx)/libnss_files.so +diff --git a/nss/nss_files/files-alias.c b/nss/nss_files/files-alias.c +index cfd34b66b9..35b0bfc5d2 100644 +--- a/nss/nss_files/files-alias.c ++++ b/nss/nss_files/files-alias.c +@@ -221,6 +221,13 @@ get_next_alias (FILE *stream, const char *match, struct aliasent *result, + { + while (! feof_unlocked (listfile)) + { ++ if (room_left < 2) ++ { ++ free (old_line); ++ fclose (listfile); ++ goto no_more_room; ++ } ++ + first_unused[room_left - 1] = '\xff'; + line = fgets_unlocked (first_unused, room_left, + listfile); +@@ -229,6 +236,7 @@ get_next_alias (FILE *stream, const char *match, struct aliasent *result, + if (first_unused[room_left - 1] != '\xff') + { + free (old_line); ++ fclose (listfile); + goto no_more_room; + } + +@@ -256,6 +264,7 @@ get_next_alias (FILE *stream, const char *match, struct aliasent *result, + + __alignof__ (char *))) + { + free (old_line); ++ fclose (listfile); + goto no_more_room; + } + room_left -= ((first_unused - cp) +diff --git a/nss/tst-nss-files-alias-leak.c b/nss/tst-nss-files-alias-leak.c +new file mode 100644 +index 0000000000..26d38e2dba +--- /dev/null ++++ b/nss/tst-nss-files-alias-leak.c +@@ -0,0 +1,237 @@ ++/* Check for file descriptor leak in alias :include: processing (bug 23521). ++ Copyright (C) 2018 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ <http://www.gnu.org/licenses/>. */ ++ ++#include <aliases.h> ++#include <array_length.h> ++#include <dlfcn.h> ++#include <errno.h> ++#include <gnu/lib-names.h> ++#include <nss.h> ++#include <stdlib.h> ++#include <string.h> ++#include <support/check.h> ++#include <support/namespace.h> ++#include <support/support.h> ++#include <support/temp_file.h> ++#include <support/test-driver.h> ++#include <support/xstdio.h> ++#include <support/xunistd.h> ++ ++static struct support_chroot *chroot_env; ++ ++/* Number of the aliases for the "many" user. This must be large ++ enough to trigger reallocation for the pointer array, but result in ++ answers below the maximum size tried in do_test. */ ++enum { many_aliases = 30 }; ++ ++static void ++prepare (int argc, char **argv) ++{ ++ chroot_env = support_chroot_create ++ ((struct support_chroot_configuration) { } ); ++ ++ char *path = xasprintf ("%s/etc/aliases", chroot_env->path_chroot); ++ add_temp_file (path); ++ support_write_file_string ++ (path, ++ "user1: :include:/etc/aliases.user1\n" ++ "user2: :include:/etc/aliases.user2\n" ++ "comment: comment1, :include:/etc/aliases.comment\n" ++ "many: :include:/etc/aliases.many\n"); ++ free (path); ++ ++ path = xasprintf ("%s/etc/aliases.user1", chroot_env->path_chroot); ++ add_temp_file (path); ++ support_write_file_string (path, "alias1\n"); ++ free (path); ++ ++ path = xasprintf ("%s/etc/aliases.user2", chroot_env->path_chroot); ++ add_temp_file (path); ++ support_write_file_string (path, "alias1a, alias2\n"); ++ free (path); ++ ++ path = xasprintf ("%s/etc/aliases.comment", chroot_env->path_chroot); ++ add_temp_file (path); ++ support_write_file_string ++ (path, ++ /* The line must be longer than the line with the :include: ++ directive in /etc/aliases. */ ++ "# Long line. ##############################################\n" ++ "comment2\n"); ++ free (path); ++ ++ path = xasprintf ("%s/etc/aliases.many", chroot_env->path_chroot); ++ add_temp_file (path); ++ FILE *fp = xfopen (path, "w"); ++ for (int i = 0; i < many_aliases; ++i) ++ fprintf (fp, "a%d\n", i); ++ TEST_VERIFY_EXIT (! ferror (fp)); ++ xfclose (fp); ++ free (path); ++} ++ ++/* The names of the users to test. */ ++static const char *users[] = { "user1", "user2", "comment", "many" }; ++ ++static void ++check_aliases (int id, const struct aliasent *e) ++{ ++ TEST_VERIFY_EXIT (id >= 0 || id < array_length (users)); ++ const char *name = users[id]; ++ TEST_COMPARE_BLOB (e->alias_name, strlen (e->alias_name), ++ name, strlen (name)); ++ ++ switch (id) ++ { ++ case 0: ++ TEST_COMPARE (e->alias_members_len, 1); ++ TEST_COMPARE_BLOB (e->alias_members[0], strlen (e->alias_members[0]), ++ "alias1", strlen ("alias1")); ++ break; ++ ++ case 1: ++ TEST_COMPARE (e->alias_members_len, 2); ++ TEST_COMPARE_BLOB (e->alias_members[0], strlen (e->alias_members[0]), ++ "alias1a", strlen ("alias1a")); ++ TEST_COMPARE_BLOB (e->alias_members[1], strlen (e->alias_members[1]), ++ "alias2", strlen ("alias2")); ++ break; ++ ++ case 2: ++ TEST_COMPARE (e->alias_members_len, 2); ++ TEST_COMPARE_BLOB (e->alias_members[0], strlen (e->alias_members[0]), ++ "comment1", strlen ("comment1")); ++ TEST_COMPARE_BLOB (e->alias_members[1], strlen (e->alias_members[1]), ++ "comment2", strlen ("comment2")); ++ break; ++ ++ case 3: ++ TEST_COMPARE (e->alias_members_len, many_aliases); ++ for (int i = 0; i < e->alias_members_len; ++i) ++ { ++ char alias[30]; ++ int len = snprintf (alias, sizeof (alias), "a%d", i); ++ TEST_VERIFY_EXIT (len > 0); ++ TEST_COMPARE_BLOB (e->alias_members[i], strlen (e->alias_members[i]), ++ alias, len); ++ } ++ break; ++ } ++} ++ ++static int ++do_test (void) ++{ ++ /* Make sure we don't try to load the module in the chroot. */ ++ if (dlopen (LIBNSS_FILES_SO, RTLD_NOW) == NULL) ++ FAIL_EXIT1 ("could not load " LIBNSS_FILES_SO ": %s", dlerror ()); ++ ++ /* Some of these descriptors will become unavailable if there is a ++ file descriptor leak. 10 is chosen somewhat arbitrarily. The ++ array must be longer than the number of files opened by nss_files ++ at the same time (currently that number is 2). */ ++ int next_descriptors[10]; ++ for (size_t i = 0; i < array_length (next_descriptors); ++i) ++ { ++ next_descriptors[i] = dup (0); ++ TEST_VERIFY_EXIT (next_descriptors[i] > 0); ++ } ++ for (size_t i = 0; i < array_length (next_descriptors); ++i) ++ xclose (next_descriptors[i]); ++ ++ support_become_root (); ++ if (!support_can_chroot ()) ++ return EXIT_UNSUPPORTED; ++ ++ __nss_configure_lookup ("aliases", "files"); ++ ++ xchroot (chroot_env->path_chroot); ++ ++ /* Attempt various buffer sizes. If the operation succeeds, we ++ expect correct data. */ ++ for (int id = 0; id < array_length (users); ++id) ++ { ++ bool found = false; ++ for (size_t size = 1; size <= 1000; ++size) ++ { ++ void *buffer = malloc (size); ++ struct aliasent result; ++ struct aliasent *res; ++ errno = EINVAL; ++ int ret = getaliasbyname_r (users[id], &result, buffer, size, &res); ++ if (ret == 0) ++ { ++ if (res != NULL) ++ { ++ found = true; ++ check_aliases (id, res); ++ } ++ else ++ { ++ support_record_failure (); ++ printf ("error: failed lookup for user \"%s\", size %zu\n", ++ users[id], size); ++ } ++ } ++ else if (ret != ERANGE) ++ { ++ support_record_failure (); ++ printf ("error: invalid return code %d (user \%s\", size %zu)\n", ++ ret, users[id], size); ++ } ++ free (buffer); ++ ++ /* Make sure that we did not have a file descriptor leak. */ ++ for (size_t i = 0; i < array_length (next_descriptors); ++i) ++ { ++ int new_fd = dup (0); ++ if (new_fd != next_descriptors[i]) ++ { ++ support_record_failure (); ++ printf ("error: descriptor %d at index %zu leaked" ++ " (user \"%s\", size %zu)\n", ++ next_descriptors[i], i, users[id], size); ++ ++ /* Close unexpected descriptor, the leak probing ++ descriptors, and the leaked descriptor ++ next_descriptors[i]. */ ++ xclose (new_fd); ++ for (size_t j = 0; j <= i; ++j) ++ xclose (next_descriptors[j]); ++ goto next_size; ++ } ++ } ++ for (size_t i = 0; i < array_length (next_descriptors); ++i) ++ xclose (next_descriptors[i]); ++ ++ next_size: ++ ; ++ } ++ if (!found) ++ { ++ support_record_failure (); ++ printf ("error: user %s not found\n", users[id]); ++ } ++ } ++ ++ support_chroot_free (chroot_env); ++ return 0; ++} ++ ++#define PREPARE prepare ++#include <support/test-driver.c> +diff --git a/posix/Makefile b/posix/Makefile +index 00c62841a2..83162123f9 100644 +--- a/posix/Makefile ++++ b/posix/Makefile +@@ -96,7 +96,7 @@ tests := test-errno tstgetopt testfnm runtests runptests \ + tst-posix_fadvise tst-posix_fadvise64 \ + tst-sysconf-empty-chroot tst-glob_symlinks tst-fexecve \ + tst-glob-tilde test-ssize-max tst-spawn4 bug-regex37 \ +- bug-regex38 ++ bug-regex38 tst-regcomp-truncated + tests-internal := bug-regex5 bug-regex20 bug-regex33 \ + tst-rfc3484 tst-rfc3484-2 tst-rfc3484-3 \ + tst-glob_lstat_compat tst-spawn4-compat +@@ -194,6 +194,7 @@ $(objpfx)tst-regex2.out: $(gen-locales) + $(objpfx)tst-regexloc.out: $(gen-locales) + $(objpfx)tst-rxspencer.out: $(gen-locales) + $(objpfx)tst-rxspencer-no-utf8.out: $(gen-locales) ++$(objpfx)tst-regcomp-truncated.out: $(gen-locales) + endif + + # If we will use the generic uname implementation, we must figure out what +diff --git a/posix/regex_internal.c b/posix/regex_internal.c +index 7f0083b918..b10588f1cc 100644 +--- a/posix/regex_internal.c ++++ b/posix/regex_internal.c +@@ -317,7 +317,7 @@ build_wcs_upper_buffer (re_string_t *pstr) + mbclen = __mbrtowc (&wc, + ((const char *) pstr->raw_mbs + pstr->raw_mbs_idx + + byte_idx), remain_len, &pstr->cur_state); +- if (BE (mbclen < (size_t) -2, 1)) ++ if (BE (0 < mbclen && mbclen < (size_t) -2, 1)) + { + wchar_t wcu = __towupper (wc); + if (wcu != wc) +@@ -386,7 +386,7 @@ build_wcs_upper_buffer (re_string_t *pstr) + else + p = (const char *) pstr->raw_mbs + pstr->raw_mbs_idx + src_idx; + mbclen = __mbrtowc (&wc, p, remain_len, &pstr->cur_state); +- if (BE (mbclen < (size_t) -2, 1)) ++ if (BE (0 < mbclen && mbclen < (size_t) -2, 1)) + { + wchar_t wcu = __towupper (wc); + if (wcu != wc) +diff --git a/posix/tst-regcomp-truncated.c b/posix/tst-regcomp-truncated.c +new file mode 100644 +index 0000000000..a4a1581bbc +--- /dev/null ++++ b/posix/tst-regcomp-truncated.c +@@ -0,0 +1,191 @@ ++/* Test compilation of truncated regular expressions. ++ Copyright (C) 2018 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ <http://www.gnu.org/licenses/>. */ ++ ++/* This test constructs various patterns in an attempt to trigger ++ over-reading the regular expression compiler, such as bug ++ 23578. */ ++ ++#include <array_length.h> ++#include <errno.h> ++#include <locale.h> ++#include <regex.h> ++#include <stdio.h> ++#include <stdlib.h> ++#include <string.h> ++#include <support/check.h> ++#include <support/next_to_fault.h> ++#include <support/support.h> ++#include <support/test-driver.h> ++#include <wchar.h> ++ ++/* Locales to test. */ ++static const char locales[][17] = ++ { ++ "C", ++ "en_US.UTF-8", ++ "de_DE.ISO-8859-1", ++ }; ++ ++/* Syntax options. Will be combined with other flags. */ ++static const reg_syntax_t syntaxes[] = ++ { ++ RE_SYNTAX_EMACS, ++ RE_SYNTAX_AWK, ++ RE_SYNTAX_GNU_AWK, ++ RE_SYNTAX_POSIX_AWK, ++ RE_SYNTAX_GREP, ++ RE_SYNTAX_EGREP, ++ RE_SYNTAX_POSIX_EGREP, ++ RE_SYNTAX_POSIX_BASIC, ++ RE_SYNTAX_POSIX_EXTENDED, ++ RE_SYNTAX_POSIX_MINIMAL_EXTENDED, ++ }; ++ ++/* Trailing characters placed after the initial character. */ ++static const char trailing_strings[][4] = ++ { ++ "", ++ "[", ++ "\\", ++ "[\\", ++ "(", ++ "(\\", ++ "\\(", ++ }; ++ ++static int ++do_test (void) ++{ ++ /* Staging buffer for the constructed regular expression. */ ++ char buffer[16]; ++ ++ /* Allocation used to detect over-reading by the regular expression ++ compiler. */ ++ struct support_next_to_fault ntf ++ = support_next_to_fault_allocate (sizeof (buffer)); ++ ++ /* Arbitrary Unicode codepoint at which we stop generating ++ characters. We do not probe the whole range because that would ++ take too long due to combinatorical exploision as the result of ++ combination with other flags. */ ++ static const wchar_t last_character = 0xfff; ++ ++ for (size_t locale_idx = 0; locale_idx < array_length (locales); ++ ++ locale_idx) ++ { ++ if (setlocale (LC_ALL, locales[locale_idx]) == NULL) ++ { ++ support_record_failure (); ++ printf ("error: setlocale (\"%s\"): %m", locales[locale_idx]); ++ continue; ++ } ++ if (test_verbose > 0) ++ printf ("info: testing locale \"%s\"\n", locales[locale_idx]); ++ ++ for (wchar_t wc = 0; wc <= last_character; ++wc) ++ { ++ char *after_wc; ++ if (wc == 0) ++ { ++ /* wcrtomb treats L'\0' in a special way. */ ++ *buffer = '\0'; ++ after_wc = &buffer[1]; ++ } ++ else ++ { ++ mbstate_t ps = { }; ++ size_t ret = wcrtomb (buffer, wc, &ps); ++ if (ret == (size_t) -1) ++ { ++ /* EILSEQ means that the target character set ++ cannot encode the character. */ ++ if (errno != EILSEQ) ++ { ++ support_record_failure (); ++ printf ("error: wcrtomb (0x%x) failed: %m\n", ++ (unsigned) wc); ++ } ++ continue; ++ } ++ TEST_VERIFY_EXIT (ret != 0); ++ after_wc = &buffer[ret]; ++ } ++ ++ for (size_t trailing_idx = 0; ++ trailing_idx < array_length (trailing_strings); ++ ++trailing_idx) ++ { ++ char *after_trailing ++ = stpcpy (after_wc, trailing_strings[trailing_idx]); ++ ++ for (int do_nul = 0; do_nul < 2; ++do_nul) ++ { ++ char *after_nul; ++ if (do_nul) ++ { ++ *after_trailing = '\0'; ++ after_nul = &after_trailing[1]; ++ } ++ else ++ after_nul = after_trailing; ++ ++ size_t length = after_nul - buffer; ++ ++ /* Make sure that the faulting region starts ++ after the used portion of the buffer. */ ++ char *ntf_start = ntf.buffer + sizeof (buffer) - length; ++ memcpy (ntf_start, buffer, length); ++ ++ for (const reg_syntax_t *psyntax = syntaxes; ++ psyntax < array_end (syntaxes); ++psyntax) ++ for (int do_icase = 0; do_icase < 2; ++do_icase) ++ { ++ re_syntax_options = *psyntax; ++ if (do_icase) ++ re_syntax_options |= RE_ICASE; ++ ++ regex_t reg; ++ memset (®, 0, sizeof (reg)); ++ const char *msg = re_compile_pattern ++ (ntf_start, length, ®); ++ if (msg != NULL) ++ { ++ if (test_verbose > 0) ++ { ++ char *quoted = support_quote_blob ++ (buffer, length); ++ printf ("info: compilation failed for pattern" ++ " \"%s\", syntax 0x%lx: %s\n", ++ quoted, re_syntax_options, msg); ++ free (quoted); ++ } ++ } ++ else ++ regfree (®); ++ } ++ } ++ } ++ } ++ } ++ ++ support_next_to_fault_free (&ntf); ++ ++ return 0; ++} ++ ++#include <support/test-driver.c> +diff --git a/stdlib/tst-setcontext9.c b/stdlib/tst-setcontext9.c +index 4636ce9030..009928235d 100644 +--- a/stdlib/tst-setcontext9.c ++++ b/stdlib/tst-setcontext9.c +@@ -41,30 +41,59 @@ f2 (void) + } + + static void +-f1 (void) ++f1b (void) + { +- puts ("start f1"); +- if (getcontext (&ctx[2]) != 0) +- { +- printf ("%s: getcontext: %m\n", __FUNCTION__); +- exit (EXIT_FAILURE); +- } + if (done) + { +- puts ("set context in f1"); ++ puts ("set context in f1b"); + if (setcontext (&ctx[3]) != 0) + { + printf ("%s: setcontext: %m\n", __FUNCTION__); + exit (EXIT_FAILURE); + } + } ++ exit (EXIT_FAILURE); ++} ++ ++static void ++f1a (void) ++{ ++ static char st2[32768]; ++ puts ("start f1a"); ++ if (getcontext (&ctx[2]) != 0) ++ { ++ printf ("%s: getcontext: %m\n", __FUNCTION__); ++ exit (EXIT_FAILURE); ++ } ++ ctx[2].uc_stack.ss_sp = st2; ++ ctx[2].uc_stack.ss_size = sizeof st2; ++ ctx[2].uc_link = &ctx[0]; ++ makecontext (&ctx[2], (void (*) (void)) f1b, 0); + f2 (); + } + ++/* The execution path through the test looks like this: ++ do_test (call) ++ -> "making contexts" ++ -> "swap contexts" ++ f1a (via swapcontext to ctx[1], with alternate stack) ++ -> "start f1a" ++ f2 (call) ++ -> "swap contexts in f2" ++ f1b (via swapcontext to ctx[2], with alternate stack) ++ -> "set context in f1b" ++ do_test (via setcontext to ctx[3], main stack) ++ -> "setcontext" ++ f2 (via setcontext to ctx[4], with alternate stack) ++ -> "end f2" ++ ++ We must use an alternate stack for f1b, because if we don't then the ++ result of executing an earlier caller may overwrite registers ++ spilled to the stack in f2. */ + static int + do_test (void) + { +- char st1[32768]; ++ static char st1[32768]; + puts ("making contexts"); + if (getcontext (&ctx[0]) != 0) + { +@@ -79,7 +108,7 @@ do_test (void) + ctx[1].uc_stack.ss_sp = st1; + ctx[1].uc_stack.ss_size = sizeof st1; + ctx[1].uc_link = &ctx[0]; +- makecontext (&ctx[1], (void (*) (void)) f1, 0); ++ makecontext (&ctx[1], (void (*) (void)) f1a, 0); + puts ("swap contexts"); + if (swapcontext (&ctx[3], &ctx[1]) != 0) + { +diff --git a/string/strcasestr.c b/string/strcasestr.c +index 5909fe3cdb..421764bd1b 100644 +--- a/string/strcasestr.c ++++ b/string/strcasestr.c +@@ -37,8 +37,9 @@ + /* Two-Way algorithm. */ + #define RETURN_TYPE char * + #define AVAILABLE(h, h_l, j, n_l) \ +- (((j) + (n_l) <= (h_l)) || ((h_l) += __strnlen ((void*)((h) + (h_l)), 512), \ +- (j) + (n_l) <= (h_l))) ++ (((j) + (n_l) <= (h_l)) \ ++ || ((h_l) += __strnlen ((void*)((h) + (h_l)), (n_l) + 512), \ ++ (j) + (n_l) <= (h_l))) + #define CHECK_EOL (1) + #define RET0_IF_0(a) if (!a) goto ret0 + #define CANON_ELEMENT(c) TOLOWER (c) +diff --git a/string/strstr.c b/string/strstr.c +index 265e9f310c..79ebcc7532 100644 +--- a/string/strstr.c ++++ b/string/strstr.c +@@ -33,8 +33,9 @@ + + #define RETURN_TYPE char * + #define AVAILABLE(h, h_l, j, n_l) \ +- (((j) + (n_l) <= (h_l)) || ((h_l) += __strnlen ((void*)((h) + (h_l)), 512), \ +- (j) + (n_l) <= (h_l))) ++ (((j) + (n_l) <= (h_l)) \ ++ || ((h_l) += __strnlen ((void*)((h) + (h_l)), (n_l) + 512), \ ++ (j) + (n_l) <= (h_l))) + #define CHECK_EOL (1) + #define RET0_IF_0(a) if (!a) goto ret0 + #define FASTSEARCH(S,C,N) (void*) strchr ((void*)(S), (C)) +diff --git a/string/test-strstr.c b/string/test-strstr.c +index 8d99716ff3..5861b01b73 100644 +--- a/string/test-strstr.c ++++ b/string/test-strstr.c +@@ -151,6 +151,32 @@ check2 (void) + } + } + ++#define N 1024 ++ ++static void ++pr23637 (void) ++{ ++ char *h = (char*) buf1; ++ char *n = (char*) buf2; ++ ++ for (int i = 0; i < N; i++) ++ { ++ n[i] = 'x'; ++ h[i] = ' '; ++ h[i + N] = 'x'; ++ } ++ ++ n[N] = '\0'; ++ h[N * 2] = '\0'; ++ ++ /* Ensure we don't match at the first 'x'. */ ++ h[0] = 'x'; ++ ++ char *exp_result = stupid_strstr (h, n); ++ FOR_EACH_IMPL (impl, 0) ++ check_result (impl, h, n, exp_result); ++} ++ + static int + test_main (void) + { +@@ -158,6 +184,7 @@ test_main (void) + + check1 (); + check2 (); ++ pr23637 (); + + printf ("%23s", ""); + FOR_EACH_IMPL (impl, 0) +@@ -202,6 +229,9 @@ test_main (void) + do_test (15, 9, hlen, klen, 1); + do_test (15, 15, hlen, klen, 0); + do_test (15, 15, hlen, klen, 1); ++ ++ do_test (15, 15, hlen + klen * 4, klen * 4, 0); ++ do_test (15, 15, hlen + klen * 4, klen * 4, 1); + } + + do_test (0, 0, page_size - 1, 16, 0); +diff --git a/sysdeps/htl/pt-getspecific.c b/sysdeps/htl/pt-getspecific.c +index a0227a67f6..64ddf9551a 100644 +--- a/sysdeps/htl/pt-getspecific.c ++++ b/sysdeps/htl/pt-getspecific.c +@@ -36,3 +36,4 @@ __pthread_getspecific (pthread_key_t key) + return self->thread_specifics[key]; + } + strong_alias (__pthread_getspecific, pthread_getspecific); ++hidden_def (__pthread_getspecific) +diff --git a/sysdeps/htl/pt-setspecific.c b/sysdeps/htl/pt-setspecific.c +index a46a12f157..02aff417ef 100644 +--- a/sysdeps/htl/pt-setspecific.c ++++ b/sysdeps/htl/pt-setspecific.c +@@ -48,3 +48,4 @@ __pthread_setspecific (pthread_key_t key, const void *value) + return 0; + } + strong_alias (__pthread_setspecific, pthread_setspecific); ++hidden_def (__pthread_setspecific) +diff --git a/sysdeps/htl/pthreadP.h b/sysdeps/htl/pthreadP.h +index 132ac1718e..71c2fcd9c6 100644 +--- a/sysdeps/htl/pthreadP.h ++++ b/sysdeps/htl/pthreadP.h +@@ -68,6 +68,8 @@ struct __pthread_cancelation_handler **___pthread_get_cleanup_stack (void) attri + + #if IS_IN (libpthread) + hidden_proto (__pthread_key_create) ++hidden_proto (__pthread_getspecific) ++hidden_proto (__pthread_setspecific) + hidden_proto (_pthread_mutex_init) + #endif + +diff --git a/sysdeps/i386/dl-cet.c b/sysdeps/i386/dl-cet.c +deleted file mode 100644 +index 5d9a4e8d51..0000000000 +--- a/sysdeps/i386/dl-cet.c ++++ /dev/null +@@ -1,67 +0,0 @@ +-/* Linux/i386 CET initializers function. +- Copyright (C) 2018 Free Software Foundation, Inc. +- +- The GNU C Library is free software; you can redistribute it and/or +- modify it under the terms of the GNU Lesser General Public +- License as published by the Free Software Foundation; either +- version 2.1 of the License, or (at your option) any later version. +- +- The GNU C Library is distributed in the hope that it will be useful, +- but WITHOUT ANY WARRANTY; without even the implied warranty of +- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +- Lesser General Public License for more details. +- +- You should have received a copy of the GNU Lesser General Public +- License along with the GNU C Library; if not, see +- <http://www.gnu.org/licenses/>. */ +- +- +-#define LINKAGE static inline +-#define _dl_cet_check cet_check +-#include <sysdeps/x86/dl-cet.c> +-#undef _dl_cet_check +- +-#ifdef SHARED +-void +-_dl_cet_check (struct link_map *main_map, const char *program) +-{ +- cet_check (main_map, program); +- +- if ((GL(dl_x86_feature_1)[0] & GNU_PROPERTY_X86_FEATURE_1_SHSTK)) +- { +- /* Replace _dl_runtime_resolve and _dl_runtime_profile with +- _dl_runtime_resolve_shstk and _dl_runtime_profile_shstk, +- respectively if SHSTK is enabled. */ +- extern void _dl_runtime_resolve (Elf32_Word) attribute_hidden; +- extern void _dl_runtime_resolve_shstk (Elf32_Word) attribute_hidden; +- extern void _dl_runtime_profile (Elf32_Word) attribute_hidden; +- extern void _dl_runtime_profile_shstk (Elf32_Word) attribute_hidden; +- unsigned int i; +- struct link_map *l; +- Elf32_Addr *got; +- +- if (main_map->l_info[DT_JMPREL]) +- { +- got = (Elf32_Addr *) D_PTR (main_map, l_info[DT_PLTGOT]); +- if (got[2] == (Elf32_Addr) &_dl_runtime_resolve) +- got[2] = (Elf32_Addr) &_dl_runtime_resolve_shstk; +- else if (got[2] == (Elf32_Addr) &_dl_runtime_profile) +- got[2] = (Elf32_Addr) &_dl_runtime_profile_shstk; +- } +- +- i = main_map->l_searchlist.r_nlist; +- while (i-- > 0) +- { +- l = main_map->l_initfini[i]; +- if (l->l_info[DT_JMPREL]) +- { +- got = (Elf32_Addr *) D_PTR (l, l_info[DT_PLTGOT]); +- if (got[2] == (Elf32_Addr) &_dl_runtime_resolve) +- got[2] = (Elf32_Addr) &_dl_runtime_resolve_shstk; +- else if (got[2] == (Elf32_Addr) &_dl_runtime_profile) +- got[2] = (Elf32_Addr) &_dl_runtime_profile_shstk; +- } +- } +- } +-} +-#endif +diff --git a/sysdeps/i386/dl-machine.h b/sysdeps/i386/dl-machine.h +index 1afdcbd9ea..f6cfb90e21 100644 +--- a/sysdeps/i386/dl-machine.h ++++ b/sysdeps/i386/dl-machine.h +@@ -67,6 +67,11 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile) + Elf32_Addr *got; + extern void _dl_runtime_resolve (Elf32_Word) attribute_hidden; + extern void _dl_runtime_profile (Elf32_Word) attribute_hidden; ++ extern void _dl_runtime_resolve_shstk (Elf32_Word) attribute_hidden; ++ extern void _dl_runtime_profile_shstk (Elf32_Word) attribute_hidden; ++ /* Check if SHSTK is enabled by kernel. */ ++ bool shstk_enabled ++ = (GL(dl_x86_feature_1)[0] & GNU_PROPERTY_X86_FEATURE_1_SHSTK) != 0; + + if (l->l_info[DT_JMPREL] && lazy) + { +@@ -93,7 +98,9 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile) + end in this function. */ + if (__glibc_unlikely (profile)) + { +- got[2] = (Elf32_Addr) &_dl_runtime_profile; ++ got[2] = (shstk_enabled ++ ? (Elf32_Addr) &_dl_runtime_profile_shstk ++ : (Elf32_Addr) &_dl_runtime_profile); + + if (GLRO(dl_profile) != NULL + && _dl_name_match_p (GLRO(dl_profile), l)) +@@ -104,7 +111,9 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile) + else + /* This function will get called to fix up the GOT entry indicated by + the offset on the stack, and then jump to the resolved address. */ +- got[2] = (Elf32_Addr) &_dl_runtime_resolve; ++ got[2] = (shstk_enabled ++ ? (Elf32_Addr) &_dl_runtime_resolve_shstk ++ : (Elf32_Addr) &_dl_runtime_resolve); + } + + return lazy; +diff --git a/sysdeps/i386/start.S b/sysdeps/i386/start.S +index 91035fa83f..e35e9bd31b 100644 +--- a/sysdeps/i386/start.S ++++ b/sysdeps/i386/start.S +@@ -52,10 +52,11 @@ + NULL + */ + +- .text +- .globl _start +- .type _start,@function +-_start: ++#include <sysdep.h> ++ ++ENTRY (_start) ++ /* Clearing frame pointer is insufficient, use CFI. */ ++ cfi_undefined (eip) + /* Clear the frame pointer. The ABI suggests this be done, to mark + the outermost frame obviously. */ + xorl %ebp, %ebp +@@ -131,6 +132,7 @@ _start: + 1: movl (%esp), %ebx + ret + #endif ++END (_start) + + /* To fulfill the System V/i386 ABI we need this symbol. Yuck, it's so + meaningless since we don't support machines < 80386. */ +diff --git a/sysdeps/riscv/rv64/rvd/libm-test-ulps b/sysdeps/riscv/rv64/rvd/libm-test-ulps +index f8feadcd0d..61be2df60d 100644 +--- a/sysdeps/riscv/rv64/rvd/libm-test-ulps ++++ b/sysdeps/riscv/rv64/rvd/libm-test-ulps +@@ -1006,6 +1006,8 @@ ildouble: 2 + ldouble: 2 + + Function: "cos": ++double: 1 ++idouble: 1 + ildouble: 1 + ldouble: 1 + +@@ -1348,9 +1350,9 @@ ildouble: 4 + ldouble: 4 + + Function: Imaginary part of "ctan_towardzero": +-double: 1 ++double: 2 + float: 2 +-idouble: 1 ++idouble: 2 + ifloat: 2 + ildouble: 5 + ldouble: 5 +@@ -1898,10 +1900,12 @@ ldouble: 2 + Function: "log_upward": + double: 1 + idouble: 1 +-ildouble: 1 +-ldouble: 1 ++ildouble: 2 ++ldouble: 2 + + Function: "pow": ++double: 1 ++idouble: 1 + ildouble: 2 + ldouble: 2 + +@@ -1930,6 +1934,8 @@ ildouble: 2 + ldouble: 2 + + Function: "sin": ++double: 1 ++idouble: 1 + ildouble: 1 + ldouble: 1 + +@@ -1952,6 +1958,8 @@ ildouble: 3 + ldouble: 3 + + Function: "sincos": ++double: 1 ++idouble: 1 + ildouble: 1 + ldouble: 1 + +diff --git a/sysdeps/riscv/rvf/math_private.h b/sysdeps/riscv/rvf/math_private.h +index cdb7858fc8..ca587620cb 100644 +--- a/sysdeps/riscv/rvf/math_private.h ++++ b/sysdeps/riscv/rvf/math_private.h +@@ -72,8 +72,8 @@ libc_fesetround_riscv (int round) + static __always_inline void + libc_feholdexcept_setround_riscv (fenv_t *envp, int round) + { +- libc_fesetround_riscv (round); + libc_feholdexcept_riscv (envp); ++ libc_fesetround_riscv (round); + } + + #define libc_feholdexcept_setround libc_feholdexcept_setround_riscv +diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile +index f71cc39c7e..773aaea0e9 100644 +--- a/sysdeps/unix/sysv/linux/Makefile ++++ b/sysdeps/unix/sysv/linux/Makefile +@@ -161,6 +161,7 @@ inhibit-glue = yes + + ifeq ($(subdir),dirent) + sysdep_routines += getdirentries getdirentries64 ++tests-internal += tst-readdir64-compat + endif + + ifeq ($(subdir),nis) +diff --git a/sysdeps/unix/sysv/linux/getdents64.c b/sysdeps/unix/sysv/linux/getdents64.c +index 3bde0cf4f0..bc140b5a7f 100644 +--- a/sysdeps/unix/sysv/linux/getdents64.c ++++ b/sysdeps/unix/sysv/linux/getdents64.c +@@ -33,41 +33,80 @@ strong_alias (__getdents64, __getdents) + # include <shlib-compat.h> + + # if SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_2) +-# include <olddirent.h> ++# include <olddirent.h> ++# include <unistd.h> + +-/* kernel definition of as of 3.2. */ +-struct compat_linux_dirent ++static ssize_t ++handle_overflow (int fd, __off64_t offset, ssize_t count) + { +- /* Both d_ino and d_off are compat_ulong_t which are defined in all +- architectures as 'u32'. */ +- uint32_t d_ino; +- uint32_t d_off; +- unsigned short d_reclen; +- char d_name[1]; +-}; ++ /* If this is the first entry in the buffer, we can report the ++ error. */ ++ if (count == 0) ++ { ++ __set_errno (EOVERFLOW); ++ return -1; ++ } ++ ++ /* Otherwise, seek to the overflowing entry, so that the next call ++ will report the error, and return the data read so far.. */ ++ if (__lseek64 (fd, offset, SEEK_SET) != 0) ++ return -1; ++ return count; ++} + + ssize_t + __old_getdents64 (int fd, char *buf, size_t nbytes) + { +- ssize_t retval = INLINE_SYSCALL_CALL (getdents, fd, buf, nbytes); ++ /* We do not move the individual directory entries. This is only ++ possible if the target type (struct __old_dirent64) is smaller ++ than the source type. */ ++ _Static_assert (offsetof (struct __old_dirent64, d_name) ++ <= offsetof (struct dirent64, d_name), ++ "__old_dirent64 is larger than dirent64"); ++ _Static_assert (__alignof__ (struct __old_dirent64) ++ <= __alignof__ (struct dirent64), ++ "alignment of __old_dirent64 is larger than dirent64"); + +- /* The kernel added the d_type value after the name. Change this now. */ +- if (retval != -1) ++ ssize_t retval = INLINE_SYSCALL_CALL (getdents64, fd, buf, nbytes); ++ if (retval > 0) + { +- union +- { +- struct compat_linux_dirent k; +- struct dirent u; +- } *kbuf = (void *) buf; +- +- while ((char *) kbuf < buf + retval) ++ char *p = buf; ++ char *end = buf + retval; ++ while (p < end) + { +- char d_type = *((char *) kbuf + kbuf->k.d_reclen - 1); +- memmove (kbuf->u.d_name, kbuf->k.d_name, +- strlen (kbuf->k.d_name) + 1); +- kbuf->u.d_type = d_type; ++ struct dirent64 *source = (struct dirent64 *) p; ++ ++ /* Copy out the fixed-size data. */ ++ __ino_t ino = source->d_ino; ++ __off64_t offset = source->d_off; ++ unsigned int reclen = source->d_reclen; ++ unsigned char type = source->d_type; ++ ++ /* Check for ino_t overflow. */ ++ if (__glibc_unlikely (ino != source->d_ino)) ++ return handle_overflow (fd, offset, p - buf); ++ ++ /* Convert to the target layout. Use a separate struct and ++ memcpy to side-step aliasing issues. */ ++ struct __old_dirent64 result; ++ result.d_ino = ino; ++ result.d_off = offset; ++ result.d_reclen = reclen; ++ result.d_type = type; ++ ++ /* Write the fixed-sized part of the result to the ++ buffer. */ ++ size_t result_name_offset = offsetof (struct __old_dirent64, d_name); ++ memcpy (p, &result, result_name_offset); ++ ++ /* Adjust the position of the name if necessary. Copy ++ everything until the end of the record, including the ++ terminating NUL byte. */ ++ if (result_name_offset != offsetof (struct dirent64, d_name)) ++ memmove (p + result_name_offset, source->d_name, ++ reclen - offsetof (struct dirent64, d_name)); + +- kbuf = (void *) ((char *) kbuf + kbuf->k.d_reclen); ++ p += reclen; + } + } + return retval; +diff --git a/sysdeps/unix/sysv/linux/gethostid.c b/sysdeps/unix/sysv/linux/gethostid.c +index 2e20f034dc..ee0190e7f9 100644 +--- a/sysdeps/unix/sysv/linux/gethostid.c ++++ b/sysdeps/unix/sysv/linux/gethostid.c +@@ -102,12 +102,12 @@ gethostid (void) + { + int ret = __gethostbyname_r (hostname, &hostbuf, + tmpbuf.data, tmpbuf.length, &hp, &herr); +- if (ret == 0) ++ if (ret == 0 && hp != NULL) + break; + else + { + /* Enlarge the buffer on ERANGE. */ +- if (herr == NETDB_INTERNAL && errno == ERANGE) ++ if (ret != 0 && herr == NETDB_INTERNAL && errno == ERANGE) + { + if (!scratch_buffer_grow (&tmpbuf)) + return 0; +diff --git a/sysdeps/unix/sysv/linux/preadv2.c b/sysdeps/unix/sysv/linux/preadv2.c +index c8bf0764ef..bb08cbc5fd 100644 +--- a/sysdeps/unix/sysv/linux/preadv2.c ++++ b/sysdeps/unix/sysv/linux/preadv2.c +@@ -32,7 +32,7 @@ preadv2 (int fd, const struct iovec *vector, int count, off_t offset, + # ifdef __NR_preadv2 + ssize_t result = SYSCALL_CANCEL (preadv2, fd, vector, count, + LO_HI_LONG (offset), flags); +- if (result >= 0) ++ if (result >= 0 || errno != ENOSYS) + return result; + # endif + /* Trying to emulate the preadv2 syscall flags is troublesome: +diff --git a/sysdeps/unix/sysv/linux/preadv64v2.c b/sysdeps/unix/sysv/linux/preadv64v2.c +index d7400a0252..b72a047347 100644 +--- a/sysdeps/unix/sysv/linux/preadv64v2.c ++++ b/sysdeps/unix/sysv/linux/preadv64v2.c +@@ -30,7 +30,7 @@ preadv64v2 (int fd, const struct iovec *vector, int count, off64_t offset, + #ifdef __NR_preadv64v2 + ssize_t result = SYSCALL_CANCEL (preadv64v2, fd, vector, count, + LO_HI_LONG (offset), flags); +- if (result >= 0) ++ if (result >= 0 || errno != ENOSYS) + return result; + #endif + /* Trying to emulate the preadv2 syscall flags is troublesome: +diff --git a/sysdeps/unix/sysv/linux/pwritev2.c b/sysdeps/unix/sysv/linux/pwritev2.c +index 29c2264c8f..26333ebd43 100644 +--- a/sysdeps/unix/sysv/linux/pwritev2.c ++++ b/sysdeps/unix/sysv/linux/pwritev2.c +@@ -28,7 +28,7 @@ pwritev2 (int fd, const struct iovec *vector, int count, off_t offset, + # ifdef __NR_pwritev2 + ssize_t result = SYSCALL_CANCEL (pwritev2, fd, vector, count, + LO_HI_LONG (offset), flags); +- if (result >= 0) ++ if (result >= 0 || errno != ENOSYS) + return result; + # endif + /* Trying to emulate the pwritev2 syscall flags is troublesome: +diff --git a/sysdeps/unix/sysv/linux/pwritev64v2.c b/sysdeps/unix/sysv/linux/pwritev64v2.c +index 42da321149..17ea905aa6 100644 +--- a/sysdeps/unix/sysv/linux/pwritev64v2.c ++++ b/sysdeps/unix/sysv/linux/pwritev64v2.c +@@ -30,7 +30,7 @@ pwritev64v2 (int fd, const struct iovec *vector, int count, off64_t offset, + #ifdef __NR_pwritev64v2 + ssize_t result = SYSCALL_CANCEL (pwritev64v2, fd, vector, count, + LO_HI_LONG (offset), flags); +- if (result >= 0) ++ if (result >= 0 || errno != ENOSYS) + return result; + #endif + /* Trying to emulate the pwritev2 syscall flags is troublesome: +diff --git a/sysdeps/unix/sysv/linux/spawni.c b/sysdeps/unix/sysv/linux/spawni.c +index cf0213ece5..85239cedbf 100644 +--- a/sysdeps/unix/sysv/linux/spawni.c ++++ b/sysdeps/unix/sysv/linux/spawni.c +@@ -101,7 +101,7 @@ maybe_script_execute (struct posix_spawn_args *args) + ptrdiff_t argc = args->argc; + + /* Construct an argument list for the shell. */ +- char *new_argv[argc + 1]; ++ char *new_argv[argc + 2]; + new_argv[0] = (char *) _PATH_BSHELL; + new_argv[1] = (char *) args->file; + if (argc > 1) +diff --git a/sysdeps/unix/sysv/linux/tst-readdir64-compat.c b/sysdeps/unix/sysv/linux/tst-readdir64-compat.c +new file mode 100644 +index 0000000000..43c4a8477c +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/tst-readdir64-compat.c +@@ -0,0 +1,111 @@ ++/* Test readdir64 compatibility symbol. ++ Copyright (C) 2018 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ <http://www.gnu.org/licenses/>. */ ++ ++#include <dirent.h> ++#include <dlfcn.h> ++#include <errno.h> ++#include <shlib-compat.h> ++#include <stdbool.h> ++#include <stdio.h> ++#include <string.h> ++#include <support/check.h> ++ ++/* Copied from <olddirent.h>. */ ++struct __old_dirent64 ++ { ++ __ino_t d_ino; ++ __off64_t d_off; ++ unsigned short int d_reclen; ++ unsigned char d_type; ++ char d_name[256]; ++ }; ++ ++typedef struct __old_dirent64 *(*compat_readdir64_type) (DIR *); ++ ++#if TEST_COMPAT (libc, GLIBC_2_1, GLIBC_2_2) ++struct __old_dirent64 *compat_readdir64 (DIR *); ++compat_symbol_reference (libc, compat_readdir64, readdir64, GLIBC_2_1); ++#endif ++ ++static int ++do_test (void) ++{ ++#if TEST_COMPAT (libc, GLIBC_2_1, GLIBC_2_2) ++ ++ /* Directory stream using the non-compat readdir64 symbol. The test ++ checks against this. */ ++ DIR *dir_reference = opendir ("."); ++ TEST_VERIFY_EXIT (dir_reference != NULL); ++ DIR *dir_test = opendir ("."); ++ TEST_VERIFY_EXIT (dir_test != NULL); ++ ++ /* This loop assumes that the enumeration order is consistent for ++ two different handles. Nothing should write to the current ++ directory (in the source tree) while this test runs, so there ++ should not be any difference due to races. */ ++ size_t count = 0; ++ while (true) ++ { ++ errno = 0; ++ struct dirent64 *entry_reference = readdir64 (dir_reference); ++ if (entry_reference == NULL && errno != 0) ++ FAIL_EXIT1 ("readdir64 entry %zu: %m\n", count); ++ struct __old_dirent64 *entry_test = compat_readdir64 (dir_test); ++ if (entry_reference == NULL) ++ { ++ if (errno == EOVERFLOW) ++ { ++ TEST_VERIFY (entry_reference->d_ino ++ != (__ino_t) entry_reference->d_ino); ++ printf ("info: inode number overflow at entry %zu\n", count); ++ break; ++ } ++ if (errno != 0) ++ FAIL_EXIT1 ("compat readdir64 entry %zu: %m\n", count); ++ } ++ ++ /* Check that both streams end at the same time. */ ++ if (entry_reference == NULL) ++ { ++ TEST_VERIFY (entry_test == NULL); ++ break; ++ } ++ else ++ TEST_VERIFY_EXIT (entry_test != NULL); ++ ++ /* Check that the entries are the same. */ ++ TEST_COMPARE_BLOB (entry_reference->d_name, ++ strlen (entry_reference->d_name), ++ entry_test->d_name, strlen (entry_test->d_name)); ++ TEST_COMPARE (entry_reference->d_ino, entry_test->d_ino); ++ TEST_COMPARE (entry_reference->d_off, entry_test->d_off); ++ TEST_COMPARE (entry_reference->d_type, entry_test->d_type); ++ TEST_COMPARE (entry_reference->d_reclen, entry_test->d_reclen); ++ ++ ++count; ++ } ++ printf ("info: %zu directory entries found\n", count); ++ TEST_VERIFY (count >= 3); /* ".", "..", and some source files. */ ++ ++ TEST_COMPARE (closedir (dir_test), 0); ++ TEST_COMPARE (closedir (dir_reference), 0); ++#endif ++ return 0; ++} ++ ++#include <support/test-driver.c> |