diff --git a/ChangeLog b/ChangeLog index cb9124e..376355f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,300 @@ +2016-02-12 Florian Weimer + + * misc/bug18240.c (do_test): Set RLIMIT_AS. + +2016-01-27 Paul Eggert + + [BZ #18240] + * misc/hsearch_r.c (isprime, __hcreate_r): Protect against + unsigned int wraparound. + +2016-01-27 Florian Weimer + + [BZ #18240] + * misc/bug18240.c: New test. + * misc/Makefile (tests): Add it. + +2015-08-25 Ondřej Bílka + + [BZ #18240] + * misc/hsearch_r.c (__hcreate_r): Handle overflow. + +2015-10-27 Ludovic Courtès + + * locale/loadlocale.c (_nl_intern_locale_data): Change assertion + on CNT to a conditional jump to 'puntdata'. + +2015-08-18 Alan Modra + + [BZ #18421] + * sysdeps/hppa/start.S [SHARED]: Use .section .data.rel.ro and define + .Lp__global. + (_start): Load %dp via .Lp__global. + [!SHARED]: Use .section .rodata. + +2015-08-09 John David Anglin + + [BZ #18480] + * sysdeps/unix/sysv/linux/hppa/sysdep.h (LOAD_ARGS_0, LOAD_ARGS_1, + LOAD_ARGS_2, LOAD_ARGS_3, LOAD_ARGS_4, LOAD_ARGS_5, LOAD_ARGS_6): + Define. + (LOAD_REGS_0, LOAD_REGS_1, LOAD_REGS_2, LOAD_REGS_3, LOAD_REGS_4, + LOAD_REGS_5, LOAD_REGS_6): Update. + (INTERNAL_SYSCALL): Update using new LOAD defines. + (INTERNAL_SYSCALL_NCS): Likewise. + * sysdeps/unix/sysv/linux/hppa/syscall.c (syscall): Likewise. + +2015-09-26 Paul Pluzhnikov + + [BZ #18985] + * time/strftime_l.c (a_wkday, f_wkday, a_month, f_month): Range check. + (__strftime_internal): Likewise. + * time/tst-strftime.c (do_bz18985): New test. + (do_test): Call it. + +2015-08-08 Paul Pluzhnikov + + [BZ #17905] + * catgets/Makefile (tst-catgets-mem): New test. + * catgets/catgets.c (catopen): Don't use unbounded alloca. + * catgets/open_catalog.c (__open_catalog): Likewise. + * catgets/tst-catgets.c (do_bz17905): Test unbounded alloca. + +2015-12-31 Aurelien Jarno + + * sysdeps/unix/sysv/linux/alpha/libc.abilist [GLIBC_2.22]: Move + to keep the file sorted. + * sysdeps/unix/sysv/linux/hppa/libc.abilist [GLIBC_2.22]: Likewise. + +2015-12-17 Paul E. Murphy + + [BZ #19174] + * sysdeps/powerpc/nptl/elide.h (__elide_lock): Fix usage of + .skip_lock_out_of_tbegin_retries. + * sysdeps/unix/sysv/linux/powerpc/elision-lock.c + (__lll_lock_elision): Likewise, and respect a value of + try_tbegin <= 0. + +2015-11-20 Roland McGrath + + * sysdeps/nacl/dl-map-segments.h (_dl_map_segments): Use + __glibc_likely instead of __builtin_expect. After falling back to + dyncode_create in a non-ET_DYN case, use the allocate_code_data + system interface to register the code pages as occupied. + +2015-11-14 H.J. Lu + + * config.make.in (have-glob-dat-reloc): New. + * configure.ac (libc_cv_has_glob_dat): New. Set to yes if + target supports GLOB_DAT relocaton. AC_SUBST. + * configure: Regenerated. + * elf/Makefile (tests): Add tst-prelink. + (tests-special): Add $(objpfx)tst-prelink-cmp.out. + (tst-prelink-ENV): New. + ($(objpfx)tst-prelink-conflict.out): Likewise. + ($(objpfx)tst-prelink-cmp.out): Likewise. + * sysdeps/x86/tst-prelink.c: Moved to ... + * elf/tst-prelink.c: Here. + * sysdeps/x86/tst-prelink.exp: Moved to ... + * elf/tst-prelink.exp: Here. + * sysdeps/x86/Makefile (tests): Don't add tst-prelink. + (tst-prelink-ENV): Removed. + ($(objpfx)tst-prelink-conflict.out): Likewise. + ($(objpfx)tst-prelink-cmp.out): Likewise. + (tests-special): Don't add $(objpfx)tst-prelink-cmp.out. + +2015-11-10 Roland McGrath + + * elf/dl-load.c (open_verify): Take new argument FD. + Skip __open call if passed FD is not -1. + (_dl_map_object, open_path): Update callers. + * elf/dl-sysdep-open.h: New file. + * elf/dl-load.c: Include it. + (_dl_map_object): Try _dl_sysdep_open_object before ldconfig cache. + * sysdeps/nacl/dl-sysdep.c (_dl_sysdep_open_object): New function. + * sysdeps/nacl/dl-sysdep-open.h: New file. + * sysdeps/nacl/nacl-interface-list.h: Move nacl_irt_resource_open + from libc to rtld. + +2015-11-10 H.J. Lu + + [BZ #19178] + * sysdeps/x86/Makefile (tests): Add tst-prelink. + (tst-prelink-ENV): New. + ($(objpfx)tst-prelink-conflict.out): Likewise. + ($(objpfx)tst-prelink-cmp.out): Likewise. + (tests-special): Add $(objpfx)tst-prelink-cmp.out. + * sysdeps/x86/tst-prelink.c: New file. + * sysdeps/x86/tst-prelink.exp: Likewise. + +2015-11-07 H.J. Lu + + [BZ #19178] + * elf/dl-lookup.c (RTYPE_CLASS_VALID): New. + (RTYPE_CLASS_PLT): Likewise. + (RTYPE_CLASS_COPY): Likewise. + (RTYPE_CLASS_TLS): Likewise. + (_dl_debug_bindings): Use RTYPE_CLASS_TLS and RTYPE_CLASS_VALID + to set relocation type class for DL_DEBUG_PRELINK. Keep only + ELF_RTYPE_CLASS_PLT and ELF_RTYPE_CLASS_COPY bits for + DL_DEBUG_PRELINK. + +2015-10-20 Tulio Magno Quites Machado Filho + + [BZ #18743] + * sysdeps/powerpc/nptl/elide.h (__elide_lock): Move most of this + code to... + (ELIDE_LOCK): ...here. + (__get_new_count): New function with part of the code from + __elide_lock that updates the value of adapt_count after a + transaction abort. + (__elided_trylock): Moved this code to... + (ELIDE_TRYLOCK): ...here. + +2015-10-06 Florian Weimer + + [BZ #19018] + * stdlib/cxa_thread_atexit_impl.c (__cxa_thread_atexit_impl): + Mangle function pointer before storing it. + (__call_tls_dtors): Demangle function pointer before calling it. + +2015-10-15 Florian Weimer + + [BZ #18928] + * sysdeps/generic/ldsodefs.h (struct rtld_global_ro): Remove + _dl_pointer_guard member. + * elf/rtld.c (_rtld_global_ro): Remove _dl_pointer_guard + initializer. + (security_init): Always set up pointer guard. + (process_envvars): Do not process LD_POINTER_GUARD. + +2015-10-09 Carlos O'Donell + + [BZ #18589] + * string/bug-strcoll2.c: Adjust copyright, and remove contributed by. + * string/Makefile ($(objpfx)bug-strcoll2.out): Depend on + $(gen-locales). + +2015-10-08 Carlos O'Donell + + [BZ #18589] + * string/Makefile (tests): Add bug-strcoll2. + (LOCALES): Add cs_CZ.UTF-8. + +2015-09-28 Martin Sebor + + [BZ #18969] + * string/Makefile (LOCALES): Define. + (gen-locales.mk): Include. + (test-strcasecmp.out, test-strncasecmp.out, tst-strxfrm.out) + (tst-strxfrm2.out): Add deppendency on $(gen-locales). + * string/tst-strxfrm2.c (do_test): Print the name of the locale + on setlocale failure. + +2015-10-08 Carlos O'Donell + + [BZ #18589] + * string/bug-strcoll2.c: New file. + * locale/categories.def: Revert commit + f13c2a8dff2329c6692a80176262ceaaf8a6f74e. + * locale/langinfo.h: Likewise. + * locale/localeinfo.h: Likewise. + * locale/C-collate.c: Likewise. + * programs/ld-collate.c (collate_output): Likewise. + * string/strcoll_l.c (STRDIFF): Likewise. + (STRCOLL): Likewise. + * wcsmbs/wcscoll_l.c: Likewise. + +2015-09-15 Roland McGrath + + * misc/sys/param.h [!MAXHOSTNAMELEN && HOST_NAME_MAX] + (MAXHOSTNAMELEN): Define it to HOST_NAME_MAX. + +2015-09-11 Roland McGrath + + * sysdeps/nacl/Makefile [$(subdir) = misc] (sysdep_headers): + Use 'override' keyword to freeze the value here, preventing + the addition of sys/mtio.h by sysdeps/gnu/Makefile. + +2015-09-04 Roland McGrath + + [BZ #18921] + * sysdeps/posix/opendir.c (need_isdir_precheck) [O_DIRECTORY]: + Fix inverted sense of test of 'o_directory_works' value. + Reported by Pádraig Brady , diagnosed by + Bernhard Voelker . + +2015-08-31 Brett Neumeier + + [BZ #18870] + * sysdeps/sparc/sparc32/sem_open.c: Add missing #include + +2015-08-28 Mike Frysinger + + [BZ #18887] + * misc/Makefile (tests): Add tst-mntent-blank-corrupt and + tst-mntent-blank-passno. + * misc/mntent_r.c (__getmntent_r): Do not read past buffer[0]. + * misc/tst-mntent-blank-corrupt.c: New test. + * misc/tst-mntent-blank-passno.c: New test ripped from ... + * misc/tst-mntent.c (do_test): ... here. + +2015-08-25 Roland McGrath + + * sysdeps/nacl/start.c (_start): Call __nacl_main instead of main + if the weak reference is not null. + +2015-08-19 Andrew Senkevich + + [BZ #18796] + * scripts/test-installation.pl: Don't add -lmvec to build options + if libmvec wasn't built. + * NEWS: Mention this fix. + +2015-08-10 Maxim Ostapenko + + [BZ #18778] + * elf/Makefile (tests): Add Add tst-nodelete2. + (modules-names): Add tst-nodelete2mod. + (tst-nodelete2mod.so-no-z-defs): New. + ($(objpfx)tst-nodelete2): Likewise. + ($(objpfx)tst-nodelete2.out): Likewise. + (LDFLAGS-tst-nodelete2): Likewise. + * elf/dl-close.c (_dl_close_worker): Move DF_1_NODELETE clearing + out of loop through all loaded libraries. + * elf/tst-nodelete2.c: New file. + * elf/tst-nodelete2mod.c: Likewise. + +2015-08-10 Andreas Schwab + + [BZ #18781] + * sysdeps/unix/sysv/linux/openat.c (__OPENAT) [MORE_OFLAGS]: Add + MORE_OFLAGS to oflag. + * io/test-lfs.c (do_test): Test openat64. + +2015-08-08 John David Anglin + + [BZ #18787] + * sysdeps/unix/sysv/linux/hppa/bits/atomic.h (_LWS_CLOBBER): Revise + clobber registers. + (atomic_compare_and_exchange_val_acq): Use register asms to assign + operand registers. Use register %r20 for EAGAIN and EDEADLOCK checks. + Cast return to __typeof (oldval). + +2015-08-08 Mike Frysinger + + * sysdeps/unix/sysv/linux/microblaze/sysdep.h: Wrap the whole file + in _LINUX_MICROBLAZE_SYSDEP_H defines. Include sysdeps/unix/sysdep.h + and delete sys/syscall.h include. + +2015-08-07 Mike Frysinger + + * sysdeps/hppa/dl-symaddr.c (_dl_symbol_address): Add rtld_hidden_def. + +2015-08-05 Zack Weinberg + + * misc/regexp.h: Update comments. + 2015-08-05 Carlos O'Donell * version.h (RELEASE): Set to "stable". diff --git a/NEWS b/NEWS index 4c31de7..7c4fbc6 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,16 @@ See the end for copying conditions. Please send GNU C library bug reports via using `glibc' in the "product" field. +Version 2.22.1 + +* The following bugs are resolved with this release: + + 17905, 18420, 18421, 18480, 18589, 18743, 18778, 18781, 18787, 18796, + 18870, 18887, 18921, 18928, 18969, 18985, 19018, 19174, 19178. + +* The LD_POINTER_GUARD environment variable can no longer be used to + disable the pointer guard feature. It is always enabled. + Version 2.22 * The following bugs are resolved with this release: @@ -84,7 +94,7 @@ Version 2.22 release. Use of this header will trigger a deprecation warning. Application developers should update their code to use instead. - This header was formerly part of SUSv2, but was deprecated in 1997 and + This header was formerly part of SUS, but was deprecated in 1994 and removed from the standard in 2001. Also, the glibc implementation leaks memory. See BZ#18681 for more details. diff --git a/catgets/Makefile b/catgets/Makefile index 4624a88..56de38b 100644 --- a/catgets/Makefile +++ b/catgets/Makefile @@ -34,6 +34,7 @@ test-srcs = test-gencat ifeq ($(run-built-tests),yes) tests-special += $(objpfx)de/libc.cat $(objpfx)test1.cat $(objpfx)test2.cat \ $(objpfx)sample.SJIS.cat $(objpfx)test-gencat.out +tests-special += $(objpfx)tst-catgets-mem.out endif gencat-modules = xmalloc @@ -50,9 +51,11 @@ catgets-CPPFLAGS := -DNLSPATH='"$(msgcatdir)/%L/%N:$(msgcatdir)/%L/LC_MESSAGES/% generated += de.msg test1.cat test1.h test2.cat test2.h sample.SJIS.cat \ test-gencat.h +generated += tst-catgets.mtrace tst-catgets-mem.out + generated-dirs += de -tst-catgets-ENV = NLSPATH="$(objpfx)%l/%N.cat" LANG=de +tst-catgets-ENV = NLSPATH="$(objpfx)%l/%N.cat" LANG=de MALLOC_TRACE=$(objpfx)tst-catgets.mtrace ifeq ($(run-built-tests),yes) # This test just checks whether the program produces any error or not. @@ -86,4 +89,8 @@ $(objpfx)test-gencat.out: test-gencat.sh $(objpfx)test-gencat \ $(objpfx)sample.SJIS.cat: sample.SJIS $(objpfx)gencat $(built-program-cmd) -H $(objpfx)test-gencat.h < $(word 1,$^) > $@; \ $(evaluate-test) + +$(objpfx)tst-catgets-mem.out: $(objpfx)tst-catgets.out + $(common-objpfx)malloc/mtrace $(objpfx)tst-catgets.mtrace > $@; \ + $(evaluate-test) endif diff --git a/catgets/catgets.c b/catgets/catgets.c index cf93d56..4be452d 100644 --- a/catgets/catgets.c +++ b/catgets/catgets.c @@ -16,7 +16,6 @@ License along with the GNU C Library; if not, see . */ -#include #include #include #include @@ -35,6 +34,7 @@ catopen (const char *cat_name, int flag) __nl_catd result; const char *env_var = NULL; const char *nlspath = NULL; + char *tmp = NULL; if (strchr (cat_name, '/') == NULL) { @@ -54,7 +54,10 @@ catopen (const char *cat_name, int flag) { /* Append the system dependent directory. */ size_t len = strlen (nlspath) + 1 + sizeof NLSPATH; - char *tmp = alloca (len); + tmp = malloc (len); + + if (__glibc_unlikely (tmp == NULL)) + return (nl_catd) -1; __stpcpy (__stpcpy (__stpcpy (tmp, nlspath), ":"), NLSPATH); nlspath = tmp; @@ -65,16 +68,18 @@ catopen (const char *cat_name, int flag) result = (__nl_catd) malloc (sizeof (*result)); if (result == NULL) - /* We cannot get enough memory. */ - return (nl_catd) -1; - - if (__open_catalog (cat_name, nlspath, env_var, result) != 0) + { + /* We cannot get enough memory. */ + result = (nl_catd) -1; + } + else if (__open_catalog (cat_name, nlspath, env_var, result) != 0) { /* Couldn't open the file. */ free ((void *) result); - return (nl_catd) -1; + result = (nl_catd) -1; } + free (tmp); return (nl_catd) result; } diff --git a/catgets/open_catalog.c b/catgets/open_catalog.c index e069416..9f4d776 100644 --- a/catgets/open_catalog.c +++ b/catgets/open_catalog.c @@ -47,6 +47,7 @@ __open_catalog (const char *cat_name, const char *nlspath, const char *env_var, size_t tab_size; const char *lastp; int result = -1; + char *buf = NULL; if (strchr (cat_name, '/') != NULL || nlspath == NULL) fd = open_not_cancel_2 (cat_name, O_RDONLY); @@ -57,23 +58,23 @@ __open_catalog (const char *cat_name, const char *nlspath, const char *env_var, if (__glibc_unlikely (bufact + (n) >= bufmax)) \ { \ char *old_buf = buf; \ - bufmax += 256 + (n); \ - buf = (char *) alloca (bufmax); \ - memcpy (buf, old_buf, bufact); \ + bufmax += (bufmax < 256 + (n)) ? 256 + (n) : bufmax; \ + buf = realloc (buf, bufmax); \ + if (__glibc_unlikely (buf == NULL)) \ + { \ + free (old_buf); \ + return -1; \ + } \ } /* The RUN_NLSPATH variable contains a colon separated list of descriptions where we expect to find catalogs. We have to recognize certain % substitutions and stop when we found the first existing file. */ - char *buf; size_t bufact; - size_t bufmax; + size_t bufmax = 0; size_t len; - buf = NULL; - bufmax = 0; - fd = -1; while (*run_nlspath != '\0') { @@ -188,7 +189,10 @@ __open_catalog (const char *cat_name, const char *nlspath, const char *env_var, /* Avoid dealing with directories and block devices */ if (__builtin_expect (fd, 0) < 0) - return -1; + { + free (buf); + return -1; + } if (__builtin_expect (__fxstat64 (_STAT_VER, fd, &st), 0) < 0) goto close_unlock_return; @@ -325,6 +329,7 @@ __open_catalog (const char *cat_name, const char *nlspath, const char *env_var, /* Release the lock again. */ close_unlock_return: close_not_cancel_no_status (fd); + free (buf); return result; } diff --git a/catgets/tst-catgets.c b/catgets/tst-catgets.c index a0a4089..0886938 100644 --- a/catgets/tst-catgets.c +++ b/catgets/tst-catgets.c @@ -1,7 +1,10 @@ +#include #include #include #include +#include #include +#include static const char *msgs[] = @@ -12,6 +15,33 @@ static const char *msgs[] = }; #define nmsgs (sizeof (msgs) / sizeof (msgs[0])) + +/* Test for unbounded alloca. */ +static int +do_bz17905 (void) +{ + char *buf; + struct rlimit rl; + nl_catd result; + + const int sz = 1024 * 1024; + + getrlimit (RLIMIT_STACK, &rl); + rl.rlim_cur = sz; + setrlimit (RLIMIT_STACK, &rl); + + buf = malloc (sz + 1); + memset (buf, 'A', sz); + buf[sz] = '\0'; + setenv ("NLSPATH", buf, 1); + + result = catopen (buf, NL_CAT_LOCALE); + assert (result == (nl_catd) -1); + + free (buf); + return 0; +} + #define ROUNDS 5 static int @@ -62,6 +92,7 @@ do_test (void) } } + result += do_bz17905 (); return result; } diff --git a/config.make.in b/config.make.in index a9f5696..46cd9bb 100644 --- a/config.make.in +++ b/config.make.in @@ -51,6 +51,7 @@ have-z-combreloc = @libc_cv_z_combreloc@ have-z-execstack = @libc_cv_z_execstack@ have-Bgroup = @libc_cv_Bgroup@ have-protected-data = @libc_cv_protected_data@ +have-glob-dat-reloc = @libc_cv_has_glob_dat@ with-fp = @with_fp@ old-glibc-headers = @old_glibc_headers@ unwind-find-fde = @libc_cv_gcc_unwind_find_fde@ diff --git a/configure b/configure index 45cc7cb..4f87b31 100755 --- a/configure +++ b/configure @@ -628,6 +628,7 @@ gnu89_inline libc_cv_ssp fno_unit_at_a_time libc_cv_output_format +libc_cv_has_glob_dat libc_cv_hashstyle libc_cv_fpie libc_cv_z_execstack @@ -6335,6 +6336,39 @@ $as_echo "$libc_cv_use_default_link" >&6; } use_default_link=$libc_cv_use_default_link fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GLOB_DAT reloc" >&5 +$as_echo_n "checking for GLOB_DAT reloc... " >&6; } +if ${libc_cv_has_glob_dat+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat > conftest.c <&5 + (eval $ac_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; } +then + if $READELF -rW conftest.so | grep '_GLOB_DAT' > /dev/null; then + libc_cv_has_glob_dat=yes + else + libc_cv_has_glob_dat=no + fi +else + libc_cv_has_glob_dat=no +fi +rm -f conftest* +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_has_glob_dat" >&5 +$as_echo "$libc_cv_has_glob_dat" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking linker output format" >&5 $as_echo_n "checking linker output format... " >&6; } if ${libc_cv_output_format+:} false; then : diff --git a/configure.ac b/configure.ac index 7e9383a..8be612d 100644 --- a/configure.ac +++ b/configure.ac @@ -1535,6 +1535,29 @@ $ac_try" use_default_link=$libc_cv_use_default_link fi +AC_CACHE_CHECK(for GLOB_DAT reloc, + libc_cv_has_glob_dat, [dnl +cat > conftest.c <&AS_MESSAGE_LOG_FD]) +then +dnl look for GLOB_DAT relocation. + if $READELF -rW conftest.so | grep '_GLOB_DAT' > /dev/null; then + libc_cv_has_glob_dat=yes + else + libc_cv_has_glob_dat=no + fi +else + libc_cv_has_glob_dat=no +fi +rm -f conftest*]) +AC_SUBST(libc_cv_has_glob_dat) + AC_CACHE_CHECK(linker output format, libc_cv_output_format, [dnl if libc_cv_output_format=` ${CC-cc} -nostartfiles -nostdlib -Wl,--print-output-format 2>&AS_MESSAGE_LOG_FD` diff --git a/elf/Makefile b/elf/Makefile index 4ceeaf8..a2c43bc 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -148,7 +148,8 @@ tests += loadtest restest1 preloadtest loadfail multiload origtest resolvfail \ tst-unique1 tst-unique2 $(if $(CXX),tst-unique3 tst-unique4 \ tst-nodelete) \ tst-initorder tst-initorder2 tst-relsort1 tst-null-argv \ - tst-ptrguard1 tst-tlsalign tst-tlsalign-extern tst-nodelete-opened + tst-ptrguard1 tst-tlsalign tst-tlsalign-extern tst-nodelete-opened \ + tst-nodelete2 # reldep9 ifeq ($(build-hardcoded-path-in-tests),yes) tests += tst-dlopen-aout @@ -218,7 +219,7 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \ tst-initorder2d \ tst-relsort1mod1 tst-relsort1mod2 tst-array2dep \ tst-array5dep tst-null-argv-lib \ - tst-tlsalign-lib tst-nodelete-opened-lib + tst-tlsalign-lib tst-nodelete-opened-lib tst-nodelete2mod ifeq (yes,$(have-protected-data)) modules-names += tst-protected1moda tst-protected1modb tests += tst-protected1a tst-protected1b @@ -292,6 +293,13 @@ check-abi: $(objpfx)check-abi-ld.out tests-special += $(objpfx)check-abi-ld.out update-abi: update-abi-ld +ifeq ($(have-glob-dat-reloc),yes) +tests += tst-prelink +ifeq ($(run-built-tests),yes) +tests-special += $(objpfx)tst-prelink-cmp.out +endif +endif + include ../Rules ifeq (yes,$(build-shared)) @@ -594,6 +602,7 @@ tst-auditmod9b.so-no-z-defs = yes tst-nodelete-uniquemod.so-no-z-defs = yes tst-nodelete-rtldmod.so-no-z-defs = yes tst-nodelete-zmod.so-no-z-defs = yes +tst-nodelete2mod.so-no-z-defs = yes ifeq ($(build-shared),yes) # Build all the modules even when not actually running test programs. @@ -1164,6 +1173,11 @@ $(objpfx)tst-nodelete.out: $(objpfx)tst-nodelete-uniquemod.so \ LDFLAGS-tst-nodelete = -rdynamic LDFLAGS-tst-nodelete-zmod.so = -Wl,--enable-new-dtags,-z,nodelete +$(objpfx)tst-nodelete2: $(libdl) +$(objpfx)tst-nodelete2.out: $(objpfx)tst-nodelete2mod.so + +LDFLAGS-tst-nodelete2 = -rdynamic + $(objpfx)tst-initorder-cmp.out: tst-initorder.exp $(objpfx)tst-initorder.out cmp $^ > $@; \ $(evaluate-test) @@ -1205,3 +1219,13 @@ $(objpfx)tst-unused-dep.out: $(objpfx)testobj1.so $(objpfx)tst-unused-dep-cmp.out: $(objpfx)tst-unused-dep.out cmp $< /dev/null > $@; \ $(evaluate-test) + +tst-prelink-ENV = LD_TRACE_PRELINKING=1 + +$(objpfx)tst-prelink-conflict.out: $(objpfx)tst-prelink.out + grep stdout $< | grep conflict | $(AWK) '{ print $$10, $$11 }' > $@ + +$(objpfx)tst-prelink-cmp.out: tst-prelink.exp \ + $(objpfx)tst-prelink-conflict.out + cmp $^ > $@; \ + $(evaluate-test) diff --git a/elf/dl-close.c b/elf/dl-close.c index 9105277..c897247 100644 --- a/elf/dl-close.c +++ b/elf/dl-close.c @@ -144,6 +144,14 @@ _dl_close_worker (struct link_map *map, bool force) char done[nloaded]; struct link_map *maps[nloaded]; + /* Clear DF_1_NODELETE to force object deletion. We don't need to touch + l_tls_dtor_count because forced object deletion only happens when an + error occurs during object load. Destructor registration for TLS + non-POD objects should not have happened till then for this + object. */ + if (force) + map->l_flags_1 &= ~DF_1_NODELETE; + /* Run over the list and assign indexes to the link maps and enter them into the MAPS array. */ int idx = 0; @@ -153,13 +161,6 @@ _dl_close_worker (struct link_map *map, bool force) maps[idx] = l; ++idx; - /* Clear DF_1_NODELETE to force object deletion. We don't need to touch - l_tls_dtor_count because forced object deletion only happens when an - error occurs during object load. Destructor registration for TLS - non-POD objects should not have happened till then for this - object. */ - if (force) - l->l_flags_1 &= ~DF_1_NODELETE; } assert (idx == nloaded); diff --git a/elf/dl-load.c b/elf/dl-load.c index 0c052e4..7e6f4c5 100644 --- a/elf/dl-load.c +++ b/elf/dl-load.c @@ -42,6 +42,7 @@ #include #include #include +#include #include @@ -1471,9 +1472,13 @@ print_search_path (struct r_search_path_elem **list, ignore only ELF files for other architectures. Non-ELF files and ELF files with different header information cause fatal errors since this could mean there is something wrong in the installation and the - user might want to know about this. */ + user might want to know about this. + + If FD is not -1, then the file is already open and FD refers to it. + In that case, FD is consumed for both successful and error returns. */ static int -open_verify (const char *name, struct filebuf *fbp, struct link_map *loader, +open_verify (const char *name, int fd, + struct filebuf *fbp, struct link_map *loader, int whatcode, int mode, bool *found_other_class, bool free_name) { /* This is the expected ELF header. */ @@ -1514,6 +1519,7 @@ open_verify (const char *name, struct filebuf *fbp, struct link_map *loader, if (__glibc_unlikely (GLRO(dl_naudit) > 0) && whatcode != 0 && loader->l_auditing == 0) { + const char *original_name = name; struct audit_ifaces *afct = GLRO(dl_audit); for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) { @@ -1528,11 +1534,21 @@ open_verify (const char *name, struct filebuf *fbp, struct link_map *loader, afct = afct->next; } + + if (fd != -1 && name != original_name && strcmp (name, original_name)) + { + /* An audit library changed what we're supposed to open, + so FD no longer matches it. */ + __close (fd); + fd = -1; + } } #endif - /* Open the file. We always open files read-only. */ - int fd = __open (name, O_RDONLY | O_CLOEXEC); + if (fd == -1) + /* Open the file. We always open files read-only. */ + fd = __open (name, O_RDONLY | O_CLOEXEC); + if (fd != -1) { ElfW(Ehdr) *ehdr; @@ -1801,7 +1817,7 @@ open_path (const char *name, size_t namelen, int mode, if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_LIBS)) _dl_debug_printf (" trying file=%s\n", buf); - fd = open_verify (buf, fbp, loader, whatcode, mode, + fd = open_verify (buf, -1, fbp, loader, whatcode, mode, found_other_class, false); if (this_dir->status[cnt] == unknown) { @@ -2041,6 +2057,20 @@ _dl_map_object (struct link_map *loader, const char *name, &loader->l_runpath_dirs, &realname, &fb, loader, LA_SER_RUNPATH, &found_other_class); + if (fd == -1) + { + realname = _dl_sysdep_open_object (name, namelen, &fd); + if (realname != NULL) + { + fd = open_verify (realname, fd, + &fb, loader ?: GL(dl_ns)[nsid]._ns_loaded, + LA_SER_CONFIG, mode, &found_other_class, + false); + if (fd == -1) + free (realname); + } + } + #ifdef USE_LDCONFIG if (fd == -1 && (__glibc_likely ((mode & __RTLD_SECURE) == 0) @@ -2086,7 +2116,7 @@ _dl_map_object (struct link_map *loader, const char *name, if (cached != NULL) { - fd = open_verify (cached, + fd = open_verify (cached, -1, &fb, loader ?: GL(dl_ns)[nsid]._ns_loaded, LA_SER_CONFIG, mode, &found_other_class, false); @@ -2121,7 +2151,7 @@ _dl_map_object (struct link_map *loader, const char *name, fd = -1; else { - fd = open_verify (realname, &fb, + fd = open_verify (realname, -1, &fb, loader ?: GL(dl_ns)[nsid]._ns_loaded, 0, mode, &found_other_class, true); if (__glibc_unlikely (fd == -1)) diff --git a/elf/dl-lookup.c b/elf/dl-lookup.c index 11cb44b..acf5280 100644 --- a/elf/dl-lookup.c +++ b/elf/dl-lookup.c @@ -1016,6 +1016,18 @@ _dl_debug_bindings (const char *undef_name, struct link_map *undef_map, #ifdef SHARED if (GLRO(dl_debug_mask) & DL_DEBUG_PRELINK) { +/* ELF_RTYPE_CLASS_XXX must match RTYPE_CLASS_XXX used by prelink with + LD_TRACE_PRELINKING. */ +#define RTYPE_CLASS_VALID 8 +#define RTYPE_CLASS_PLT (8|1) +#define RTYPE_CLASS_COPY (8|2) +#define RTYPE_CLASS_TLS (8|4) +#if ELF_RTYPE_CLASS_PLT != 0 && ELF_RTYPE_CLASS_PLT != 1 +# error ELF_RTYPE_CLASS_PLT must be 0 or 1! +#endif +#if ELF_RTYPE_CLASS_COPY != 0 && ELF_RTYPE_CLASS_COPY != 2 +# error ELF_RTYPE_CLASS_COPY must be 0 or 2! +#endif int conflict = 0; struct sym_val val = { NULL, NULL }; @@ -1071,12 +1083,17 @@ _dl_debug_bindings (const char *undef_name, struct link_map *undef_map, if (value->s) { + /* Keep only ELF_RTYPE_CLASS_PLT and ELF_RTYPE_CLASS_COPY + bits since since prelink only uses them. */ + type_class &= ELF_RTYPE_CLASS_PLT | ELF_RTYPE_CLASS_COPY; if (__glibc_unlikely (ELFW(ST_TYPE) (value->s->st_info) == STT_TLS)) - type_class = 4; + /* Clear the RTYPE_CLASS_VALID bit in RTYPE_CLASS_TLS. */ + type_class = RTYPE_CLASS_TLS & ~RTYPE_CLASS_VALID; else if (__glibc_unlikely (ELFW(ST_TYPE) (value->s->st_info) == STT_GNU_IFUNC)) - type_class |= 8; + /* Set the RTYPE_CLASS_VALID bit. */ + type_class |= RTYPE_CLASS_VALID; } if (conflict diff --git a/elf/dl-sysdep-open.h b/elf/dl-sysdep-open.h new file mode 100644 index 0000000..a63d9f5 --- /dev/null +++ b/elf/dl-sysdep-open.h @@ -0,0 +1,45 @@ +/* System-specific call to open a shared object by name. Stub version. + Copyright (C) 2015 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#ifndef _DL_SYSDEP_OPEN_H +#define _DL_SYSDEP_OPEN_H 1 + +#include +#include + +/* NAME is a name without slashes, as it appears in a DT_NEEDED entry + or a dlopen call's argument or suchlike. NAMELEN is (strlen (NAME) + 1). + + Find NAME in an OS-dependent fashion, and return its "real" name. + Optionally fill in *FD with a file descriptor open on that file (or + else leave its initial value of -1). The return value is a new + malloc'd string, which will be free'd by the caller. If NAME is + resolved to an actual file that can be opened, then the return + value should name that file (and if *FD was not set, then a normal + __open call on that string will be made). If *FD was set by some + other means than a normal open and there is no "real" name to use, + then __strdup (NAME) is fine (modulo error checking). */ + +static inline char * +_dl_sysdep_open_object (const char *name, size_t namelen, int *fd) +{ + assert (*fd == -1); + return NULL; +} + +#endif /* dl-sysdep-open.h */ diff --git a/elf/rtld.c b/elf/rtld.c index 69873c2..07e741c 100644 --- a/elf/rtld.c +++ b/elf/rtld.c @@ -162,7 +162,6 @@ struct rtld_global_ro _rtld_global_ro attribute_relro = ._dl_hwcap_mask = HWCAP_IMPORTANT, ._dl_lazy = 1, ._dl_fpu_control = _FPU_DEFAULT, - ._dl_pointer_guard = 1, ._dl_pagesize = EXEC_PAGESIZE, ._dl_inhibit_cache = 0, @@ -709,15 +708,12 @@ security_init (void) #endif /* Set up the pointer guard as well, if necessary. */ - if (GLRO(dl_pointer_guard)) - { - uintptr_t pointer_chk_guard = _dl_setup_pointer_guard (_dl_random, - stack_chk_guard); + uintptr_t pointer_chk_guard + = _dl_setup_pointer_guard (_dl_random, stack_chk_guard); #ifdef THREAD_SET_POINTER_GUARD - THREAD_SET_POINTER_GUARD (pointer_chk_guard); + THREAD_SET_POINTER_GUARD (pointer_chk_guard); #endif - __pointer_chk_guard_local = pointer_chk_guard; - } + __pointer_chk_guard_local = pointer_chk_guard; /* We do not need the _dl_random value anymore. The less information we leave behind, the better, so clear the @@ -2471,9 +2467,6 @@ process_envvars (enum mode *modep) GLRO(dl_use_load_bias) = envline[14] == '1' ? -1 : 0; break; } - - if (memcmp (envline, "POINTER_GUARD", 13) == 0) - GLRO(dl_pointer_guard) = envline[14] != '0'; break; case 14: diff --git a/elf/tst-nodelete2.c b/elf/tst-nodelete2.c new file mode 100644 index 0000000..388e8af --- /dev/null +++ b/elf/tst-nodelete2.c @@ -0,0 +1,37 @@ +#include "../dlfcn/dlfcn.h" +#include +#include +#include + +static int +do_test (void) +{ + int result = 0; + + printf ("\nOpening pthread library.\n"); + void *pthread = dlopen (LIBPTHREAD_SO, RTLD_LAZY); + + /* This is a test for correct DF_1_NODELETE clearing when dlopen failure + happens. We should clear DF_1_NODELETE for failed library only, because + doing this for others (e.g. libpthread) might cause them to be unloaded, + that may lead to some global references (e.g. __rtld_lock_unlock) to be + broken. The dlopen should fail because of undefined symbols in shared + library, that cause DF_1_NODELETE to be cleared. For libpthread, this + flag should be set, because if not, SIGSEGV will happen in dlclose. */ + if (dlopen ("tst-nodelete2mod.so", RTLD_NOW) != NULL) + { + printf ("Unique symbols test failed\n"); + result = 1; + } + + if (pthread) + dlclose (pthread); + + if (result == 0) + printf ("SUCCESS\n"); + + return result; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/elf/tst-nodelete2mod.c b/elf/tst-nodelete2mod.c new file mode 100644 index 0000000..e88c756 --- /dev/null +++ b/elf/tst-nodelete2mod.c @@ -0,0 +1,7 @@ +/* Undefined symbol. */ +extern int not_exist (void); + +int foo (void) +{ + return not_exist (); +} diff --git a/elf/tst-prelink.c b/elf/tst-prelink.c new file mode 100644 index 0000000..ab61c4e --- /dev/null +++ b/elf/tst-prelink.c @@ -0,0 +1,30 @@ +/* Test the output from the environment variable, LD_TRACE_PRELINKING, + for prelink. + Copyright (C) 2015 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include + +static int +do_test (void) +{ + fprintf (stdout, "hello\n"); + return 0; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/elf/tst-prelink.exp b/elf/tst-prelink.exp new file mode 100644 index 0000000..b35b4c9 --- /dev/null +++ b/elf/tst-prelink.exp @@ -0,0 +1 @@ +/0 stdout diff --git a/elf/tst-znodelete-zlib.cc b/elf/tst-znodelete-zlib.cc deleted file mode 100644 index 1e8f368..0000000 --- a/elf/tst-znodelete-zlib.cc +++ /dev/null @@ -1,6 +0,0 @@ -extern int not_exist (void); - -int foo (void) -{ - return not_exist (); -} diff --git a/io/test-lfs.c b/io/test-lfs.c index 539c2a2..b6ebae4 100644 --- a/io/test-lfs.c +++ b/io/test-lfs.c @@ -144,7 +144,7 @@ test_ftello (void) int do_test (int argc, char *argv[]) { - int ret; + int ret, fd2; struct stat64 statbuf; ret = lseek64 (fd, TWO_GB+100, SEEK_SET); @@ -195,6 +195,25 @@ do_test (int argc, char *argv[]) error (EXIT_FAILURE, 0, "stat reported size %lld instead of %lld.", (long long int) statbuf.st_size, (TWO_GB + 100 + 5)); + fd2 = openat64 (AT_FDCWD, name, O_RDWR); + if (fd2 == -1) + { + if (errno == ENOSYS) + { + /* Silently ignore this test. */ + error (0, 0, "openat64 is not supported"); + } + else + error (EXIT_FAILURE, errno, "openat64 failed to open big file"); + } + else + { + ret = close (fd2); + + if (ret == -1) + error (EXIT_FAILURE, errno, "error closing file"); + } + test_ftello (); return 0; diff --git a/locale/C-collate.c b/locale/C-collate.c index d7f3c55..06dfdfa 100644 --- a/locale/C-collate.c +++ b/locale/C-collate.c @@ -144,8 +144,6 @@ const struct __locale_data _nl_C_LC_COLLATE attribute_hidden = /* _NL_COLLATE_COLLSEQWC */ { .string = (const char *) collseqwc }, /* _NL_COLLATE_CODESET */ - { .string = _nl_C_codeset }, - /* _NL_COLLATE_ENCODING_TYPE */ - { .word = __cet_8bit } + { .string = _nl_C_codeset } } }; diff --git a/locale/categories.def b/locale/categories.def index 045489d..a8dda53 100644 --- a/locale/categories.def +++ b/locale/categories.def @@ -58,7 +58,6 @@ DEFINE_CATEGORY DEFINE_ELEMENT (_NL_COLLATE_COLLSEQMB, "collate-collseqmb", std, wstring) DEFINE_ELEMENT (_NL_COLLATE_COLLSEQWC, "collate-collseqwc", std, wstring) DEFINE_ELEMENT (_NL_COLLATE_CODESET, "collate-codeset", std, string) - DEFINE_ELEMENT (_NL_COLLATE_ENCODING_TYPE, "collate-encoding-type", std, word) ), NO_POSTLOAD) diff --git a/locale/langinfo.h b/locale/langinfo.h index ffc5c7f..a565d9d 100644 --- a/locale/langinfo.h +++ b/locale/langinfo.h @@ -255,7 +255,6 @@ enum _NL_COLLATE_COLLSEQMB, _NL_COLLATE_COLLSEQWC, _NL_COLLATE_CODESET, - _NL_COLLATE_ENCODING_TYPE, _NL_NUM_LC_COLLATE, /* LC_CTYPE category: character classification. diff --git a/locale/loadlocale.c b/locale/loadlocale.c index fdba6e9..dcbb833 100644 --- a/locale/loadlocale.c +++ b/locale/loadlocale.c @@ -121,9 +121,10 @@ _nl_intern_locale_data (int category, const void *data, size_t datasize) switch (category) { #define CATTEST(cat) \ - case LC_##cat: \ - assert (cnt < (sizeof (_nl_value_type_LC_##cat) \ - / sizeof (_nl_value_type_LC_##cat[0]))); \ + case LC_##cat: \ + if (cnt >= (sizeof (_nl_value_type_LC_##cat) \ + / sizeof (_nl_value_type_LC_##cat[0]))) \ + goto puntdata; \ break CATTEST (NUMERIC); CATTEST (TIME); diff --git a/locale/localeinfo.h b/locale/localeinfo.h index bdab9fe..1d2ee00 100644 --- a/locale/localeinfo.h +++ b/locale/localeinfo.h @@ -110,14 +110,6 @@ enum coll_sort_rule sort_mask }; -/* Collation encoding type. */ -enum collation_encoding_type -{ - __cet_other, - __cet_8bit, - __cet_utf8 -}; - /* We can map the types of the entries into a few categories. */ enum value_type { diff --git a/locale/programs/ld-collate.c b/locale/programs/ld-collate.c index a39a94f..dc0fe30 100644 --- a/locale/programs/ld-collate.c +++ b/locale/programs/ld-collate.c @@ -32,7 +32,6 @@ #include "linereader.h" #include "locfile.h" #include "elem-hash.h" -#include "../localeinfo.h" /* Uncomment the following line in the production version. */ /* #define NDEBUG 1 */ @@ -2131,8 +2130,6 @@ collate_output (struct localedef_t *locale, const struct charmap_t *charmap, /* The words have to be handled specially. */ if (idx == _NL_ITEM_INDEX (_NL_COLLATE_SYMB_HASH_SIZEMB)) add_locale_uint32 (&file, 0); - else if (idx == _NL_ITEM_INDEX (_NL_COLLATE_ENCODING_TYPE)) - add_locale_uint32 (&file, __cet_other); else add_locale_empty (&file); } @@ -2496,12 +2493,6 @@ collate_output (struct localedef_t *locale, const struct charmap_t *charmap, add_locale_raw_data (&file, collate->mbseqorder, 256); add_locale_collseq_table (&file, &collate->wcseqorder); add_locale_string (&file, charmap->code_set_name); - if (strcmp (charmap->code_set_name, "UTF-8") == 0) - add_locale_uint32 (&file, __cet_utf8); - else if (charmap->mb_cur_max == 1) - add_locale_uint32 (&file, __cet_8bit); - else - add_locale_uint32 (&file, __cet_other); write_locale_data (output_path, LC_COLLATE, "LC_COLLATE", &file); obstack_free (&weightpool, NULL); diff --git a/misc/Makefile b/misc/Makefile index aecb0da..12055ce 100644 --- a/misc/Makefile +++ b/misc/Makefile @@ -76,7 +76,8 @@ install-lib := libg.a gpl2lgpl := error.c error.h tests := tst-dirname tst-tsearch tst-fdset tst-efgcvt tst-mntent tst-hsearch \ - tst-error1 tst-pselect tst-insremque tst-mntent2 bug-hsearch1 + tst-error1 tst-pselect tst-insremque tst-mntent2 bug-hsearch1 \ + tst-mntent-blank-corrupt tst-mntent-blank-passno bug18240 ifeq ($(run-built-tests),yes) tests-special += $(objpfx)tst-error1-mem.out endif diff --git a/misc/bug18240.c b/misc/bug18240.c new file mode 100644 index 0000000..773586e --- /dev/null +++ b/misc/bug18240.c @@ -0,0 +1,97 @@ +/* Test integer wraparound in hcreate. + Copyright (C) 2016 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include +#include +#include +#include +#include +#include +#include + +static void +test_size (size_t size) +{ + int res = hcreate (size); + if (res == 0) + { + if (errno == ENOMEM) + return; + printf ("error: hcreate (%zu): %m\n", size); + exit (1); + } + char *keys[100]; + for (int i = 0; i < 100; ++i) + { + if (asprintf (keys + i, "%d", i) < 0) + { + printf ("error: asprintf: %m\n"); + exit (1); + } + ENTRY e = { keys[i], (char *) "value" }; + if (hsearch (e, ENTER) == NULL) + { + printf ("error: hsearch (\"%s\"): %m\n", keys[i]); + exit (1); + } + } + hdestroy (); + + for (int i = 0; i < 100; ++i) + free (keys[i]); +} + +static int +do_test (void) +{ + /* Limit the size of the process, so that memory allocation will + fail without impacting the entire system. */ + { + struct rlimit limit; + if (getrlimit (RLIMIT_AS, &limit) != 0) + { + printf ("getrlimit (RLIMIT_AS) failed: %m\n"); + return 1; + } + long target = 100 * 1024 * 1024; + if (limit.rlim_cur == RLIM_INFINITY || limit.rlim_cur > target) + { + limit.rlim_cur = target; + if (setrlimit (RLIMIT_AS, &limit) != 0) + { + printf ("setrlimit (RLIMIT_AS) failed: %m\n"); + return 1; + } + } + } + + test_size (500); + test_size (-1); + test_size (-3); + test_size (INT_MAX - 2); + test_size (INT_MAX - 1); + test_size (INT_MAX); + test_size (((unsigned) INT_MAX) + 1); + test_size (UINT_MAX - 2); + test_size (UINT_MAX - 1); + test_size (UINT_MAX); + return 0; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/misc/hsearch_r.c b/misc/hsearch_r.c index 9f55e84..661f0f6 100644 --- a/misc/hsearch_r.c +++ b/misc/hsearch_r.c @@ -19,7 +19,7 @@ #include #include #include - +#include #include /* [Aho,Sethi,Ullman] Compilers: Principles, Techniques and Tools, 1986 @@ -46,15 +46,12 @@ static int isprime (unsigned int number) { /* no even number will be passed */ - unsigned int div = 3; - - while (div * div < number && number % div != 0) - div += 2; - - return number % div != 0; + for (unsigned int div = 3; div <= number / div; div += 2) + if (number % div == 0) + return 0; + return 1; } - /* Before using the hash table we must allocate memory for it. Test for an existing table are done. We allocate one element more as the found prime number says. This is done for more effective @@ -81,10 +78,19 @@ __hcreate_r (nel, htab) use will not work. */ if (nel < 3) nel = 3; - /* Change nel to the first prime number not smaller as nel. */ - nel |= 1; /* make odd */ - while (!isprime (nel)) - nel += 2; + + /* Change nel to the first prime number in the range [nel, UINT_MAX - 2], + The '- 2' means 'nel += 2' cannot overflow. */ + for (nel |= 1; ; nel += 2) + { + if (UINT_MAX - 2 < nel) + { + __set_errno (ENOMEM); + return 0; + } + if (isprime (nel)) + break; + } htab->size = nel; htab->filled = 0; diff --git a/misc/mntent_r.c b/misc/mntent_r.c index 6159873..4f26998 100644 --- a/misc/mntent_r.c +++ b/misc/mntent_r.c @@ -136,7 +136,9 @@ __getmntent_r (FILE *stream, struct mntent *mp, char *buffer, int bufsiz) end_ptr = strchr (buffer, '\n'); if (end_ptr != NULL) /* chop newline */ { - while (end_ptr[-1] == ' ' || end_ptr[-1] == '\t') + /* Do not walk past the start of buffer if it's all whitespace. */ + while (end_ptr != buffer + && (end_ptr[-1] == ' ' || end_ptr[-1] == '\t')) end_ptr--; *end_ptr = '\0'; } diff --git a/misc/regexp.h b/misc/regexp.h index 3460989..42394f7 100644 --- a/misc/regexp.h +++ b/misc/regexp.h @@ -19,10 +19,11 @@ #ifndef _REGEXP_H #define _REGEXP_H 1 -/* The contents of this header file were standardized in the - Single Unix Specification, Version 2 (1997) but marked as - LEGACY; new applications were already being encouraged to - use instead. POSIX.1-2001 removed this header. +/* The contents of this header file were originally standardized in + the Single Unix Specification, Issue 3 (1992). In Issue 4 (1994) + the header was marked as TO BE WITHDRAWN, and new applications + were encouraged to use instead. It was officially + withdrawn from the standard in Issue 6 (aka POSIX.1-2001). This header is provided only for backward compatibility. It will be removed in the next release of the GNU C Library. diff --git a/misc/sys/param.h b/misc/sys/param.h index 62b7ed2..1908b93 100644 --- a/misc/sys/param.h +++ b/misc/sys/param.h @@ -50,6 +50,9 @@ #if !defined NOFILE && defined OPEN_MAX # define NOFILE OPEN_MAX #endif +#if !defined MAXHOSTNAMELEN && defined HOST_NAME_MAX +# define MAXHOSTNAMELEN HOST_NAME_MAX +#endif #ifndef NCARGS # ifdef ARG_MAX # define NCARGS ARG_MAX diff --git a/misc/tst-mntent-blank-corrupt.c b/misc/tst-mntent-blank-corrupt.c new file mode 100644 index 0000000..92266a3 --- /dev/null +++ b/misc/tst-mntent-blank-corrupt.c @@ -0,0 +1,45 @@ +/* Make sure blank lines does not cause memory corruption BZ #18887. + + Copyright (C) 2009-2015 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include +#include +#include + +/* Make sure blank lines don't trigger memory corruption. This doesn't happen + for all targets though, so it's a best effort test BZ #18887. */ +static int +do_test (void) +{ + FILE *fp; + + fp = tmpfile (); + fputs ("\n \n/foo\\040dir /bar\\040dir auto bind \t \n", fp); + rewind (fp); + + /* The corruption happens here ... */ + getmntent (fp); + /* ... but trigers here. */ + endmntent (fp); + + /* If the test failed, we would crash, and not hit this point. */ + return 0; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/misc/tst-mntent-blank-passno.c b/misc/tst-mntent-blank-passno.c new file mode 100644 index 0000000..fc04291 --- /dev/null +++ b/misc/tst-mntent-blank-passno.c @@ -0,0 +1,53 @@ +/* Make sure trailing whitespace is handled properly BZ #17273. + + Copyright (C) 2009-2015 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include +#include +#include + +/* Check entries to make sure trailing whitespace is ignored and we return the + correct passno value BZ #17273. */ +static int +do_test (void) +{ + int result = 0; + FILE *fp; + struct mntent *mnt; + + fp = tmpfile (); + fputs ("/foo\\040dir /bar\\040dir auto bind \t \n", fp); + rewind (fp); + + mnt = getmntent (fp); + if (strcmp (mnt->mnt_fsname, "/foo dir") != 0 + || strcmp (mnt->mnt_dir, "/bar dir") != 0 + || strcmp (mnt->mnt_type, "auto") != 0 + || strcmp (mnt->mnt_opts, "bind") != 0 + || mnt->mnt_freq != 0 + || mnt->mnt_passno != 0) + { + puts ("Error while reading entry with trailing whitespaces"); + result = 1; + } + + return result; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/misc/tst-mntent.c b/misc/tst-mntent.c index 876c89f..820b354 100644 --- a/misc/tst-mntent.c +++ b/misc/tst-mntent.c @@ -73,26 +73,6 @@ main (int argc, char *argv[]) puts ("Error while reading written entry back in"); result = 1; } - - /* Part III: Entry with whitespaces at the end of a line. */ - rewind (fp); - - fputs ("/foo\\040dir /bar\\040dir auto bind \t \n", fp); - - rewind (fp); - - mnt = getmntent (fp); - - if (strcmp (mnt->mnt_fsname, "/foo dir") != 0 - || strcmp (mnt->mnt_dir, "/bar dir") != 0 - || strcmp (mnt->mnt_type, "auto") != 0 - || strcmp (mnt->mnt_opts, "bind") != 0 - || mnt->mnt_freq != 0 - || mnt->mnt_passno != 0) - { - puts ("Error while reading entry with trailing whitespaces"); - result = 1; - } } return result; diff --git a/scripts/test-installation.pl b/scripts/test-installation.pl index cac1562..79b2b3e 100755 --- a/scripts/test-installation.pl +++ b/scripts/test-installation.pl @@ -80,16 +80,25 @@ arglist: while (@ARGV) { # We expect none or one argument. if ($#ARGV == -1) { $soversions="soversions.mk"; + $config="config.make"; } elsif ($#ARGV == 0) { if (-d $ARGV[0]) { $soversions = "$ARGV[0]/soversions.mk"; + $config = "$ARGV[0]/config.make"; } else { - $soversions = $ARGV[0]; + $soversions = $dir = $ARGV[0]; + $dir =~ s!/?[^/]*/*$!!; + $config = $dir . "/config.make"; } } else { die "Wrong number of arguments."; } +if (system ("grep -q \"build-mathvec = yes\" $config") == 0) { + $build_mathvec = 1; +} else { + $build_mathvec = 0; +} # Read names and versions of all shared libraries that are part of # glibc @@ -111,6 +120,8 @@ while () { # - libthread_db since it contains unresolved references # - it's just a test NSS module # - We don't provide the libgcc so we don't test it + # - libmvec if it wasn't built + next if ($build_mathvec == 0 && $name eq "mvec"); if ($name ne "nss_ldap" && $name ne "db1" && !($name =~/^nss1_/) && $name ne "thread_db" && $name ne "nss_test1" && $name ne "libgcc_s") { diff --git a/stdlib/cxa_thread_atexit_impl.c b/stdlib/cxa_thread_atexit_impl.c index 2d5d56a..5717f09 100644 --- a/stdlib/cxa_thread_atexit_impl.c +++ b/stdlib/cxa_thread_atexit_impl.c @@ -98,6 +98,10 @@ static __thread struct link_map *lm_cache; int __cxa_thread_atexit_impl (dtor_func func, void *obj, void *dso_symbol) { +#ifdef PTR_MANGLE + PTR_MANGLE (func); +#endif + /* Prepend. */ struct dtor_list *new = calloc (1, sizeof (struct dtor_list)); new->func = func; @@ -142,9 +146,13 @@ __call_tls_dtors (void) while (tls_dtor_list) { struct dtor_list *cur = tls_dtor_list; + dtor_func func = cur->func; +#ifdef PTR_DEMANGLE + PTR_DEMANGLE (func); +#endif tls_dtor_list = tls_dtor_list->next; - cur->func (cur->obj); + func (cur->obj); /* Ensure that the MAP dereference happens before l_tls_dtor_count decrement. That way, we protect this access from a diff --git a/string/Makefile b/string/Makefile index 8424a61..ebe9354 100644 --- a/string/Makefile +++ b/string/Makefile @@ -54,7 +54,7 @@ tests := tester inl-tester noinl-tester testcopy test-ffs \ tst-strtok tst-strxfrm bug-strcoll1 tst-strfry \ bug-strtok1 $(addprefix test-,$(strop-tests)) \ bug-envz1 tst-strxfrm2 tst-endian tst-svc2 \ - tst-strtok_r + tst-strtok_r bug-strcoll2 xtests = tst-strcoll-overflow @@ -75,4 +75,17 @@ ifeq ($(run-built-tests),yes) $(objpfx)tst-svc-cmp.out: tst-svc.expect $(objpfx)tst-svc.out cmp $^ > $@; \ $(evaluate-test) + +LOCALES := de_DE.UTF-8 en_US.ISO-8859-1 en_US.UTF-8 \ + tr_TR.ISO-8859-9 tr_TR.UTF-8 cs_CZ.UTF-8 \ + da_DK.ISO-8859-1 +include ../gen-locales.mk + +$(objpfx)test-strcasecmp.out: $(gen-locales) +$(objpfx)test-strncasecmp.out: $(gen-locales) +$(objpfx)tst-strxfrm.out: $(gen-locales) +$(objpfx)tst-strxfrm2.out: $(gen-locales) +# bug-strcoll2 needs cs_CZ.UTF-8 and da_DK.ISO-8859-1. +$(objpfx)bug-strcoll2.out: $(gen-locales) + endif diff --git a/string/bug-strcoll2.c b/string/bug-strcoll2.c new file mode 100644 index 0000000..72a9ff2 --- /dev/null +++ b/string/bug-strcoll2.c @@ -0,0 +1,92 @@ +/* Bug 18589: sort-test.sh fails at random. + Copyright (C) 2015 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include +#include +#include + +/* An incorrect strcoll optimization resulted in incorrect + results from strcoll for cs_CZ and da_DK. */ + +int +test_cs_CZ (void) +{ + const char t1[] = "config"; + const char t2[] = "choose"; + if (setlocale (LC_ALL, "cs_CZ.UTF-8") == NULL) + { + perror ("setlocale"); + return 1; + } + /* In Czech the digraph ch sorts after c, therefore we expect + config to sort before choose. */ + int a = strcoll (t1, t2); + int b = strcoll (t2, t1); + printf ("strcoll (\"%s\", \"%s\") = %d\n", t1, t2, a); + printf ("strcoll (\"%s\", \"%s\") = %d\n", t2, t1, b); + if (a < 0 && b > 0) + { + puts ("PASS: config < choose"); + return 0; + } + else + { + puts ("FAIL: Wrong sorting in cs_CZ.UTF-8."); + return 1; + } +} + +int +test_da_DK (void) +{ + const char t1[] = "AS"; + const char t2[] = "AA"; + if (setlocale (LC_ALL, "da_DK.ISO-8859-1") == NULL) + { + perror ("setlocale"); + return 1; + } + /* AA should be treated as the last letter of the Danish alphabet, + hence sorting after AS. */ + int a = strcoll (t1, t2); + int b = strcoll (t2, t1); + printf ("strcoll (\"%s\", \"%s\") = %d\n", t1, t2, a); + printf ("strcoll (\"%s\", \"%s\") = %d\n", t2, t1, b); + if (a < 0 && b > 0) + { + puts ("PASS: AS < AA"); + return 0; + } + else + { + puts ("FAIL: Wrong sorting in da_DK.ISO-8859-1"); + return 1; + } +} + +static int +do_test (void) +{ + int err = 0; + err |= test_cs_CZ (); + err |= test_da_DK (); + return err; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/string/strcoll_l.c b/string/strcoll_l.c index 8f1225f..35bc0e4 100644 --- a/string/strcoll_l.c +++ b/string/strcoll_l.c @@ -29,7 +29,6 @@ # define STRING_TYPE char # define USTRING_TYPE unsigned char # define STRCOLL __strcoll_l -# define STRDIFF __strdiff # define STRCMP strcmp # define WEIGHT_H "../locale/weight.h" # define SUFFIX MB @@ -42,20 +41,6 @@ #include "../locale/localeinfo.h" #include WEIGHT_H -#define MASK_UTF8_7BIT (1 << 7) -#define MASK_UTF8_START (3 << 6) - -size_t -STRDIFF (const STRING_TYPE *s, const STRING_TYPE *t) -{ - size_t n; - - for (n = 0; *s != '\0' && *s++ == *t++; ++n) - continue; - - return n; -} - /* Track status while looking for sequences in a string. */ typedef struct { @@ -269,29 +254,9 @@ STRCOLL (const STRING_TYPE *s1, const STRING_TYPE *s2, __locale_t l) const USTRING_TYPE *extra; const int32_t *indirect; - /* In case there is no locale specific sort order (C / POSIX). */ if (nrules == 0) return STRCMP (s1, s2); - /* Fast forward to the position of the first difference. Needs to be - encoding aware as the byte-by-byte comparison can stop in the middle - of a char sequence for multibyte encodings like UTF-8. */ - uint_fast32_t encoding = - current->values[_NL_ITEM_INDEX (_NL_COLLATE_ENCODING_TYPE)].word; - if (encoding != __cet_other) - { - size_t diff = STRDIFF (s1, s2); - if (diff > 0) - { - if (encoding == __cet_utf8 && (*(s1 + diff) & MASK_UTF8_7BIT) != 0) - do - diff--; - while (diff > 0 && (*(s1 + diff) & MASK_UTF8_START) != MASK_UTF8_START); - s1 += diff; - s2 += diff; - } - } - /* Catch empty strings. */ if (__glibc_unlikely (*s1 == '\0') || __glibc_unlikely (*s2 == '\0')) return (*s1 != '\0') - (*s2 != '\0'); @@ -358,8 +323,7 @@ STRCOLL (const STRING_TYPE *s1, const STRING_TYPE *s2, __locale_t l) byte-level comparison to ensure that we don't waste time going through multiple passes for totally equal strings before proceeding to subsequent passes. */ - if (pass == 0 && encoding == __cet_other && - STRCMP (s1, s2) == 0) + if (pass == 0 && STRCMP (s1, s2) == 0) return result; else break; diff --git a/string/tst-strxfrm2.c b/string/tst-strxfrm2.c index d5a1115..bea5aa2 100644 --- a/string/tst-strxfrm2.c +++ b/string/tst-strxfrm2.c @@ -5,6 +5,8 @@ static int do_test (void) { + static const char test_locale[] = "de_DE.UTF-8"; + int res = 0; char buf[20]; @@ -38,9 +40,9 @@ do_test (void) res = 1; } - if (setlocale (LC_ALL, "de_DE.UTF-8") == NULL) + if (setlocale (LC_ALL, test_locale) == NULL) { - puts ("setlocale failed"); + printf ("cannot set locale \"%s\"\n", test_locale); res = 1; } else diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h index 7a0fe8d..78e3a97 100644 --- a/sysdeps/generic/ldsodefs.h +++ b/sysdeps/generic/ldsodefs.h @@ -592,9 +592,6 @@ struct rtld_global_ro /* List of auditing interfaces. */ struct audit_ifaces *_dl_audit; unsigned int _dl_naudit; - - /* 0 if internal pointer values should not be guarded, 1 if they should. */ - EXTERN int _dl_pointer_guard; }; # define __rtld_global_attribute__ # if IS_IN (rtld) diff --git a/sysdeps/hppa/dl-symaddr.c b/sysdeps/hppa/dl-symaddr.c index b707c19..89d8baf 100644 --- a/sysdeps/hppa/dl-symaddr.c +++ b/sysdeps/hppa/dl-symaddr.c @@ -33,3 +33,4 @@ _dl_symbol_address (struct link_map *map, const ElfW(Sym) *ref) else return (void *) value; } +rtld_hidden_def (_dl_symbol_address) diff --git a/sysdeps/hppa/start.S b/sysdeps/hppa/start.S index 64d8c3e..cc4f243 100644 --- a/sysdeps/hppa/start.S +++ b/sysdeps/hppa/start.S @@ -42,7 +42,11 @@ /* Have the linker create plabel words so we get PLABEL32 relocs and not 21/14. The use of 21/14 relocs is only supported in the latest dynamic linker. */ - .section .rodata +#ifdef SHARED + .section .data.rel.ro,"aw",@progbits +#else + .section .rodata,"a",@progbits +#endif .align 4 .Lpmain: .word P%main @@ -52,6 +56,10 @@ .word P%__libc_csu_fini .Lp__libc_csu_init: .word P%__libc_csu_init +#ifdef SHARED +.Lp__global: + .word $global$ +#endif .text .align 4 @@ -122,10 +130,14 @@ _start: /* void *stack_end (7th argument) */ stw %sp, -60(%sp) +#ifdef SHARED + addil LT'.Lp__global, %r19 + ldw RT'.Lp__global(%r1), %dp +#else /* load global */ ldil L%$global$, %dp ldo R%$global$(%dp), %dp - +#endif bl __libc_start_main,%r2 nop /* die horribly if it returned (it shouldn't) */ diff --git a/sysdeps/nacl/Makefile b/sysdeps/nacl/Makefile index 6749a44..1748886 100644 --- a/sysdeps/nacl/Makefile +++ b/sysdeps/nacl/Makefile @@ -132,4 +132,13 @@ ifeq ($(subdir),misc) # sysdeps/.../linux/ directories, but it's still a sysdeps decision to # install it. sysdep_headers += bits/mman-linux.h + +# This defeats sysdeps/gnu/Makefile's addition of sys/mtio.h, which +# we do not want. This is a total kludge, but it seems no worse for +# now than making the sysdeps/gnu/Makefile code conditional on a +# variable we set here. If some sysdeps/.../Makefile that is later +# in the list than sysdeps/gnu needed to add to sysdep_headers, this +# would break it. But sysdeps/gnu is close to last in the list and +# this coming up seems unlikely. +override sysdep_headers := $(sysdep_headers) endif diff --git a/sysdeps/nacl/dl-map-segments.h b/sysdeps/nacl/dl-map-segments.h index f305da3..f2d5d84 100644 --- a/sysdeps/nacl/dl-map-segments.h +++ b/sysdeps/nacl/dl-map-segments.h @@ -53,7 +53,7 @@ _dl_map_segments (struct link_map *l, int fd, const size_t maplength, bool has_holes, struct link_map *loader) { - if (__builtin_expect (type, ET_DYN) == ET_DYN) + if (__glibc_likely (type == ET_DYN)) { /* This is a position-independent shared object. Let the system choose where to place it. @@ -165,6 +165,32 @@ _dl_map_segments (struct link_map *l, int fd, errno = error; return DL_MAP_SEGMENTS_ERROR_MAP_SEGMENT; } + if (__glibc_unlikely (type != ET_DYN)) + { + /* A successful PROT_EXEC mmap would have implicitly + updated the bookkeeping so that a future + allocate_code_data call would know that this range + of the address space is already occupied. That + doesn't happen implicitly with dyncode_create, so + it's necessary to do an explicit call to update the + bookkeeping. */ + uintptr_t allocated_address; + error = __nacl_irt_code_data_alloc.allocate_code_data + (l->l_addr + c->mapstart, len, 0, 0, &allocated_address); + if (__glibc_unlikely (error)) + { + errno = error; + return DL_MAP_SEGMENTS_ERROR_MAP_SEGMENT; + } + if (__glibc_unlikely + (allocated_address != l->l_addr + c->mapstart)) + { + /* This is not a very helpful error for this case, + but there isn't really anything better to use. */ + errno = ENOMEM; + return DL_MAP_SEGMENTS_ERROR_MAP_SEGMENT; + } + } } else { diff --git a/sysdeps/nacl/dl-sysdep-open.h b/sysdeps/nacl/dl-sysdep-open.h new file mode 100644 index 0000000..38b0f9e --- /dev/null +++ b/sysdeps/nacl/dl-sysdep-open.h @@ -0,0 +1,40 @@ +/* System-specific call to open a shared object by name. NaCl version. + Copyright (C) 2015 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#ifndef _DL_SYSDEP_OPEN_H +#define _DL_SYSDEP_OPEN_H 1 + +#include + +/* NAME is a name without slashes, as it appears in a DT_NEEDED entry + or a dlopen call's argument or suchlike. NAMELEN is (strlen (NAME) + 1). + + Find NAME in an OS-dependent fashion, and return its "real" name. + Optionally fill in *FD with a file descriptor open on that file (or + else leave its initial value of -1). The return value is a new + malloc'd string, which will be free'd by the caller. If NAME is + resolved to an actual file that can be opened, then the return + value should name that file (and if *FD was not set, then a normal + __open call on that string will be made). If *FD was set by some + other means than a normal open and there is no "real" name to use, + then __strdup (NAME) is fine (modulo error checking). */ + +extern char *_dl_sysdep_open_object (const char *name, size_t namelen, int *fd) + internal_function attribute_hidden; + +#endif /* dl-sysdep-open.h */ diff --git a/sysdeps/nacl/dl-sysdep.c b/sysdeps/nacl/dl-sysdep.c index 3e902c2..3a04aa1 100644 --- a/sysdeps/nacl/dl-sysdep.c +++ b/sysdeps/nacl/dl-sysdep.c @@ -87,3 +87,26 @@ _dl_start_user (void (*user_entry) (uint32_t info[]), uint32_t info[]) #endif /* SHARED */ #include + +#include +#include +#include +#include +#include + +char * +internal_function +_dl_sysdep_open_object (const char *name, size_t namelen, int *fd) +{ + int error = __nacl_irt_resource_open.open_resource (name, fd); + if (error) + return NULL; + assert (*fd != -1); + char *realname = __strdup (name); + if (__glibc_unlikely (realname == NULL)) + { + __close (*fd); + *fd = -1; + } + return realname; +} diff --git a/sysdeps/nacl/nacl-interface-list.h b/sysdeps/nacl/nacl-interface-list.h index cb33751..c68faed 100644 --- a/sysdeps/nacl/nacl-interface-list.h +++ b/sysdeps/nacl/nacl-interface-list.h @@ -28,7 +28,7 @@ NACL_MANDATORY_INTERFACE (rtld, NACL_IRT_FUTEX_v0_1, nacl_irt_futex) NACL_MANDATORY_INTERFACE (rtld, NACL_IRT_TLS_v0_1, nacl_irt_tls) -NACL_MANDATORY_INTERFACE (libc, +NACL_MANDATORY_INTERFACE (rtld, NACL_IRT_RESOURCE_OPEN_v0_1, nacl_irt_resource_open) NACL_MANDATORY_INTERFACE (rtld, NACL_IRT_CODE_DATA_ALLOC_v0_1, diff --git a/sysdeps/nacl/start.c b/sysdeps/nacl/start.c index a4b6dd3..8e8bc1a 100644 --- a/sysdeps/nacl/start.c +++ b/sysdeps/nacl/start.c @@ -44,6 +44,10 @@ /* The application defines this, of course. */ extern int main (int argc, char **argv, char **envp); +/* But maybe it defines this too, in which case it takes precedence. */ +extern int __nacl_main (int argc, char **argv, char **envp) + __attribute__ ((weak)); + /* These are defined in libc. */ extern int __libc_csu_init (int argc, char **argv, char **envp); extern void __libc_csu_fini (void); @@ -59,7 +63,7 @@ _start (uint32_t info[]) { /* The generic code actually assumes that envp follows argv. */ - __libc_start_main (&main, + __libc_start_main (&__nacl_main ?: &main, nacl_startup_argc (info), nacl_startup_argv (info), nacl_startup_auxv (info), diff --git a/sysdeps/posix/opendir.c b/sysdeps/posix/opendir.c index 6509f5c..9edf056 100644 --- a/sysdeps/posix/opendir.c +++ b/sysdeps/posix/opendir.c @@ -105,7 +105,7 @@ need_isdir_precheck (void) tryopen_o_directory (); /* We can skip the expensive `stat' call if O_DIRECTORY works. */ - return o_directory_works > 0; + return o_directory_works < 0; #endif return true; } diff --git a/sysdeps/powerpc/nptl/elide.h b/sysdeps/powerpc/nptl/elide.h index 389f5a5..2e1e443 100644 --- a/sysdeps/powerpc/nptl/elide.h +++ b/sysdeps/powerpc/nptl/elide.h @@ -23,67 +23,78 @@ # include # include -/* Returns true if the lock defined by is_lock_free as elided. - ADAPT_COUNT is a pointer to per-lock state variable. */ - +/* Get the new value of adapt_count according to the elision + configurations. Returns true if the system should retry again or false + otherwise. */ static inline bool -__elide_lock (uint8_t *adapt_count, int is_lock_free) +__get_new_count (uint8_t *adapt_count, int attempt) { - if (*adapt_count > 0) + /* A persistent failure indicates that a retry will probably + result in another failure. Use normal locking now and + for the next couple of calls. */ + if (_TEXASRU_FAILURE_PERSISTENT (__builtin_get_texasru ())) { - (*adapt_count)--; + if (__elision_aconf.skip_lock_internal_abort > 0) + *adapt_count = __elision_aconf.skip_lock_internal_abort; return false; } - - for (int i = __elision_aconf.try_tbegin; i > 0; i--) - { - if (__builtin_tbegin (0)) - { - if (is_lock_free) - return true; - /* Lock was busy. */ - __builtin_tabort (_ABORT_LOCK_BUSY); - } - else - { - /* A persistent failure indicates that a retry will probably - result in another failure. Use normal locking now and - for the next couple of calls. */ - if (_TEXASRU_FAILURE_PERSISTENT (__builtin_get_texasru ())) - { - if (__elision_aconf.skip_lock_internal_abort > 0) - *adapt_count = __elision_aconf.skip_lock_internal_abort; - break; - } - /* Same logic as above, but for a number of temporary failures in a - a row. */ - else if (__elision_aconf.skip_lock_out_of_tbegin_retries > 0 - && __elision_aconf.try_tbegin > 0) - *adapt_count = __elision_aconf.skip_lock_out_of_tbegin_retries; - } - } - - return false; + /* Same logic as above, but for a number of temporary failures in a + a row. */ + else if (attempt <= 1 && __elision_aconf.skip_lock_out_of_tbegin_retries > 0 + && __elision_aconf.try_tbegin > 0) + *adapt_count = __elision_aconf.skip_lock_out_of_tbegin_retries; + return true; } -# define ELIDE_LOCK(adapt_count, is_lock_free) \ - __elide_lock (&(adapt_count), is_lock_free) - - -static inline bool -__elide_trylock (uint8_t *adapt_count, int is_lock_free, int write) -{ - if (__elision_aconf.try_tbegin > 0) - { - if (write) - __builtin_tabort (_ABORT_NESTED_TRYLOCK); - return __elide_lock (adapt_count, is_lock_free); - } - return false; -} +/* CONCURRENCY NOTES: + + The evaluation of the macro expression is_lock_free encompasses one or + more loads from memory locations that are concurrently modified by other + threads. For lock elision to work, this evaluation and the rest of the + critical section protected by the lock must be atomic because an + execution with lock elision must be equivalent to an execution in which + the lock would have been actually acquired and released. Therefore, we + evaluate is_lock_free inside of the transaction that represents the + critical section for which we want to use lock elision, which ensures + the atomicity that we require. */ + +/* Returns 0 if the lock defined by is_lock_free was elided. + ADAPT_COUNT is a per-lock state variable. */ +# define ELIDE_LOCK(adapt_count, is_lock_free) \ + ({ \ + int ret = 0; \ + if (adapt_count > 0) \ + (adapt_count)--; \ + else \ + for (int i = __elision_aconf.try_tbegin; i > 0; i--) \ + { \ + if (__builtin_tbegin (0)) \ + { \ + if (is_lock_free) \ + { \ + ret = 1; \ + break; \ + } \ + __builtin_tabort (_ABORT_LOCK_BUSY); \ + } \ + else \ + if (!__get_new_count (&adapt_count,i)) \ + break; \ + } \ + ret; \ + }) # define ELIDE_TRYLOCK(adapt_count, is_lock_free, write) \ - __elide_trylock (&(adapt_count), is_lock_free, write) + ({ \ + int ret = 0; \ + if (__elision_aconf.try_tbegin > 0) \ + { \ + if (write) \ + __builtin_tabort (_ABORT_NESTED_TRYLOCK); \ + ret = ELIDE_LOCK (adapt_count, is_lock_free); \ + } \ + ret; \ + }) static inline bool diff --git a/sysdeps/sparc/sparc32/sem_open.c b/sysdeps/sparc/sparc32/sem_open.c index 16cb9ad..59df2d7 100644 --- a/sysdeps/sparc/sparc32/sem_open.c +++ b/sysdeps/sparc/sparc32/sem_open.c @@ -29,6 +29,7 @@ #include #include #include "semaphoreP.h" +#include #include diff --git a/sysdeps/unix/sysv/linux/alpha/libc.abilist b/sysdeps/unix/sysv/linux/alpha/libc.abilist index 58c8b32..aa20e22 100644 --- a/sysdeps/unix/sysv/linux/alpha/libc.abilist +++ b/sysdeps/unix/sysv/linux/alpha/libc.abilist @@ -1822,9 +1822,6 @@ GLIBC_2.17 GLIBC_2.18 GLIBC_2.18 A __cxa_thread_atexit_impl F -GLIBC_2.22 - GLIBC_2.22 A - fmemopen F GLIBC_2.2 GLIBC_2.2 A _IO_adjust_wcolumn F @@ -2015,6 +2012,9 @@ GLIBC_2.2.4 GLIBC_2.2.6 GLIBC_2.2.6 A __nanosleep F +GLIBC_2.22 + GLIBC_2.22 A + fmemopen F GLIBC_2.3 GLIBC_2.3 A __ctype_b_loc F diff --git a/sysdeps/unix/sysv/linux/hppa/bits/atomic.h b/sysdeps/unix/sysv/linux/hppa/bits/atomic.h index abde83e..6e73504 100644 --- a/sysdeps/unix/sysv/linux/hppa/bits/atomic.h +++ b/sysdeps/unix/sysv/linux/hppa/bits/atomic.h @@ -56,42 +56,41 @@ typedef uintmax_t uatomic_max_t; #define _LWS "0xb0" #define _LWS_CAS "0" /* Note r31 is the link register. */ -#define _LWS_CLOBBER "r1", "r26", "r25", "r24", "r23", "r22", "r21", "r20", "r28", "r31", "memory" +#define _LWS_CLOBBER "r1", "r23", "r22", "r20", "r31", "memory" /* String constant for -EAGAIN. */ #define _ASM_EAGAIN "-11" /* String constant for -EDEADLOCK. */ #define _ASM_EDEADLOCK "-45" #if __ASSUME_LWS_CAS -/* The only basic operation needed is compare and exchange. */ +/* The only basic operation needed is compare and exchange. The mem + pointer must be word aligned. */ # define atomic_compare_and_exchange_val_acq(mem, newval, oldval) \ ({ \ - volatile int lws_errno; \ - __typeof__ (*mem) lws_ret; \ - asm volatile( \ + register long lws_errno asm("r21"); \ + register unsigned long lws_ret asm("r28"); \ + register unsigned long lws_mem asm("r26") = (unsigned long)(mem); \ + register unsigned long lws_old asm("r25") = (unsigned long)(oldval);\ + register unsigned long lws_new asm("r24") = (unsigned long)(newval);\ + __asm__ __volatile__( \ "0: \n\t" \ - "copy %2, %%r26 \n\t" \ - "copy %3, %%r25 \n\t" \ - "copy %4, %%r24 \n\t" \ "ble " _LWS "(%%sr2, %%r0) \n\t" \ "ldi " _LWS_CAS ", %%r20 \n\t" \ - "ldi " _ASM_EAGAIN ", %%r24 \n\t" \ - "cmpb,=,n %%r24, %%r21, 0b \n\t" \ + "ldi " _ASM_EAGAIN ", %%r20 \n\t" \ + "cmpb,=,n %%r20, %%r21, 0b \n\t" \ "nop \n\t" \ - "ldi " _ASM_EDEADLOCK ", %%r25 \n\t" \ - "cmpb,=,n %%r25, %%r21, 0b \n\t" \ + "ldi " _ASM_EDEADLOCK ", %%r20 \n\t" \ + "cmpb,=,n %%r20, %%r21, 0b \n\t" \ "nop \n\t" \ - "stw %%r28, %0 \n\t" \ - "stw %%r21, %1 \n\t" \ - : "=m" (lws_ret), "=m" (lws_errno) \ - : "r" (mem), "r" (oldval), "r" (newval) \ + : "=r" (lws_ret), "=r" (lws_errno) \ + : "r" (lws_mem), "r" (lws_old), "r" (lws_new) \ : _LWS_CLOBBER \ ); \ \ - if(lws_errno == -EFAULT || lws_errno == -ENOSYS) \ + if (lws_errno == -EFAULT || lws_errno == -ENOSYS) \ ABORT_INSTRUCTION; \ \ - lws_ret; \ + (__typeof (oldval)) lws_ret; \ }) # define atomic_compare_and_exchange_bool_acq(mem, newval, oldval) \ diff --git a/sysdeps/unix/sysv/linux/hppa/libc.abilist b/sysdeps/unix/sysv/linux/hppa/libc.abilist index cf0ad90..224e1f3 100644 --- a/sysdeps/unix/sysv/linux/hppa/libc.abilist +++ b/sysdeps/unix/sysv/linux/hppa/libc.abilist @@ -95,9 +95,6 @@ GLIBC_2.18 GLIBC_2.19 GLIBC_2.19 A fanotify_mark F -GLIBC_2.22 - GLIBC_2.22 A - fmemopen F GLIBC_2.2 GLIBC_2.2 A _Exit F @@ -1863,6 +1860,9 @@ GLIBC_2.2.4 GLIBC_2.2.6 GLIBC_2.2.6 A __nanosleep F +GLIBC_2.22 + GLIBC_2.22 A + fmemopen F GLIBC_2.3 GLIBC_2.3 A __ctype_b_loc F diff --git a/sysdeps/unix/sysv/linux/hppa/syscall.c b/sysdeps/unix/sysv/linux/hppa/syscall.c index aff67a8..958fa47 100644 --- a/sysdeps/unix/sysv/linux/hppa/syscall.c +++ b/sysdeps/unix/sysv/linux/hppa/syscall.c @@ -43,9 +43,10 @@ syscall (long int __sysno, ...) va_end (args); { + LOAD_ARGS_6 (arg0, arg1, arg2, arg3, arg4, arg5) register unsigned long int __res asm("r28"); PIC_REG_DEF - LOAD_ARGS_6 (arg0, arg1, arg2, arg3, arg4, arg5) + LOAD_REGS_6 asm volatile (SAVE_ASM_PIC " ble 0x100(%%sr2, %%r0) \n" " copy %1, %%r20 \n" diff --git a/sysdeps/unix/sysv/linux/hppa/sysdep.h b/sysdeps/unix/sysv/linux/hppa/sysdep.h index d20a04b..cb1f163 100644 --- a/sysdeps/unix/sysv/linux/hppa/sysdep.h +++ b/sysdeps/unix/sysv/linux/hppa/sysdep.h @@ -400,9 +400,10 @@ L(pre_end): ASM_LINE_SEP \ ({ \ long __sys_res; \ { \ + LOAD_ARGS_##nr(args) \ register unsigned long __res asm("r28"); \ PIC_REG_DEF \ - LOAD_ARGS_##nr(args) \ + LOAD_REGS_##nr \ /* FIXME: HACK save/load r19 around syscall */ \ asm volatile( \ SAVE_ASM_PIC \ @@ -425,9 +426,10 @@ L(pre_end): ASM_LINE_SEP \ ({ \ long __sys_res; \ { \ + LOAD_ARGS_##nr(args) \ register unsigned long __res asm("r28"); \ PIC_REG_DEF \ - LOAD_ARGS_##nr(args) \ + LOAD_REGS_##nr \ /* FIXME: HACK save/load r19 around syscall */ \ asm volatile( \ SAVE_ASM_PIC \ @@ -443,27 +445,44 @@ L(pre_end): ASM_LINE_SEP \ __sys_res; \ }) - - #define LOAD_ARGS_0() -#define LOAD_ARGS_1(r26) \ - register unsigned long __r26 __asm__("r26") = (unsigned long)(r26); \ +#define LOAD_REGS_0 +#define LOAD_ARGS_1(a1) \ + register unsigned long __x26 = (unsigned long)(a1); \ LOAD_ARGS_0() -#define LOAD_ARGS_2(r26,r25) \ - register unsigned long __r25 __asm__("r25") = (unsigned long)(r25); \ - LOAD_ARGS_1(r26) -#define LOAD_ARGS_3(r26,r25,r24) \ - register unsigned long __r24 __asm__("r24") = (unsigned long)(r24); \ - LOAD_ARGS_2(r26,r25) -#define LOAD_ARGS_4(r26,r25,r24,r23) \ - register unsigned long __r23 __asm__("r23") = (unsigned long)(r23); \ - LOAD_ARGS_3(r26,r25,r24) -#define LOAD_ARGS_5(r26,r25,r24,r23,r22) \ - register unsigned long __r22 __asm__("r22") = (unsigned long)(r22); \ - LOAD_ARGS_4(r26,r25,r24,r23) -#define LOAD_ARGS_6(r26,r25,r24,r23,r22,r21) \ - register unsigned long __r21 __asm__("r21") = (unsigned long)(r21); \ - LOAD_ARGS_5(r26,r25,r24,r23,r22) +#define LOAD_REGS_1 \ + register unsigned long __r26 __asm__("r26") = __x26; \ + LOAD_REGS_0 +#define LOAD_ARGS_2(a1,a2) \ + register unsigned long __x25 = (unsigned long)(a2); \ + LOAD_ARGS_1(a1) +#define LOAD_REGS_2 \ + register unsigned long __r25 __asm__("r25") = __x25; \ + LOAD_REGS_1 +#define LOAD_ARGS_3(a1,a2,a3) \ + register unsigned long __x24 = (unsigned long)(a3); \ + LOAD_ARGS_2(a1,a2) +#define LOAD_REGS_3 \ + register unsigned long __r24 __asm__("r24") = __x24; \ + LOAD_REGS_2 +#define LOAD_ARGS_4(a1,a2,a3,a4) \ + register unsigned long __x23 = (unsigned long)(a4); \ + LOAD_ARGS_3(a1,a2,a3) +#define LOAD_REGS_4 \ + register unsigned long __r23 __asm__("r23") = __x23; \ + LOAD_REGS_3 +#define LOAD_ARGS_5(a1,a2,a3,a4,a5) \ + register unsigned long __x22 = (unsigned long)(a5); \ + LOAD_ARGS_4(a1,a2,a3,a4) +#define LOAD_REGS_5 \ + register unsigned long __r22 __asm__("r22") = __x22; \ + LOAD_REGS_4 +#define LOAD_ARGS_6(a1,a2,a3,a4,a5,a6) \ + register unsigned long __x21 = (unsigned long)(a6); \ + LOAD_ARGS_5(a1,a2,a3,a4,a5) +#define LOAD_REGS_6 \ + register unsigned long __r21 __asm__("r21") = __x21; \ + LOAD_REGS_5 /* Even with zero args we use r20 for the syscall number */ #define ASM_ARGS_0 diff --git a/sysdeps/unix/sysv/linux/microblaze/sysdep.h b/sysdeps/unix/sysv/linux/microblaze/sysdep.h index 83c0340..9d5c542 100644 --- a/sysdeps/unix/sysv/linux/microblaze/sysdep.h +++ b/sysdeps/unix/sysv/linux/microblaze/sysdep.h @@ -16,8 +16,11 @@ License along with the GNU C Library; if not, see . */ +#ifndef _LINUX_MICROBLAZE_SYSDEP_H +#define _LINUX_MICROBLAZE_SYSDEP_H 1 + +#include #include -#include /* Defines RTLD_PRIVATE_ERRNO. */ #include @@ -305,3 +308,5 @@ SYSCALL_ERROR_LABEL_DCL: \ # define PTR_DEMANGLE(var) (void) (var) #endif /* not __ASSEMBLER__ */ + +#endif /* _LINUX_MICROBLAZE_SYSDEP_H */ diff --git a/sysdeps/unix/sysv/linux/openat.c b/sysdeps/unix/sysv/linux/openat.c index 6777123..ad8e31d 100644 --- a/sysdeps/unix/sysv/linux/openat.c +++ b/sysdeps/unix/sysv/linux/openat.c @@ -68,6 +68,11 @@ __OPENAT (int fd, const char *file, int oflag, ...) va_end (arg); } + /* We have to add the O_LARGEFILE flag for openat64. */ +#ifdef MORE_OFLAGS + oflag |= MORE_OFLAGS; +#endif + return SYSCALL_CANCEL (openat, fd, file, oflag, mode); } libc_hidden_def (__OPENAT) diff --git a/sysdeps/unix/sysv/linux/powerpc/elision-lock.c b/sysdeps/unix/sysv/linux/powerpc/elision-lock.c index 7f9bcc2..c6731ca 100644 --- a/sysdeps/unix/sysv/linux/powerpc/elision-lock.c +++ b/sysdeps/unix/sysv/linux/powerpc/elision-lock.c @@ -72,8 +72,7 @@ __lll_lock_elision (int *lock, short *adapt_count, EXTRAARG int pshared) goto use_lock; } - int try_begin = aconf.try_tbegin; - while (1) + for (int i = aconf.try_tbegin; i > 0; i--) { if (__builtin_tbegin (0)) { @@ -87,21 +86,19 @@ __lll_lock_elision (int *lock, short *adapt_count, EXTRAARG int pshared) /* A persistent failure indicates that a retry will probably result in another failure. Use normal locking now and for the next couple of calls. */ - if (try_begin-- <= 0 - || _TEXASRU_FAILURE_PERSISTENT (__builtin_get_texasru ())) + if (_TEXASRU_FAILURE_PERSISTENT (__builtin_get_texasru ())) { if (aconf.skip_lock_internal_abort > 0) *adapt_count = aconf.skip_lock_internal_abort; goto use_lock; } - /* Same logic as above, but for for a number of temporary failures - in a row. */ - else if (aconf.skip_lock_out_of_tbegin_retries > 0 - && aconf.try_tbegin > 0) - *adapt_count = aconf.skip_lock_out_of_tbegin_retries; } } + /* Fall back to locks for a bit if retries have been exhausted */ + if (aconf.try_tbegin > 0 && aconf.skip_lock_out_of_tbegin_retries > 0) + *adapt_count = aconf.skip_lock_out_of_tbegin_retries; + use_lock: return LLL_LOCK ((*lock), pshared); } diff --git a/time/strftime_l.c b/time/strftime_l.c index b48ef34..4eb647c 100644 --- a/time/strftime_l.c +++ b/time/strftime_l.c @@ -510,13 +510,17 @@ __strftime_internal (s, maxsize, format, tp, tzset_called ut_argument only a few elements. Dereference the pointers only if the format requires this. Then it is ok to fail if the pointers are invalid. */ # define a_wkday \ - ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ABDAY_1) + tp->tm_wday)) + ((const CHAR_T *) (tp->tm_wday < 0 || tp->tm_wday > 6 \ + ? "?" : _NL_CURRENT (LC_TIME, NLW(ABDAY_1) + tp->tm_wday))) # define f_wkday \ - ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(DAY_1) + tp->tm_wday)) + ((const CHAR_T *) (tp->tm_wday < 0 || tp->tm_wday > 6 \ + ? "?" : _NL_CURRENT (LC_TIME, NLW(DAY_1) + tp->tm_wday))) # define a_month \ - ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ABMON_1) + tp->tm_mon)) + ((const CHAR_T *) (tp->tm_mon < 0 || tp->tm_mon > 11 \ + ? "?" : _NL_CURRENT (LC_TIME, NLW(ABMON_1) + tp->tm_mon))) # define f_month \ - ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(MON_1) + tp->tm_mon)) + ((const CHAR_T *) (tp->tm_mon < 0 || tp->tm_mon > 11 \ + ? "?" : _NL_CURRENT (LC_TIME, NLW(MON_1) + tp->tm_mon))) # define ampm \ ((const CHAR_T *) _NL_CURRENT (LC_TIME, tp->tm_hour > 11 \ ? NLW(PM_STR) : NLW(AM_STR))) @@ -526,8 +530,10 @@ __strftime_internal (s, maxsize, format, tp, tzset_called ut_argument # define ap_len STRLEN (ampm) #else # if !HAVE_STRFTIME -# define f_wkday (weekday_name[tp->tm_wday]) -# define f_month (month_name[tp->tm_mon]) +# define f_wkday (tp->tm_wday < 0 || tp->tm_wday > 6 \ + ? "?" : weekday_name[tp->tm_wday]) +# define f_month (tp->tm_mon < 0 || tp->tm_mon > 11 \ + ? "?" : month_name[tp->tm_mon]) # define a_wkday f_wkday # define a_month f_month # define ampm (L_("AMPM") + 2 * (tp->tm_hour > 11)) @@ -1321,7 +1327,7 @@ __strftime_internal (s, maxsize, format, tp, tzset_called ut_argument *tzset_called = true; } # endif - zone = tzname[tp->tm_isdst]; + zone = tp->tm_isdst <= 1 ? tzname[tp->tm_isdst] : "?"; } #endif if (! zone) diff --git a/time/tst-strftime.c b/time/tst-strftime.c index 374fba4..af3ff72 100644 --- a/time/tst-strftime.c +++ b/time/tst-strftime.c @@ -4,6 +4,56 @@ #include +static int +do_bz18985 (void) +{ + char buf[1000]; + struct tm ttm; + int rc, ret = 0; + + memset (&ttm, 1, sizeof (ttm)); + ttm.tm_zone = NULL; /* Dereferenced directly if non-NULL. */ + rc = strftime (buf, sizeof (buf), "%a %A %b %B %c %z %Z", &ttm); + + if (rc == 66) + { + const char expected[] + = "? ? ? ? ? ? 16843009 16843009:16843009:16843009 16844909 +467836 ?"; + if (0 != strcmp (buf, expected)) + { + printf ("expected:\n %s\ngot:\n %s\n", expected, buf); + ret += 1; + } + } + else + { + printf ("expected 66, got %d\n", rc); + ret += 1; + } + + /* Check negative values as well. */ + memset (&ttm, 0xFF, sizeof (ttm)); + ttm.tm_zone = NULL; /* Dereferenced directly if non-NULL. */ + rc = strftime (buf, sizeof (buf), "%a %A %b %B %c %z %Z", &ttm); + + if (rc == 30) + { + const char expected[] = "? ? ? ? ? ? -1 -1:-1:-1 1899 "; + if (0 != strcmp (buf, expected)) + { + printf ("expected:\n %s\ngot:\n %s\n", expected, buf); + ret += 1; + } + } + else + { + printf ("expected 30, got %d\n", rc); + ret += 1; + } + + return ret; +} + static struct { const char *fmt; @@ -104,7 +154,7 @@ do_test (void) } } - return result; + return result + do_bz18985 (); } #define TEST_FUNCTION do_test () diff --git a/wcsmbs/wcscoll_l.c b/wcsmbs/wcscoll_l.c index 6d9384a..87f240d 100644 --- a/wcsmbs/wcscoll_l.c +++ b/wcsmbs/wcscoll_l.c @@ -23,7 +23,6 @@ #define STRING_TYPE wchar_t #define USTRING_TYPE wint_t #define STRCOLL __wcscoll_l -#define STRDIFF __wcsdiff #define STRCMP __wcscmp #define WEIGHT_H "../locale/weightwc.h" #define SUFFIX WC