diff options
45 files changed, 1862 insertions, 801 deletions
diff --git a/ChangeLog b/ChangeLog index bf062849e9..7b36bcfa8c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,11 +1,118 @@ +2004-11-12 Ulrich Drepper <drepper@redhat.com> + + * posix/Makefile (tests): Add bug-regex24. + * posix/bug-regex24.c: New file. + +2004-11-12 Paolo Bonzini <bonzini@gnu.org> + + * posix/regexec.c (check_dst_limits_calc_pos_1): Use the map to + cut recursive paths. Make exit condition more precise. + (match_ctx_add_entry): Initialize the map. + * posix/regex_internal.h (struct re_backref_cache_entry): Add a map of + reachable subexpression nodes from each backreference cache entry. + +2004-11-10 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/setreuid.c: Remove sys/syscall.h, + sys/types.h, linux/posix_types.h, sysdep.h and pthread-functions.h + includes. Include setxid.h. Use INLINE_SETXID_SYSCALL macro + instead of INLINE_SYSCALL, kill the HAVE_PTR__NPTL_SETXID guarded + snippets. + * sysdeps/unix/sysv/linux/setegid.c: Likewise. + * sysdeps/unix/sysv/linux/setuid.c: Likewise. + * sysdeps/unix/sysv/linux/seteuid.c: Likewise. + * sysdeps/unix/sysv/linux/setgid.c: Likewise. + * sysdeps/unix/sysv/linux/setresuid.c: Likewise. + * sysdeps/unix/sysv/linux/setresgid.c: Likewise. + * sysdeps/unix/sysv/linux/setregid.c: Likewise. + * sysdeps/unix/sysv/linux/i386/setegid.c: Likewise. + * sysdeps/unix/sysv/linux/i386/setreuid.c: Likewise. + * sysdeps/unix/sysv/linux/i386/setuid.c: Likewise. + * sysdeps/unix/sysv/linux/i386/seteuid.c: Likewise. + * sysdeps/unix/sysv/linux/i386/setgid.c: Likewise. + * sysdeps/unix/sysv/linux/i386/setresuid.c: Likewise. + * sysdeps/unix/sysv/linux/i386/setresgid.c: Likewise. + * sysdeps/unix/sysv/linux/i386/setregid.c: Likewise. + * sysdeps/unix/sysv/linux/alpha/setreuid.c: Likewise. + Formatting. Change signed int into int. + * sysdeps/unix/sysv/linux/alpha/setresuid.c: Likewise. + * sysdeps/unix/sysv/linux/alpha/setresgid.c: Likewise. + * sysdeps/unix/sysv/linux/alpha/setregid.c: Likewise. + * sysdeps/unix/sysv/linux/syscalls.list (setresuid, setresgid): + Remove. + * sysdeps/unix/setxid.h: New file. + + * Rules (binaries-static): Add xtests-static. + * Makeconfig (run-program-prefix): Filter also xtests-static. + +2004-11-09 Paul Eggert <eggert@cs.ucla.edu. + + [BZ #535] + * time/difftime.c: Fix a double-rounding bug on hosts with + 64-bit time_t and long double being IEEE double. Also, port + to more valid C99 hosts, even those that have padding bits. + Don't include <values.h> since it is marked as an obsolescent + interface. Include <limits.h>, <float.h>, and <stdint.h> instead. + (TYPE_BITS, TYPE_FLOATING, TYPE_SIGNED): New macros. + (subtract): New static function, that works correctly without + double-rounding, even on hosts with 64-bit time_t. Also cater + to hosts with padding bits. + (__difftime): Use it. Use DBL_MANT_DIG and LDBL_MANT_DIG to + determine whether floating types are wide enough: the old + test (which used sizeof) could in theory report the wrong results + on hosts with padding bits in floating-point values. + +2004-11-11 Simon Josefsson <jas@extundo.com> + + [BZ #542] + * sysdeps/generic/strtok_r.c [HAVE_CONFIG_H]: Include config.h. + [!_LIBC]: Include strtok_r.h (in gnulib), map __strtok_r to + strtok_r and __rawmemchr to strch. + (__strtok_r): Use C89 prototype. + [weak_alias]: Move calls to libc_hidden_def and weak_alias into + this #ifdef. + +2004-11-10 Paul Eggert <eggert@cs.ucla.edu> + + [BZ #541] + * time/mktime.c (SHR): New macro, which is a portable + substitute for >> that should work even on Crays. + (TIME_T_MIDPOINT, ydhms_diff, __mktime_internal): Use it. + Problem reported by Mark D. Baushke in + <http://lists.gnu.org/archive/html/bug-gnulib/2004-11/msg00071.html>. + +2004-11-09 Paolo Bonzini <bonzini@gnu.org> + + * posix/regexec.c (match_ctx_free_subtops): Remove, merge into... + (match_ctx_clean): ... this function. + (match_ctx_free): Call match_ctx_clean. + + * posix/regexec.c (transit_state): Remove the check for + out-of-bounds buffers. + (check_matching): Check here for out-of-bounds buffers. + (re_search_internal): Store into match_kind a set of bits + indicating which incantation of fastmap scanning must be + used. Use a switch statement instead of multiple ifs. + Exit the final "for (;;)" with goto free_return unless + the match succeeded, thus simplifying some conditionals. + + * posix/regex_internal.c (re_string_reconstruct, + re_string_context_at): Add several branch predictions for + case-sensitive matching and no transition table being used. + +2004-11-10 Ulrich Drepper <drepper@redhat.com> + + * posix/tst-waitid.c: Don't use error to print error message, they + won't end up in the .out file. + 2004-11-09 Ulrich Drepper <drepper@redhat.com> * nscd/nscd-client.h (libc_locked_map_ptr): Add new first parameter, used as class for definition. * nscd/nscd_getpw_r.c: Adjust for libc_locked_map_ptr change. (pw_map_free): Ensure no crash after memory is freed. - * nscd/nscd_getgr.c: Likewise. Make map externally visible. - * nscd/nscd_gethst.c: Likewise. + * nscd/nscd_getgr_r.c: Likewise. Make map externally visible. + * nscd/nscd_gethst_r.c: Likewise. * nscd/nscd_getai.c: Use map from nscd_gethost.c. * nscd/nscd_initgroups.c: Use map from nscd_getgr.c. diff --git a/Makeconfig b/Makeconfig index dc70aa68c4..ab9f806eff 100644 --- a/Makeconfig +++ b/Makeconfig @@ -541,7 +541,7 @@ $(subst $(empty) ,:,$(strip $(patsubst -Wl$(comma)-rpath-link=%, %,\ $(filter -Wl$(comma)-rpath-link=%,\ $(sysdep-LDFLAGS))))) run-program-prefix = $(if $(filter $(notdir $(built-program-file)),\ - $(tests-static)),, \ + $(tests-static) $(xtests-static)),, \ $(elf-objpfx)$(rtld-installed-name) \ --library-path $(rpath-link)$(patsubst %,:%,$(sysdep-library-path))) else diff --git a/Rules b/Rules index 64179ad64d..a29daaa7b5 100644 --- a/Rules +++ b/Rules @@ -104,7 +104,7 @@ endif ifeq ($(build-programs),yes) binaries-all = $(others) $(sysdep-others) $(tests) $(xtests) $(test-srcs) -binaries-static = $(others-static) $(tests-static) +binaries-static = $(others-static) $(tests-static) $(xtests-static) else binaries-all = $(tests) $(xtests) $(test-srcs) binaries-static = diff --git a/fedora/branch.mk b/fedora/branch.mk index b07840623e..2714ad4822 100644 --- a/fedora/branch.mk +++ b/fedora/branch.mk @@ -1,5 +1,5 @@ # This file is updated automatically by Makefile. glibc-branch := fedora glibc-base := HEAD -fedora-sync-date := 2004-11-10 08:39 UTC -fedora-sync-tag := fedora-glibc-20041110T0839 +fedora-sync-date := 2004-11-12 16:40 UTC +fedora-sync-tag := fedora-glibc-20041112T1640 diff --git a/fedora/glibc.spec.in b/fedora/glibc.spec.in index 735419c94a..0d97316b37 100644 --- a/fedora/glibc.spec.in +++ b/fedora/glibc.spec.in @@ -1,4 +1,4 @@ -%define glibcrelease 76 +%define glibcrelease 77 %define auxarches i586 i686 athlon sparcv9 alphaev6 %define prelinkarches noarch %define nptlarches i386 i686 athlon x86_64 ia64 s390 s390x sparcv9 ppc ppc64 @@ -1256,6 +1256,12 @@ rm -f *.filelist* %endif %changelog +* Fri Nov 12 2004 Jakub Jelinek <jakub@redhat.com> 2.3.3-77 +- update from CVS + - speedup regex on palindromes (BZ #429) + - fix NPTL set{,e,re,res}[ug]id, so that even if making process + less priviledged all threads change their credentials successfully + * Wed Nov 10 2004 Jakub Jelinek <jakub@redhat.com> 2.3.3-76 - update from CVS - fix regcomp crash (#138439) diff --git a/nptl/ChangeLog b/nptl/ChangeLog index 98df5cf228..e183a02c77 100644 --- a/nptl/ChangeLog +++ b/nptl/ChangeLog @@ -1,5 +1,22 @@ 2004-11-10 Jakub Jelinek <jakub@redhat.com> + * sysdeps/pthread/setxid.h: New file. + * sysdeps/pthread/pthread-functions.h (HAVE_PTR__NPTL_SETXID): Remove. + (struct xid_command): Add forward decl. + (struct pthread_functions): Change return type of __nptl_setxid hook + to int. + * pthreadP.h (__nptl_setxid): Change return type to int. + * allocatestack.c (__nptl_setxid): Call INTERNAL_SYSCALL_NCS in the + calling thread, return its return value and set errno on failure. + * descr.h (struct xid_command): Change id type to long array. + + * Makefile: Add rules to build and test tst-setuid1 and + tst-setuid1-static. + * tst-setuid1.c: New test. + * tst-setuid1-static.c: New test. + +2004-11-10 Jakub Jelinek <jakub@redhat.com> + * Makefile (tests): Add tst-exit3. * tst-exit3.c: New test. diff --git a/nptl/Makefile b/nptl/Makefile index 564eaca6c5..805b4dc046 100644 --- a/nptl/Makefile +++ b/nptl/Makefile @@ -242,6 +242,7 @@ tests = tst-attr1 tst-attr2 tst-attr3 \ tst-backtrace1 \ tst-oddstacklimit \ tst-vfork1 tst-vfork2 tst-vfork1x tst-vfork2x +xtests = tst-setuid1 tst-setuid1-static # Files which must not be linked with libpthread. tests-nolibpthread = tst-unload @@ -342,6 +343,7 @@ link-libc-static := $(common-objpfx)libc.a $(static-gnulib) \ ifeq ($(build-static),yes) tests-static += tst-locale1 tst-locale2 +xtests-static += tst-setuid1-static endif # These tests are linked with libc before libpthread tests-reverse += tst-cancel5 tst-cancel23 tst-vfork1x tst-vfork2x @@ -499,9 +501,10 @@ $(objpfx)libpthread.so: $(common-objpfx)libc.so \ # Make sure we link with the thread library. ifeq ($(build-shared),yes) $(addprefix $(objpfx), \ - $(filter-out $(tests-static) $(tests-reverse) $(tests-nolibpthread), \ - $(tests) $(test-srcs))): $(objpfx)libpthread.so \ - $(objpfx)libpthread_nonshared.a + $(filter-out $(tests-static) $(xtests-static) $(tests-reverse) \ + $(tests-nolibpthread), \ + $(tests) $(xtests) $(test-srcs))): $(objpfx)libpthread.so \ + $(objpfx)libpthread_nonshared.a $(objpfx)tst-unload: $(common-objpfx)dlfcn/libdl.so # $(objpfx)linklibc.so is used instead of $(common-objpfx)libc.so, # since otherwise libpthread.so comes before libc.so when linking. @@ -509,7 +512,7 @@ $(addprefix $(objpfx), $(tests-reverse)): \ $(objpfx)linklibc.so $(objpfx)libpthread.so \ $(objpfx)libpthread_nonshared.a $(objpfx)../libc.so: $(common-objpfx)libc.so ; -$(addprefix $(objpfx),$(tests-static)): $(objpfx)libpthread.a +$(addprefix $(objpfx),$(tests-static) $(xtests-static)): $(objpfx)libpthread.a $(objpfx)tst-atfork2.out: $(objpfx)tst-atfork2mod.so diff --git a/nptl/allocatestack.c b/nptl/allocatestack.c index d4f3188f53..6c2367cc89 100644 --- a/nptl/allocatestack.c +++ b/nptl/allocatestack.c @@ -816,10 +816,11 @@ __find_thread_by_id (pid_t tid) } #endif -void +int attribute_hidden __nptl_setxid (struct xid_command *cmdp) { + int result; lll_lock (stack_cache_lock); __xidcmd = cmdp; @@ -891,7 +892,18 @@ __nptl_setxid (struct xid_command *cmdp) cur = cmdp->cntr; } + /* This must be last, otherwise the current thread might not have + permissions to send SIGSETXID syscall to the other threads. */ + result = INTERNAL_SYSCALL_NCS (cmdp->syscall_no, err, 3, + cmdp->id[0], cmdp->id[1], cmdp->id[2]); + if (INTERNAL_SYSCALL_ERROR_P (result, err)) + { + __set_errno (INTERNAL_SYSCALL_ERRNO (result, err)); + result = -1; + } + lll_unlock (stack_cache_lock); + return result; } static inline void __attribute__((always_inline)) diff --git a/nptl/descr.h b/nptl/descr.h index 7ef4221e83..4c234a2349 100644 --- a/nptl/descr.h +++ b/nptl/descr.h @@ -101,7 +101,7 @@ struct pthread_unwind_buf struct xid_command { int syscall_no; - id_t id[3]; + long id[3]; volatile int cntr; }; diff --git a/nptl/pthreadP.h b/nptl/pthreadP.h index 1fedce5f3a..f73c817f60 100644 --- a/nptl/pthreadP.h +++ b/nptl/pthreadP.h @@ -448,6 +448,6 @@ extern void _pthread_cleanup_pop_restore (struct _pthread_cleanup_buffer *buffer extern void __nptl_deallocate_tsd (void) attribute_hidden; -extern void __nptl_setxid (struct xid_command *cmdp) attribute_hidden; +extern int __nptl_setxid (struct xid_command *cmdp) attribute_hidden; #endif /* pthreadP.h */ diff --git a/nptl/sysdeps/pthread/pthread-functions.h b/nptl/sysdeps/pthread/pthread-functions.h index b1e0fcb26d..2845346128 100644 --- a/nptl/sysdeps/pthread/pthread-functions.h +++ b/nptl/sysdeps/pthread/pthread-functions.h @@ -24,6 +24,7 @@ #include <setjmp.h> #include <internaltypes.h> +struct xid_command; /* Data type shared with libc. The libc uses it to pass on calls to the thread functions. */ @@ -93,8 +94,7 @@ struct pthread_functions void (*ptr___pthread_unwind) (__pthread_unwind_buf_t *) __attribute ((noreturn)) __cleanup_fct_attribute; void (*ptr__nptl_deallocate_tsd) (void); -#define HAVE_PTR__NPTL_SETXID - void (*ptr__nptl_setxid) (struct xid_command *); + int (*ptr__nptl_setxid) (struct xid_command *); }; /* Variable in libc.so. */ diff --git a/nptl/sysdeps/pthread/setxid.h b/nptl/sysdeps/pthread/setxid.h new file mode 100644 index 0000000000..8ec382f406 --- /dev/null +++ b/nptl/sysdeps/pthread/setxid.h @@ -0,0 +1,64 @@ +/* Copyright (C) 2004 Free Software 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <pthreadP.h> +#include <sysdep.h> + +#define __SETXID_1(cmd, arg1) \ + cmd.id[0] = arg1 +#define __SETXID_2(cmd, arg1, arg2) \ + __SETXID_1 (cmd, arg1); cmd.id[1] = arg2 +#define __SETXID_3(cmd, arg1, arg2, arg3) \ + __SETXID_2 (cmd, arg1, arg2); cmd.id[2] = arg3 + +#ifdef SINGLE_THREAD +# define INLINE_SETXID_SYSCALL(name, nr, args...) \ + INLINE_SYSCALL (name, nr, args) +#elif defined SHARED +# define INLINE_SETXID_SYSCALL(name, nr, args...) \ + ({ \ + int __result; \ + if (__builtin_expect (__libc_pthread_functions.ptr__nptl_setxid \ + != NULL, 0)) \ + { \ + struct xid_command __cmd; \ + __cmd.syscall_no = __NR_##name; \ + __SETXID_##nr (__cmd, args); \ + __result = __libc_pthread_functions.ptr__nptl_setxid (&__cmd); \ + } \ + else \ + __result = INLINE_SYSCALL (name, nr, args); \ + __result; \ + }) +#else +# define INLINE_SETXID_SYSCALL(name, nr, args...) \ + ({ \ + extern __typeof (__nptl_setxid) __nptl_setxid __attribute__((weak));\ + int __result; \ + if (__builtin_expect (__nptl_setxid != NULL, 0)) \ + { \ + struct xid_command __cmd; \ + __cmd.syscall_no = __NR_##name; \ + __SETXID_##nr (__cmd, args); \ + __result =__nptl_setxid (&__cmd); \ + } \ + else \ + __result = INLINE_SYSCALL (name, nr, args); \ + __result; \ + }) +#endif diff --git a/nptl/tst-setuid1-static.c b/nptl/tst-setuid1-static.c new file mode 100644 index 0000000000..46d26f0991 --- /dev/null +++ b/nptl/tst-setuid1-static.c @@ -0,0 +1 @@ +#include "tst-setuid1.c" diff --git a/nptl/tst-setuid1.c b/nptl/tst-setuid1.c new file mode 100644 index 0000000000..f026c576d6 --- /dev/null +++ b/nptl/tst-setuid1.c @@ -0,0 +1,1085 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <jaku@redhat.com>, 2004. + + 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <pthread.h> +#include <pwd.h> +#include <grp.h> +#include <stdlib.h> +#include <stdio.h> +#include <sys/wait.h> +#include <unistd.h> + + +static pthread_barrier_t b3, b4; +static uid_t prev_ruid, prev_euid, prev_suid, nobody_uid; +static gid_t prev_rgid, prev_egid, prev_sgid, nobody_gid; +enum ACTION { PREPARE, SET, CHECK_BEFORE, CHECK_AFTER }; +#define TESTNO(arg) ((long int) (arg) & 0xff) +#define THREADNO(arg) ((long int) (arg) >> 8) + + +static void +check_prev_uid (int tno) +{ + uid_t ruid, euid, suid; + if (getresuid (&ruid, &euid, &suid) < 0) + { + printf ("getresuid failed: %d %m\n", tno); + exit (1); + } + + if (ruid != prev_ruid || euid != prev_euid || suid != prev_suid) + { + printf ("uids before in %d (%d %d %d) != (%d %d %d)\n", tno, + ruid, euid, suid, prev_ruid, prev_euid, prev_suid); + exit (1); + } +} + + +static void +check_prev_gid (int tno) +{ + gid_t rgid, egid, sgid; + if (getresgid (&rgid, &egid, &sgid) < 0) + { + printf ("getresgid failed: %d %m\n", tno); + exit (1); + } + + if (rgid != prev_rgid || egid != prev_egid || sgid != prev_sgid) + { + printf ("gids before in %d (%d %d %d) != (%d %d %d)\n", tno, + rgid, egid, sgid, prev_rgid, prev_egid, prev_sgid); + exit (1); + } +} + + +static void +test_setuid1 (enum ACTION action, int tno) +{ + if (action == PREPARE) + return; + + if (action != CHECK_AFTER) + check_prev_uid (tno); + + if (action == SET && setuid (nobody_uid) < 0) + { + printf ("setuid failed: %m\n"); + exit (1); + } + + if (action != CHECK_BEFORE) + { + uid_t ruid, euid, suid; + if (getresuid (&ruid, &euid, &suid) < 0) + { + printf ("getresuid failed: %d %m\n", tno); + exit (1); + } + + if (ruid != nobody_uid || euid != nobody_uid || suid != nobody_uid) + { + printf ("after setuid %d (%d %d %d) != (%d %d %d)\n", tno, + ruid, euid, suid, nobody_uid, nobody_uid, nobody_uid); + exit (1); + } + } +} + + +static void +test_setuid2 (enum ACTION action, int tno) +{ + if (action == PREPARE) + { + if (setresuid (nobody_uid, nobody_uid, -1) < 0) + { + printf ("setresuid failed: %m\n"); + exit (1); + } + + prev_ruid = nobody_uid; + prev_euid = nobody_uid; + return; + } + + if (action != CHECK_AFTER) + check_prev_uid (tno); + + if (action == SET && setuid (prev_suid) < 0) + { + printf ("setuid failed: %m\n"); + exit (1); + } + + if (action != CHECK_BEFORE) + { + uid_t ruid, euid, suid; + if (getresuid (&ruid, &euid, &suid) < 0) + { + printf ("getresuid failed: %d %m\n", tno); + exit (1); + } + + if (ruid != nobody_uid || euid != prev_suid || suid != prev_suid) + { + printf ("after setuid %d (%d %d %d) != (%d %d %d)\n", tno, + ruid, euid, suid, nobody_uid, prev_suid, prev_suid); + exit (1); + } + } +} + + +static void +test_seteuid1 (enum ACTION action, int tno) +{ + if (action == PREPARE) + return; + + if (action != CHECK_AFTER) + check_prev_uid (tno); + + if (action == SET && seteuid (nobody_uid) < 0) + { + printf ("seteuid failed: %m\n"); + exit (1); + } + + if (action != CHECK_BEFORE) + { + uid_t ruid, euid, suid; + if (getresuid (&ruid, &euid, &suid) < 0) + { + printf ("getresuid failed: %d %m\n", tno); + exit (1); + } + + if (ruid != prev_ruid || euid != nobody_uid || suid != prev_suid) + { + printf ("after seteuid %d (%d %d %d) != (%d %d %d)\n", tno, + ruid, euid, suid, prev_ruid, nobody_uid, prev_suid); + exit (1); + } + } +} + + +static void +test_seteuid2 (enum ACTION action, int tno) +{ + if (action == PREPARE) + { + if (setresuid (nobody_uid, nobody_uid, -1) < 0) + { + printf ("setresuid failed: %m\n"); + exit (1); + } + + prev_ruid = nobody_uid; + prev_euid = nobody_uid; + nobody_uid = prev_suid; + return; + } + + test_seteuid1 (action, tno); +} + + +static void +test_setreuid1 (enum ACTION action, int tno) +{ + if (action == PREPARE) + return; + + if (action != CHECK_AFTER) + check_prev_uid (tno); + + if (action == SET && setreuid (-1, nobody_uid) < 0) + { + printf ("setreuid failed: %m\n"); + exit (1); + } + + if (action != CHECK_BEFORE) + { + uid_t ruid, euid, suid, esuid; + if (getresuid (&ruid, &euid, &suid) < 0) + { + printf ("getresuid failed: %d %m\n", tno); + exit (1); + } + + if (prev_ruid != nobody_uid) + esuid = nobody_uid; + else + esuid = prev_suid; + + if (ruid != prev_ruid || euid != nobody_uid || suid != esuid) + { + printf ("after setreuid %d (%d %d %d) != (%d %d %d)\n", tno, + ruid, euid, suid, prev_ruid, nobody_uid, esuid); + exit (1); + } + } +} + + +static void +test_setreuid2 (enum ACTION action, int tno) +{ + if (action == PREPARE) + return; + + if (action != CHECK_AFTER) + check_prev_uid (tno); + + if (action == SET && setreuid (nobody_uid, -1) < 0) + { + printf ("setreuid failed: %m\n"); + exit (1); + } + + if (action != CHECK_BEFORE) + { + uid_t ruid, euid, suid; + if (getresuid (&ruid, &euid, &suid) < 0) + { + printf ("getresuid failed: %d %m\n", tno); + exit (1); + } + + if (ruid != nobody_uid || euid != prev_euid || suid != prev_euid) + { + printf ("after setreuid %d (%d %d %d) != (%d %d %d)\n", tno, + ruid, euid, suid, nobody_uid, prev_euid, prev_euid); + exit (1); + } + } +} + + +static void +test_setreuid3 (enum ACTION action, int tno) +{ + if (action == PREPARE) + return; + + if (action != CHECK_AFTER) + check_prev_uid (tno); + + if (action == SET && setreuid (nobody_uid, nobody_uid) < 0) + { + printf ("setreuid failed: %m\n"); + exit (1); + } + + if (action != CHECK_BEFORE) + { + uid_t ruid, euid, suid; + if (getresuid (&ruid, &euid, &suid) < 0) + { + printf ("getresuid failed: %d %m\n", tno); + exit (1); + } + + if (ruid != nobody_uid || euid != nobody_uid || suid != nobody_uid) + { + printf ("after setreuid %d (%d %d %d) != (%d %d %d)\n", tno, + ruid, euid, suid, nobody_uid, nobody_uid, nobody_uid); + exit (1); + } + } +} + + +static void +test_setreuid4 (enum ACTION action, int tno) +{ + if (action == PREPARE) + { + if (setresuid (nobody_uid, nobody_uid, -1) < 0) + { + printf ("setresuid failed: %m\n"); + exit (1); + } + + prev_ruid = nobody_uid; + prev_euid = nobody_uid; + nobody_uid = prev_suid; + return; + } + + test_setreuid1 (action, tno); +} + + +static void +test_setresuid1 (enum ACTION action, int tno) +{ + if (action == PREPARE) + return; + + if (action != CHECK_AFTER) + check_prev_uid (tno); + + if (action == SET && setresuid (-1, nobody_uid, -1) < 0) + { + printf ("setresuid failed: %m\n"); + exit (1); + } + + if (action != CHECK_BEFORE) + { + uid_t ruid, euid, suid; + if (getresuid (&ruid, &euid, &suid) < 0) + { + printf ("getresuid failed: %d %m\n", tno); + exit (1); + } + + if (ruid != prev_ruid || euid != nobody_uid || suid != prev_suid) + { + printf ("after setresuid %d (%d %d %d) != (%d %d %d)\n", tno, + ruid, euid, suid, prev_ruid, nobody_uid, prev_suid); + exit (1); + } + } +} + + +static void +test_setresuid2 (enum ACTION action, int tno) +{ + if (action == PREPARE) + return; + + if (action != CHECK_AFTER) + check_prev_uid (tno); + + if (action == SET && setresuid (prev_euid, nobody_uid, nobody_uid) < 0) + { + printf ("setresuid failed: %m\n"); + exit (1); + } + + if (action != CHECK_BEFORE) + { + uid_t ruid, euid, suid; + if (getresuid (&ruid, &euid, &suid) < 0) + { + printf ("getresuid failed: %d %m\n", tno); + exit (1); + } + + if (ruid != prev_euid || euid != nobody_uid || suid != nobody_uid) + { + printf ("after setresuid %d (%d %d %d) != (%d %d %d)\n", tno, + ruid, euid, suid, prev_euid, nobody_uid, nobody_uid); + exit (1); + } + } +} + + +static void +test_setresuid3 (enum ACTION action, int tno) +{ + if (action == PREPARE) + return; + + if (action != CHECK_AFTER) + check_prev_uid (tno); + + if (action == SET && setresuid (nobody_uid, nobody_uid, nobody_uid) < 0) + { + printf ("setresuid failed: %m\n"); + exit (1); + } + + if (action != CHECK_BEFORE) + { + uid_t ruid, euid, suid; + if (getresuid (&ruid, &euid, &suid) < 0) + { + printf ("getresuid failed: %d %m\n", tno); + exit (1); + } + + if (ruid != nobody_uid || euid != nobody_uid || suid != nobody_uid) + { + printf ("after setresuid %d (%d %d %d) != (%d %d %d)\n", tno, + ruid, euid, suid, nobody_uid, nobody_uid, nobody_uid); + exit (1); + } + } +} + + +static void +test_setresuid4 (enum ACTION action, int tno) +{ + if (action == PREPARE) + { + if (setresuid (nobody_uid, nobody_uid, -1) < 0) + { + printf ("setresuid failed: %m\n"); + exit (1); + } + + prev_ruid = nobody_uid; + prev_euid = nobody_uid; + nobody_uid = prev_suid; + return; + } + + test_setresuid1 (action, tno); +} + + +static void +test_setgid1 (enum ACTION action, int tno) +{ + if (action == PREPARE) + return; + + if (action != CHECK_AFTER) + check_prev_gid (tno); + + if (action == SET && setgid (nobody_gid) < 0) + { + printf ("setgid failed: %m\n"); + exit (1); + } + + if (action != CHECK_BEFORE) + { + gid_t rgid, egid, sgid; + if (getresgid (&rgid, &egid, &sgid) < 0) + { + printf ("getresgid failed: %d %m\n", tno); + exit (1); + } + + if (rgid != nobody_gid || egid != nobody_gid || sgid != nobody_gid) + { + printf ("after setgid %d (%d %d %d) != (%d %d %d)\n", tno, + rgid, egid, sgid, nobody_gid, nobody_gid, nobody_gid); + exit (1); + } + } +} + + +static void +test_setgid2 (enum ACTION action, int tno) +{ + if (action == PREPARE) + { + if (setresgid (nobody_gid, nobody_gid, -1) < 0) + { + printf ("setresgid failed: %m\n"); + exit (1); + } + + prev_rgid = nobody_gid; + prev_egid = nobody_gid; + + if (setresuid (nobody_uid, nobody_uid, -1) < 0) + { + printf ("setresuid failed: %m\n"); + exit (1); + } + + prev_ruid = nobody_uid; + prev_euid = nobody_uid; + return; + } + + if (action != CHECK_AFTER) + check_prev_gid (tno); + + if (action == SET && setgid (prev_sgid) < 0) + { + printf ("setgid failed: %m\n"); + exit (1); + } + + if (action != CHECK_BEFORE) + { + gid_t rgid, egid, sgid; + if (getresgid (&rgid, &egid, &sgid) < 0) + { + printf ("getresgid failed: %d %m\n", tno); + exit (1); + } + + if (rgid != nobody_gid || egid != prev_sgid || sgid != prev_sgid) + { + printf ("after setgid %d (%d %d %d) != (%d %d %d)\n", tno, + rgid, egid, sgid, nobody_gid, prev_sgid, prev_sgid); + exit (1); + } + } +} + + +static void +test_setegid1 (enum ACTION action, int tno) +{ + if (action == PREPARE) + return; + + if (action != CHECK_AFTER) + check_prev_gid (tno); + + if (action == SET && setegid (nobody_gid) < 0) + { + printf ("setegid failed: %m\n"); + exit (1); + } + + if (action != CHECK_BEFORE) + { + gid_t rgid, egid, sgid; + if (getresgid (&rgid, &egid, &sgid) < 0) + { + printf ("getresgid failed: %d %m\n", tno); + exit (1); + } + + if (rgid != prev_rgid || egid != nobody_gid || sgid != prev_sgid) + { + printf ("after setegid %d (%d %d %d) != (%d %d %d)\n", tno, + rgid, egid, sgid, prev_rgid, nobody_gid, prev_sgid); + exit (1); + } + } +} + + +static void +test_setegid2 (enum ACTION action, int tno) +{ + if (action == PREPARE) + { + if (setresgid (nobody_gid, nobody_gid, -1) < 0) + { + printf ("setresgid failed: %m\n"); + exit (1); + } + + prev_rgid = nobody_gid; + prev_egid = nobody_gid; + nobody_gid = prev_sgid; + return; + } + + test_setegid1 (action, tno); +} + + +static void +test_setregid1 (enum ACTION action, int tno) +{ + if (action == PREPARE) + return; + + if (action != CHECK_AFTER) + check_prev_gid (tno); + + if (action == SET && setregid (-1, nobody_gid) < 0) + { + printf ("setregid failed: %m\n"); + exit (1); + } + + if (action != CHECK_BEFORE) + { + gid_t rgid, egid, sgid, esgid; + if (getresgid (&rgid, &egid, &sgid) < 0) + { + printf ("getresgid failed: %d %m\n", tno); + exit (1); + } + + if (prev_rgid != nobody_gid) + esgid = nobody_gid; + else + esgid = prev_sgid; + + if (rgid != prev_rgid || egid != nobody_gid || sgid != esgid) + { + printf ("after setregid %d (%d %d %d) != (%d %d %d)\n", tno, + rgid, egid, sgid, prev_rgid, nobody_gid, esgid); + exit (1); + } + } +} + + +static void +test_setregid2 (enum ACTION action, int tno) +{ + if (action == PREPARE) + return; + + if (action != CHECK_AFTER) + check_prev_gid (tno); + + if (action == SET && setregid (nobody_gid, -1) < 0) + { + printf ("setregid failed: %m\n"); + exit (1); + } + + if (action != CHECK_BEFORE) + { + gid_t rgid, egid, sgid; + if (getresgid (&rgid, &egid, &sgid) < 0) + { + printf ("getresgid failed: %d %m\n", tno); + exit (1); + } + + if (rgid != nobody_gid || egid != prev_egid || sgid != prev_egid) + { + printf ("after setregid %d (%d %d %d) != (%d %d %d)\n", tno, + rgid, egid, sgid, nobody_gid, prev_egid, prev_egid); + exit (1); + } + } +} + + +static void +test_setregid3 (enum ACTION action, int tno) +{ + if (action == PREPARE) + return; + + if (action != CHECK_AFTER) + check_prev_gid (tno); + + if (action == SET && setregid (nobody_gid, nobody_gid) < 0) + { + printf ("setregid failed: %m\n"); + exit (1); + } + + if (action != CHECK_BEFORE) + { + gid_t rgid, egid, sgid; + if (getresgid (&rgid, &egid, &sgid) < 0) + { + printf ("getresgid failed: %d %m\n", tno); + exit (1); + } + + if (rgid != nobody_gid || egid != nobody_gid || sgid != nobody_gid) + { + printf ("after setregid %d (%d %d %d) != (%d %d %d)\n", tno, + rgid, egid, sgid, nobody_gid, nobody_gid, nobody_gid); + exit (1); + } + } +} + + +static void +test_setregid4 (enum ACTION action, int tno) +{ + if (action == PREPARE) + { + if (setresgid (nobody_gid, nobody_gid, -1) < 0) + { + printf ("setresgid failed: %m\n"); + exit (1); + } + + prev_rgid = nobody_gid; + prev_egid = nobody_gid; + nobody_gid = prev_sgid; + return; + } + + test_setregid1 (action, tno); +} + + +static void +test_setresgid1 (enum ACTION action, int tno) +{ + if (action == PREPARE) + return; + + if (action != CHECK_AFTER) + check_prev_gid (tno); + + if (action == SET && setresgid (-1, nobody_gid, -1) < 0) + { + printf ("setresgid failed: %m\n"); + exit (1); + } + + if (action != CHECK_BEFORE) + { + gid_t rgid, egid, sgid; + if (getresgid (&rgid, &egid, &sgid) < 0) + { + printf ("getresgid failed: %d %m\n", tno); + exit (1); + } + + if (rgid != prev_rgid || egid != nobody_gid || sgid != prev_sgid) + { + printf ("after setresgid %d (%d %d %d) != (%d %d %d)\n", tno, + rgid, egid, sgid, prev_rgid, nobody_gid, prev_sgid); + exit (1); + } + } +} + + +static void +test_setresgid2 (enum ACTION action, int tno) +{ + if (action == PREPARE) + return; + + if (action != CHECK_AFTER) + check_prev_gid (tno); + + if (action == SET && setresgid (prev_egid, nobody_gid, nobody_gid) < 0) + { + printf ("setresgid failed: %m\n"); + exit (1); + } + + if (action != CHECK_BEFORE) + { + gid_t rgid, egid, sgid; + if (getresgid (&rgid, &egid, &sgid) < 0) + { + printf ("getresgid failed: %d %m\n", tno); + exit (1); + } + + if (rgid != prev_egid || egid != nobody_gid || sgid != nobody_gid) + { + printf ("after setresgid %d (%d %d %d) != (%d %d %d)\n", tno, + rgid, egid, sgid, prev_egid, nobody_gid, nobody_gid); + exit (1); + } + } +} + + +static void +test_setresgid3 (enum ACTION action, int tno) +{ + if (action == PREPARE) + return; + + if (action != CHECK_AFTER) + check_prev_gid (tno); + + if (action == SET && setresgid (nobody_gid, nobody_gid, nobody_gid) < 0) + { + printf ("setresgid failed: %m\n"); + exit (1); + } + + if (action != CHECK_BEFORE) + { + gid_t rgid, egid, sgid; + if (getresgid (&rgid, &egid, &sgid) < 0) + { + printf ("getresgid failed: %d %m\n", tno); + exit (1); + } + + if (rgid != nobody_gid || egid != nobody_gid || sgid != nobody_gid) + { + printf ("after setresgid %d (%d %d %d) != (%d %d %d)\n", tno, + rgid, egid, sgid, nobody_gid, nobody_gid, nobody_gid); + exit (1); + } + } +} + + +static void +test_setresgid4 (enum ACTION action, int tno) +{ + if (action == PREPARE) + { + if (setresgid (nobody_gid, nobody_gid, -1) < 0) + { + printf ("setresgid failed: %m\n"); + exit (1); + } + + prev_rgid = nobody_gid; + prev_egid = nobody_gid; + nobody_gid = prev_sgid; + return; + } + + test_setresgid1 (action, tno); +} + + +static struct setuid_test +{ + const char *name; + void (*test) (enum ACTION, int tno); +} setuid_tests[] = +{ + { "setuid1", test_setuid1 }, + { "setuid2", test_setuid2 }, + { "seteuid1", test_seteuid1 }, + { "seteuid2", test_seteuid2 }, + { "setreuid1", test_setreuid1 }, + { "setreuid2", test_setreuid2 }, + { "setreuid3", test_setreuid3 }, + { "setreuid4", test_setreuid4 }, + { "setresuid1", test_setresuid1 }, + { "setresuid2", test_setresuid2 }, + { "setresuid3", test_setresuid3 }, + { "setresuid4", test_setresuid4 }, + { "setgid1", test_setgid1 }, + { "setgid2", test_setgid2 }, + { "setegid1", test_setegid1 }, + { "setegid2", test_setegid2 }, + { "setregid1", test_setregid1 }, + { "setregid2", test_setregid2 }, + { "setregid3", test_setregid3 }, + { "setregid4", test_setregid4 }, + { "setresgid1", test_setresgid1 }, + { "setresgid2", test_setresgid2 }, + { "setresgid3", test_setresgid3 }, + { "setresgid4", test_setresgid4 } +}; + + +static void * +tf2 (void *arg) +{ + int e = pthread_barrier_wait (&b4); + if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD) + { + puts ("barrier_wait failed"); + exit (1); + } + + setuid_tests[TESTNO (arg)].test (CHECK_AFTER, THREADNO (arg)); + return NULL; +} + + +static void * +tf (void *arg) +{ + setuid_tests[TESTNO (arg)].test (CHECK_BEFORE, THREADNO (arg)); + + int e = pthread_barrier_wait (&b3); + if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD) + { + puts ("barrier_wait failed"); + exit (1); + } + + return tf2 (arg); +} + + +static int +do_one_test (long int testno) +{ + printf ("%s test\n", setuid_tests[testno].name); + + pid_t pid = fork (); + if (pid == 0) + { + setuid_tests[testno].test (PREPARE, 0); + setuid_tests[testno].test (SET, 0); + exit (0); + } + + if (pid < 0) + { + printf ("fork failed: %m\n"); + exit (1); + } + + int status; + if (waitpid (pid, &status, 0) < 0) + { + printf ("waitpid failed: %m\n"); + exit (1); + } + + if (!WIFEXITED (status)) + { + puts ("child did not exit"); + exit (1); + } + + if (WEXITSTATUS (status)) + { + printf ("skipping %s test\n", setuid_tests[testno].name); + return 0; + } + + pid = fork (); + if (pid == 0) + { + setuid_tests[testno].test (PREPARE, 0); + + pthread_t th; + int e = pthread_create (&th, NULL, tf, (void *) (testno | 0x100L)); + if (e != 0) + { + printf ("create failed: %m\n"); + exit (1); + } + + pthread_t th2; + e = pthread_create (&th2, NULL, tf, (void *) (testno | 0x200L)); + if (e != 0) + { + printf ("create failed: %m\n"); + exit (1); + } + + e = pthread_barrier_wait (&b3); + if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD) + { + puts ("barrier_wait failed"); + exit (1); + } + + setuid_tests[testno].test (SET, 0); + + pthread_t th3; + e = pthread_create (&th3, NULL, tf2, (void *) (testno | 0x300L)); + if (e != 0) + { + printf ("create failed: %m\n"); + exit (1); + } + + e = pthread_barrier_wait (&b4); + if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD) + { + puts ("barrier_wait failed"); + exit (1); + } + + exit (0); + } + + if (pid < 0) + { + printf ("fork failed: %m\n"); + exit (1); + } + + if (waitpid (pid, &status, 0) < 0) + { + printf ("waitpid failed: %m\n"); + exit (1); + } + + if (!WIFEXITED (status)) + { + puts ("second child did not exit"); + exit (1); + } + + if (WEXITSTATUS (status)) + exit (WEXITSTATUS (status)); + + return 0; +} + + +static int +do_test (void) +{ + struct passwd *pwd = getpwnam ("nobody"); + if (pwd == NULL) + { + puts ("User nobody doesn't exist"); + return 0; + } + nobody_uid = pwd->pw_uid; + nobody_gid = pwd->pw_gid; + + if (getresuid (&prev_ruid, &prev_euid, &prev_suid) < 0) + { + printf ("getresuid failed: %m\n"); + exit (1); + } + + if (getresgid (&prev_rgid, &prev_egid, &prev_sgid) < 0) + { + printf ("getresgid failed: %m\n"); + exit (1); + } + + if (prev_ruid == nobody_uid || prev_euid == nobody_uid + || prev_suid == nobody_uid) + { + puts ("already running as user nobody, skipping tests"); + exit (0); + } + + if (prev_rgid == nobody_gid || prev_egid == nobody_gid + || prev_sgid == nobody_gid) + { + puts ("already running as group nobody, skipping tests"); + exit (0); + } + + if (pthread_barrier_init (&b3, NULL, 3) != 0) + { + puts ("barrier_init failed"); + exit (1); + } + + if (pthread_barrier_init (&b4, NULL, 4) != 0) + { + puts ("barrier_init failed"); + exit (1); + } + + for (unsigned long int testno = 0; + testno < sizeof (setuid_tests) / sizeof (setuid_tests[0]); + ++testno) + do_one_test (testno); + return 0; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/posix/Makefile b/posix/Makefile index cd6a52c098..8bc15ad215 100644 --- a/posix/Makefile +++ b/posix/Makefile @@ -79,7 +79,8 @@ tests := tstgetopt testfnm runtests runptests \ bug-regex8 bug-regex9 bug-regex10 bug-regex11 bug-regex12 \ bug-regex13 bug-regex14 bug-regex15 bug-regex16 \ bug-regex17 bug-regex18 bug-regex19 bug-regex20 \ - bug-regex21 bug-regex22 bug-regex23 tst-nice tst-nanosleep \ + bug-regex21 bug-regex22 bug-regex23 bug-regex24 \ + tst-nice tst-nanosleep \ transbug tst-rxspencer tst-pcre tst-boost \ bug-ga1 tst-vfork1 tst-vfork2 tst-waitid \ tst-getaddrinfo2 bug-glob1 bug-glob2 diff --git a/posix/bug-regex24.c b/posix/bug-regex24.c new file mode 100644 index 0000000000..83ea10bb62 --- /dev/null +++ b/posix/bug-regex24.c @@ -0,0 +1,59 @@ +#include <regex.h> +#include <stdio.h> + +#define str "civic" + +#define N 10 +static const char *expected[N] = + { + str, "c", "i", "", "", "", "", "", "", "" + }; + +static int +do_test (void) +{ + regex_t rbuf; + static const char pat[] = "\ +^(.?)(.?)(.?)(.?)(.?)(.?)(.?)(.?)(.?).?\\9\\8\\7\\6\\5\\4\\3\\2\\1$"; + + int err = regcomp (&rbuf, pat, REG_EXTENDED); + if (err != 0) + { + char errstr[300]; + regerror (err, &rbuf, errstr, sizeof (errstr)); + puts (errstr); + return err; + } + + regmatch_t m[N]; + err = regexec (&rbuf, str, N, m, 0); + if (err != 0) + { + puts ("regexec failed"); + return 1; + } + + int result = 0; + for (int i = 0; i < N; ++i) + if (m[i].rm_so == -1) + { + printf ("m[%d] unused\n", i); + result = 1; + } + else + { + int len = m[i].rm_eo - m[i].rm_so; + + printf ("m[%d] = \"%.*s\"\n", i, len, str + m[i].rm_so); + + if (strlen (expected[i]) != len + || memcmp (expected[i], str + m[i].rm_so, len) != 0) + result = 1; + } + + return result; +} + +#define TIMEOUT 30 +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/posix/regex_internal.c b/posix/regex_internal.c index 609719f79c..bb1d73d9a0 100644 --- a/posix/regex_internal.c +++ b/posix/regex_internal.c @@ -576,7 +576,7 @@ re_string_reconstruct (pstr, idx, eflags) int idx, eflags; { int offset = idx - pstr->raw_mbs_idx; - if (offset < 0) + if (BE (offset < 0, 0)) { /* Reset buffer. */ #ifdef RE_ENABLE_I18N @@ -596,10 +596,10 @@ re_string_reconstruct (pstr, idx, eflags) offset = idx; } - if (offset != 0) + if (BE (offset != 0, 1)) { /* Are the characters which are already checked remain? */ - if (offset < pstr->valid_raw_len + if (BE (offset < pstr->valid_raw_len, 1) #ifdef RE_ENABLE_I18N /* Handling this would enlarge the code too much. Accept a slowdown in that case. */ @@ -614,7 +614,7 @@ re_string_reconstruct (pstr, idx, eflags) memmove (pstr->wcs, pstr->wcs + offset, (pstr->valid_len - offset) * sizeof (wint_t)); #endif /* RE_ENABLE_I18N */ - if (pstr->mbs_allocated) + if (BE (pstr->mbs_allocated, 0)) memmove (pstr->mbs, pstr->mbs + offset, pstr->valid_len - offset); pstr->valid_len -= offset; @@ -711,7 +711,7 @@ re_string_reconstruct (pstr, idx, eflags) ? CONTEXT_NEWLINE : 0)); } } - if (!pstr->mbs_allocated) + if (!BE (pstr->mbs_allocated, 0)) pstr->mbs += offset; } pstr->raw_mbs_idx = idx; @@ -733,16 +733,17 @@ re_string_reconstruct (pstr, idx, eflags) } else #endif /* RE_ENABLE_I18N */ + if (BE (pstr->mbs_allocated, 0)) { if (pstr->icase) build_upper_buffer (pstr); else if (pstr->trans != NULL) re_string_translate_buffer (pstr); - else - pstr->valid_len = pstr->len; } - pstr->cur_idx = 0; + else + pstr->valid_len = pstr->len; + pstr->cur_idx = 0; return REG_NOERROR; } @@ -840,16 +841,13 @@ re_string_context_at (input, idx, eflags) int idx, eflags; { int c; - if (idx < 0 || idx == input->len) - { - if (idx < 0) - /* In this case, we use the value stored in input->tip_context, - since we can't know the character in input->mbs[-1] here. */ - return input->tip_context; - else /* (idx == input->len) */ - return ((eflags & REG_NOTEOL) ? CONTEXT_ENDBUF - : CONTEXT_NEWLINE | CONTEXT_ENDBUF); - } + if (BE (idx < 0, 0)) + /* In this case, we use the value stored in input->tip_context, + since we can't know the character in input->mbs[-1] here. */ + return input->tip_context; + if (BE (idx == input->len, 0)) + return ((eflags & REG_NOTEOL) ? CONTEXT_ENDBUF + : CONTEXT_NEWLINE | CONTEXT_ENDBUF); #ifdef RE_ENABLE_I18N if (input->mb_cur_max > 1) { diff --git a/posix/regex_internal.h b/posix/regex_internal.h index 023056c028..14d95a5b84 100644 --- a/posix/regex_internal.h +++ b/posix/regex_internal.h @@ -548,9 +548,9 @@ struct re_backref_cache_entry int str_idx; int subexp_from; int subexp_to; - /* We need only one byte from the following field. If other small - fields are added the type could be changed to 'char'. */ - int more; + char more; + char unused; + unsigned short int eps_reachable_subexps_map; }; typedef struct diff --git a/posix/regexec.c b/posix/regexec.c index 72ae70b916..a03df2636a 100644 --- a/posix/regexec.c +++ b/posix/regexec.c @@ -22,8 +22,6 @@ static reg_errcode_t match_ctx_init (re_match_context_t *cache, int eflags, int n) internal_function; static void match_ctx_clean (re_match_context_t *mctx) internal_function; static void match_ctx_free (re_match_context_t *cache) internal_function; -static void match_ctx_free_subtops (re_match_context_t *mctx) - internal_function; static reg_errcode_t match_ctx_add_entry (re_match_context_t *cache, int node, int str_idx, int from, int to) internal_function; @@ -606,15 +604,16 @@ re_search_internal (preg, string, length, start, range, stop, nmatch, pmatch, reg_errcode_t err; re_dfa_t *dfa = (re_dfa_t *)preg->buffer; int left_lim, right_lim, incr; - int fl_longest_match, match_first, match_last = -1; - int fast_translate, sb; + int fl_longest_match, match_first, match_kind, match_last = -1; + int sb, ch; #if defined _LIBC || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L) re_match_context_t mctx = { .dfa = dfa }; #else re_match_context_t mctx; #endif - char *fastmap = ((preg->fastmap != NULL && preg->fastmap_accurate - && range && !preg->can_be_null) ? preg->fastmap : NULL); + char *fastmap = (preg->fastmap != NULL && preg->fastmap_accurate + && range && !preg->can_be_null) ? preg->fastmap : NULL; + unsigned RE_TRANSLATE_TYPE t = (unsigned RE_TRANSLATE_TYPE) preg->translate; #if !(defined _LIBC || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L)) memset (&mctx, '\0', sizeof (re_match_context_t)); @@ -685,88 +684,100 @@ re_search_internal (preg, string, length, start, range, stop, nmatch, pmatch, left_lim = (range < 0) ? start + range : start; right_lim = (range < 0) ? start : start + range; sb = dfa->mb_cur_max == 1; - fast_translate = sb || !(preg->syntax & RE_ICASE || preg->translate); - - for (;;) + match_kind = + (fastmap + ? ((sb || !(preg->syntax & RE_ICASE || t) ? 4 : 0) + | (range >= 0 ? 2 : 0) + | (t != NULL ? 1 : 0)) + : 8); + + for (;; match_first += incr) { - /* At first get the current byte from input string. */ - if (fastmap) + err = REG_NOMATCH; + if (match_first < left_lim || right_lim < match_first) + goto free_return; + + /* Advance as rapidly as possible through the string, until we + find a plausible place to start matching. This may be done + with varying efficiency, so there are various possibilities: + only the most common of them are specialized, in order to + save on code size. We use a switch statement for speed. */ + switch (match_kind) { - if (BE (fast_translate, 1)) + case 8: + /* No fastmap. */ + break; + + case 7: + /* Fastmap with single-byte translation, match forward. */ + while (BE (match_first < right_lim, 1) + && !fastmap[t[(unsigned char) string[match_first]]]) + ++match_first; + goto forward_match_found_start_or_reached_end; + + case 6: + /* Fastmap without translation, match forward. */ + while (BE (match_first < right_lim, 1) + && !fastmap[(unsigned char) string[match_first]]) + ++match_first; + + forward_match_found_start_or_reached_end: + if (BE (match_first == right_lim, 0)) { - unsigned RE_TRANSLATE_TYPE t - = (unsigned RE_TRANSLATE_TYPE) preg->translate; - if (BE (range >= 0, 1)) - { - if (BE (t != NULL, 0)) - { - while (BE (match_first < right_lim, 1) - && !fastmap[t[(unsigned char) string[match_first]]]) - ++match_first; - } - else - { - while (BE (match_first < right_lim, 1) - && !fastmap[(unsigned char) string[match_first]]) - ++match_first; - } - if (BE (match_first == right_lim, 0)) - { - int ch = match_first >= length - ? 0 : (unsigned char) string[match_first]; - if (!fastmap[t ? t[ch] : ch]) - break; - } - } - else - { - while (match_first >= left_lim) - { - int ch = match_first >= length - ? 0 : (unsigned char) string[match_first]; - if (fastmap[t ? t[ch] : ch]) - break; - --match_first; - } - if (match_first < left_lim) - break; - } + ch = match_first >= length + ? 0 : (unsigned char) string[match_first]; + if (!fastmap[t ? t[ch] : ch]) + goto free_return; } - else + break; + + case 4: + case 5: + /* Fastmap without multi-byte translation, match backwards. */ + while (match_first >= left_lim) { - int ch; + ch = match_first >= length + ? 0 : (unsigned char) string[match_first]; + if (fastmap[t ? t[ch] : ch]) + break; + --match_first; + } + if (match_first < left_lim) + goto free_return; + break; - do + default: + /* In this case, we can't determine easily the current byte, + since it might be a component byte of a multibyte + character. Then we use the constructed buffer instead. */ + for (;;) + { + /* If MATCH_FIRST is out of the valid range, reconstruct the + buffers. */ + unsigned int offset = match_first - mctx.input.raw_mbs_idx; + if (BE (offset >= (unsigned int) mctx.input.valid_raw_len, 0)) { - /* In this case, we can't determine easily the current byte, - since it might be a component byte of a multibyte - character. Then we use the constructed buffer - instead. */ - /* If MATCH_FIRST is out of the valid range, reconstruct the - buffers. */ - if (mctx.input.raw_mbs_idx + mctx.input.valid_raw_len - <= match_first - || match_first < mctx.input.raw_mbs_idx) - { - err = re_string_reconstruct (&mctx.input, match_first, - eflags); - if (BE (err != REG_NOERROR, 0)) - goto free_return; - } - /* If MATCH_FIRST is out of the buffer, leave it as '\0'. - Note that MATCH_FIRST must not be smaller than 0. */ - ch = ((match_first >= length) ? 0 - : re_string_byte_at (&mctx.input, - match_first - - mctx.input.raw_mbs_idx)); - if (fastmap[ch]) - break; - match_first += incr; + err = re_string_reconstruct (&mctx.input, match_first, + eflags); + if (BE (err != REG_NOERROR, 0)) + goto free_return; + + offset = match_first - mctx.input.raw_mbs_idx; } - while (match_first >= left_lim && match_first <= right_lim); - if (! fastmap[ch]) + /* If MATCH_FIRST is out of the buffer, leave it as '\0'. + Note that MATCH_FIRST must not be smaller than 0. */ + ch = (match_first >= length + ? 0 : re_string_byte_at (&mctx.input, offset)); + if (fastmap[ch]) break; + match_first += incr; + if (match_first < left_lim || match_first > right_lim) + { + err = REG_NOMATCH; + goto free_return; + } } + break; } /* Reconstruct the buffers so that the matcher can assume that @@ -774,57 +785,60 @@ re_search_internal (preg, string, length, start, range, stop, nmatch, pmatch, err = re_string_reconstruct (&mctx.input, match_first, eflags); if (BE (err != REG_NOERROR, 0)) goto free_return; + #ifdef RE_ENABLE_I18N - /* Eliminate it when it is a component of a multibyte character - and isn't the head of a multibyte character. */ - if (sb || re_string_first_byte (&mctx.input, 0)) + /* Don't consider this char as a possible match start if it part, + yet isn't the head, of a multibyte character. */ + if (!sb && !re_string_first_byte (&mctx.input, 0)) + continue; #endif + + /* It seems to be appropriate one, then use the matcher. */ + /* We assume that the matching starts from 0. */ + mctx.state_log_top = mctx.nbkref_ents = mctx.max_mb_elem_len = 0; + match_last = check_matching (&mctx, fl_longest_match, + range >= 0 ? &match_first : NULL); + if (match_last != -1) { - /* It seems to be appropriate one, then use the matcher. */ - /* We assume that the matching starts from 0. */ - mctx.state_log_top = mctx.nbkref_ents = mctx.max_mb_elem_len = 0; - match_last = check_matching (&mctx, fl_longest_match, - range >= 0 ? &match_first : NULL); - if (match_last != -1) + if (BE (match_last == -2, 0)) { - if (BE (match_last == -2, 0)) + err = REG_ESPACE; + goto free_return; + } + else + { + mctx.match_last = match_last; + if ((!preg->no_sub && nmatch > 1) || dfa->nbackref) { - err = REG_ESPACE; - goto free_return; + re_dfastate_t *pstate = mctx.state_log[match_last]; + mctx.last_node = check_halt_state_context (&mctx, pstate, + match_last); } - else + if ((!preg->no_sub && nmatch > 1 && dfa->has_plural_match) + || dfa->nbackref) { - mctx.match_last = match_last; - if ((!preg->no_sub && nmatch > 1) || dfa->nbackref) - { - re_dfastate_t *pstate = mctx.state_log[match_last]; - mctx.last_node = check_halt_state_context (&mctx, pstate, - match_last); - } - if ((!preg->no_sub && nmatch > 1 && dfa->has_plural_match) - || dfa->nbackref) - { - err = prune_impossible_nodes (&mctx); - if (err == REG_NOERROR) - break; - if (BE (err != REG_NOMATCH, 0)) - goto free_return; - match_last = -1; - } - else - break; /* We found a match. */ + err = prune_impossible_nodes (&mctx); + if (err == REG_NOERROR) + break; + if (BE (err != REG_NOMATCH, 0)) + goto free_return; + match_last = -1; } + else + break; /* We found a match. */ } - match_ctx_clean (&mctx); } - /* Update counter. */ - match_first += incr; - if (match_first < left_lim || right_lim < match_first) - break; + + match_ctx_clean (&mctx); } +#ifdef DEBUG + assert (match_last != -1); + assert (err == REG_NOERROR); +#endif + /* Set pmatch[] if we need. */ - if (match_last != -1 && nmatch > 0) + if (nmatch > 0) { int reg_idx; @@ -869,7 +883,7 @@ re_search_internal (preg, string, length, start, range, stop, nmatch, pmatch, pmatch[reg_idx].rm_eo += match_first; } } - err = (match_last == -1) ? REG_NOMATCH : REG_NOERROR; + free_return: re_free (mctx.state_log); if (dfa->nbackref) @@ -1072,6 +1086,20 @@ check_matching (mctx, fl_longest_match, p_match_first) while (!re_string_eoi (&mctx->input)) { re_dfastate_t *old_state = cur_state; + int next_char_idx = re_string_cur_idx (&mctx->input) + 1; + + if (BE (next_char_idx >= mctx->input.bufs_len, 0) + || (BE (next_char_idx >= mctx->input.valid_len, 0) + && mctx->input.valid_len < mctx->input.len)) + { + err = extend_buffers (mctx); + if (BE (err != REG_NOERROR, 0)) + { + assert (err == REG_ESPACE); + return -2; + } + } + cur_state = transit_state (&err, mctx, cur_state); if (mctx->state_log != NULL) cur_state = merge_state_with_log (&err, mctx, cur_state); @@ -1090,10 +1118,10 @@ check_matching (mctx, fl_longest_match, p_match_first) break; } - if (at_init_state) + if (BE (at_init_state, 0)) { if (old_state == cur_state) - next_start_idx = re_string_cur_idx (&mctx->input); + next_start_idx = next_char_idx; else at_init_state = 0; } @@ -1109,13 +1137,16 @@ check_matching (mctx, fl_longest_match, p_match_first) /* We found an appropriate halt state. */ match_last = re_string_cur_idx (&mctx->input); match = 1; + + /* We found a match, do not modify match_first below. */ + p_match_first = NULL; if (!fl_longest_match) break; } } - } + } - if (match_last == -1 && p_match_first) + if (p_match_first) *p_match_first += next_start_idx; return match_last; @@ -1854,7 +1885,12 @@ check_dst_limits_calc_pos_1 (mctx, boundaries, subexp_idx, from_node, bkref_idx) { int dst, cpos; - if (ent->node != node || ent->subexp_from != ent->subexp_to) + if (ent->node != node) + continue; + + if (subexp_idx <= 8 * sizeof (ent->eps_reachable_subexps_map) + && (ent->eps_reachable_subexps_map + & (1 << (subexp_idx - 1))) == 0) continue; /* Recurse trying to reach the OP_OPEN_SUBEXP and @@ -1875,11 +1911,13 @@ check_dst_limits_calc_pos_1 (mctx, boundaries, subexp_idx, from_node, bkref_idx) cpos = check_dst_limits_calc_pos_1 (mctx, boundaries, subexp_idx, dst, bkref_idx); - if (cpos == -1 && (boundaries & 1)) + if (cpos == -1 /* && (boundaries & 1) */) return -1; - if (cpos == 0 /* && (boundaries & 2) */) + if (cpos == 0 && (boundaries & 2)) return 0; + + ent->eps_reachable_subexps_map &= ~(1 << (subexp_idx - 1)); } while (ent++->more); break; @@ -2167,23 +2205,14 @@ transit_state (err, mctx, state) re_dfastate_t **trtable; unsigned char ch; - if (re_string_cur_idx (&mctx->input) + 1 >= mctx->input.bufs_len - || (re_string_cur_idx (&mctx->input) + 1 >= mctx->input.valid_len - && mctx->input.valid_len < mctx->input.len)) +#ifdef RE_ENABLE_I18N + /* If the current state can accept multibyte. */ + if (BE (state->accept_mb, 0)) { - *err = extend_buffers (mctx); + *err = transit_state_mb (mctx, state); if (BE (*err != REG_NOERROR, 0)) return NULL; } - -#ifdef RE_ENABLE_I18N - /* If the current state can accept multibyte. */ - if (state->accept_mb) - { - *err = transit_state_mb (mctx, state); - if (BE (*err != REG_NOERROR, 0)) - return NULL; - } #endif /* RE_ENABLE_I18N */ /* Then decide the next state with the single byte. */ @@ -4078,28 +4107,6 @@ static void match_ctx_clean (mctx) re_match_context_t *mctx; { - match_ctx_free_subtops (mctx); - mctx->nsub_tops = 0; - mctx->nbkref_ents = 0; -} - -/* Free all the memory associated with MCTX. */ - -static void -match_ctx_free (mctx) - re_match_context_t *mctx; -{ - match_ctx_free_subtops (mctx); - re_free (mctx->sub_tops); - re_free (mctx->bkref_ents); -} - -/* Free all the memory associated with MCTX->SUB_TOPS. */ - -static void -match_ctx_free_subtops (mctx) - re_match_context_t *mctx; -{ int st_idx; for (st_idx = 0; st_idx < mctx->nsub_tops; ++st_idx) { @@ -4119,6 +4126,21 @@ match_ctx_free_subtops (mctx) } free (top); } + + mctx->nsub_tops = 0; + mctx->nbkref_ents = 0; +} + +/* Free all the memory associated with MCTX. */ + +static void +match_ctx_free (mctx) + re_match_context_t *mctx; +{ + /* First, free all the memory associated with MCTX->SUB_TOPS. */ + match_ctx_clean (mctx); + re_free (mctx->sub_tops); + re_free (mctx->bkref_ents); } /* Add a new backreference entry to MCTX. @@ -4154,6 +4176,18 @@ match_ctx_add_entry (mctx, node, str_idx, from, to) mctx->bkref_ents[mctx->nbkref_ents].str_idx = str_idx; mctx->bkref_ents[mctx->nbkref_ents].subexp_from = from; mctx->bkref_ents[mctx->nbkref_ents].subexp_to = to; + + /* This is a cache that saves negative results of check_dst_limits_calc_pos. + If bit N is clear, means that this entry won't epsilon-transition to + an OP_OPEN_SUBEXP or OP_CLOSE_SUBEXP for the N+1-th subexpression. If + it is set, check_dst_limits_calc_pos_1 will recurse and try to find one + such node. + + A backreference does not epsilon-transition unless it is empty, so set + to all zeros if FROM != TO. */ + mctx->bkref_ents[mctx->nbkref_ents].eps_reachable_subexps_map + = (from == to ? ~0 : 0); + mctx->bkref_ents[mctx->nbkref_ents++].more = 0; if (mctx->max_mb_elem_len < to - from) mctx->max_mb_elem_len = to - from; diff --git a/posix/tst-waitid.c b/posix/tst-waitid.c index 642d529a9a..d810922f04 100644 --- a/posix/tst-waitid.c +++ b/posix/tst-waitid.c @@ -18,7 +18,7 @@ 02111-1307 USA. */ #include <errno.h> -#include <error.h> +#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/wait.h> @@ -56,16 +56,15 @@ sigchld (int signo, siginfo_t *info, void *ctx) { if (signo != SIGCHLD) { - error (0, 0, "SIGCHLD handler got signal %d instead!", signo); + printf ("SIGCHLD handler got signal %d instead!\n", signo); _exit (EXIT_FAILURE); } if (! expecting_sigchld) { spurious_sigchld = 1; - error (0, 0, - "spurious SIGCHLD: signo %d code %d status %d pid %d\n", - info->si_signo, info->si_code, info->si_status, info->si_pid); + printf ("spurious SIGCHLD: signo %d code %d status %d pid %d\n", + info->si_signo, info->si_code, info->si_status, info->si_pid); } else { @@ -79,7 +78,7 @@ check_sigchld (const char *phase, int *ok, int code, int status, pid_t pid) { if (expecting_sigchld) { - error (0, 0, "missing SIGCHLD on %s", phase); + printf ("missing SIGCHLD on %s\n", phase); *ok = EXIT_FAILURE; expecting_sigchld = 0; return; @@ -87,22 +86,22 @@ check_sigchld (const char *phase, int *ok, int code, int status, pid_t pid) if (sigchld_info.si_signo != SIGCHLD) { - error (0, 0, "SIGCHLD for %s signal %d", phase, sigchld_info.si_signo); + printf ("SIGCHLD for %s signal %d\n", phase, sigchld_info.si_signo); *ok = EXIT_FAILURE; } if (sigchld_info.si_code != code) { - error (0, 0, "SIGCHLD for %s code %d", phase, sigchld_info.si_code); + printf ("SIGCHLD for %s code %d\n", phase, sigchld_info.si_code); *ok = EXIT_FAILURE; } if (sigchld_info.si_status != status) { - error (0, 0, "SIGCHLD for %s status %d", phase, sigchld_info.si_status); + printf ("SIGCHLD for %s status %d\n", phase, sigchld_info.si_status); *ok = EXIT_FAILURE; } if (sigchld_info.si_pid != pid) { - error (0, 0, "SIGCHLD for %s pid %d", phase, sigchld_info.si_pid); + printf ("SIGCHLD for %s pid %d\n", phase, sigchld_info.si_pid); *ok = EXIT_FAILURE; } } @@ -121,7 +120,7 @@ do_test (int argc, char *argv[]) sa.sa_sigaction = &sigchld; if (sigemptyset (&sa.sa_mask) < 0 || sigaction (SIGCHLD, &sa, NULL) < 0) { - error (0, errno, "setting SIGCHLD handler"); + printf ("setting SIGCHLD handler: %m\n"); return EXIT_FAILURE; } #endif @@ -131,7 +130,7 @@ do_test (int argc, char *argv[]) pid_t pid = fork (); if (pid < 0) { - error (0, errno, "fork"); + printf ("fork: %m\n"); return EXIT_FAILURE; } else if (pid == 0) @@ -156,18 +155,18 @@ do_test (int argc, char *argv[]) switch (fail) { default: - error (0, 0, "waitid returned bogus value %d\n", fail); + printf ("waitid returned bogus value %d\n", fail); RETURN (EXIT_FAILURE); case -1: - error (0, errno, "waitid WNOHANG on stopped"); + printf ("waitid WNOHANG on stopped: %m\n"); RETURN (errno == ENOTSUP ? EXIT_SUCCESS : EXIT_FAILURE); case 0: if (info.si_signo == 0) break; if (info.si_signo == SIGCHLD) - error (0, 0, "waitid WNOHANG on stopped status %d\n", info.si_status); + printf ("waitid WNOHANG on stopped status %d\n", info.si_status); else - error (0, 0, "waitid WNOHANG on stopped signal %d\n", info.si_signo); + printf ("waitid WNOHANG on stopped signal %d\n", info.si_signo); RETURN (EXIT_FAILURE); } @@ -179,34 +178,34 @@ do_test (int argc, char *argv[]) switch (fail) { default: - error (0, 0, "waitid WSTOPPED|WNOHANG returned bogus value %d\n", fail); + printf ("waitid WSTOPPED|WNOHANG returned bogus value %d\n", fail); RETURN (EXIT_FAILURE); case -1: - error (0, errno, "waitid WSTOPPED|WNOHANG on stopped"); + printf ("waitid WSTOPPED|WNOHANG on stopped: %m\n"); RETURN (errno == ENOTSUP ? EXIT_SUCCESS : EXIT_FAILURE); case 0: if (info.si_signo != SIGCHLD) { - error (0, 0, "waitid WSTOPPED|WNOHANG on stopped signal %d\n", - info.si_signo); + printf ("waitid WSTOPPED|WNOHANG on stopped signal %d\n", + info.si_signo); RETURN (EXIT_FAILURE); } if (info.si_code != CLD_STOPPED) { - error (0, 0, "waitid WSTOPPED|WNOHANG on stopped code %d\n", - info.si_code); + printf ("waitid WSTOPPED|WNOHANG on stopped code %d\n", + info.si_code); RETURN (EXIT_FAILURE); } if (info.si_status != SIGSTOP) { - error (0, 0, "waitid WSTOPPED|WNOHANG on stopped status %d\n", - info.si_status); + printf ("waitid WSTOPPED|WNOHANG on stopped status %d\n", + info.si_status); RETURN (EXIT_FAILURE); } if (info.si_pid != pid) { - error (0, 0, "waitid WSTOPPED|WNOHANG on stopped pid %d != %d\n", - info.si_pid, pid); + printf ("waitid WSTOPPED|WNOHANG on stopped pid %d != %d\n", + info.si_pid, pid); RETURN (EXIT_FAILURE); } } @@ -215,7 +214,7 @@ do_test (int argc, char *argv[]) if (kill (pid, SIGCONT) != 0) { - error (0, errno, "kill (%d, SIGCONT)", pid); + printf ("kill (%d, SIGCONT): %m\n", pid); RETURN (EXIT_FAILURE); } @@ -225,7 +224,7 @@ do_test (int argc, char *argv[]) #if WCONTINUED != 0 if (expecting_sigchld) { - error (0, 0, "no SIGCHLD seen for SIGCONT (optional)"); + printf ("no SIGCHLD seen for SIGCONT (optional)\n"); expecting_sigchld = 0; } else @@ -238,35 +237,34 @@ do_test (int argc, char *argv[]) switch (fail) { default: - error (0, 0, - "waitid WCONTINUED|WNOWAIT returned bogus value %d\n", fail); + printf ("waitid WCONTINUED|WNOWAIT returned bogus value %d\n", fail); RETURN (EXIT_FAILURE); case -1: - error (0, errno, "waitid WCONTINUED|WNOWAIT on continued"); + printf ("waitid WCONTINUED|WNOWAIT on continued: %m\n"); RETURN (errno == ENOTSUP ? EXIT_SUCCESS : EXIT_FAILURE); case 0: if (info.si_signo != SIGCHLD) { - error (0, 0, "waitid WCONTINUED|WNOWAIT on continued signal %d\n", - info.si_signo); + printf ("waitid WCONTINUED|WNOWAIT on continued signal %d\n", + info.si_signo); RETURN (EXIT_FAILURE); } if (info.si_code != CLD_CONTINUED) { - error (0, 0, "waitid WCONTINUED|WNOWAIT on continued code %d\n", - info.si_code); + printf ("waitid WCONTINUED|WNOWAIT on continued code %d\n", + info.si_code); RETURN (EXIT_FAILURE); } if (info.si_status != SIGCONT) { - error (0, 0, "waitid WCONTINUED|WNOWAIT on continued status %d\n", - info.si_status); + printf ("waitid WCONTINUED|WNOWAIT on continued status %d\n", + info.si_status); RETURN (EXIT_FAILURE); } if (info.si_pid != pid) { - error (0, 0, "waitid WCONTINUED|WNOWAIT on continued pid %d != %d\n", - info.si_pid, pid); + printf ("waitid WCONTINUED|WNOWAIT on continued pid %d != %d\n", + info.si_pid, pid); RETURN (EXIT_FAILURE); } } @@ -279,34 +277,32 @@ do_test (int argc, char *argv[]) switch (fail) { default: - error (0, 0, "waitid WCONTINUED returned bogus value %d\n", fail); + printf ("waitid WCONTINUED returned bogus value %d\n", fail); RETURN (EXIT_FAILURE); case -1: - error (0, errno, "waitid WCONTINUED on continued"); + printf ("waitid WCONTINUED on continued: %m\n"); RETURN (errno == ENOTSUP ? EXIT_SUCCESS : EXIT_FAILURE); case 0: if (info.si_signo != SIGCHLD) { - error (0, 0, "waitid WCONTINUED on continued signal %d\n", - info.si_signo); + printf ("waitid WCONTINUED on continued signal %d\n", info.si_signo); RETURN (EXIT_FAILURE); } if (info.si_code != CLD_CONTINUED) { - error (0, 0, "waitid WCONTINUED on continued code %d\n", - info.si_code); + printf ("waitid WCONTINUED on continued code %d\n", info.si_code); RETURN (EXIT_FAILURE); } if (info.si_status != SIGCONT) { - error (0, 0, "waitid WCONTINUED on continued status %d\n", - info.si_status); + printf ("waitid WCONTINUED on continued status %d\n", + info.si_status); RETURN (EXIT_FAILURE); } if (info.si_pid != pid) { - error (0, 0, "waitid WCONTINUED on continued pid %d != %d\n", - info.si_pid, pid); + printf ("waitid WCONTINUED on continued pid %d != %d\n", + info.si_pid, pid); RETURN (EXIT_FAILURE); } } @@ -317,22 +313,20 @@ do_test (int argc, char *argv[]) switch (fail) { default: - error (0, 0, "waitid returned bogus value %d\n", fail); + printf ("waitid returned bogus value %d\n", fail); RETURN (EXIT_FAILURE); case -1: - error (0, errno, "waitid WCONTINUED|WNOHANG on waited continued"); + printf ("waitid WCONTINUED|WNOHANG on waited continued: %m\n"); RETURN (errno == ENOTSUP ? EXIT_SUCCESS : EXIT_FAILURE); case 0: if (info.si_signo == 0) break; if (info.si_signo == SIGCHLD) - error (0, 0, - "waitid WCONTINUED|WNOHANG on waited continued status %d\n", - info.si_status); + printf ("waitid WCONTINUED|WNOHANG on waited continued status %d\n", + info.si_status); else - error (0, 0, - "waitid WCONTINUED|WNOHANG on waited continued signal %d\n", - info.si_signo); + printf ("waitid WCONTINUED|WNOHANG on waited continued signal %d\n", + info.si_signo); RETURN (EXIT_FAILURE); } @@ -340,26 +334,25 @@ do_test (int argc, char *argv[]) expecting_sigchld = 1; if (kill (pid, SIGSTOP) != 0) { - error (0, errno, "kill (%d, SIGSTOP)", pid); + printf ("kill (%d, SIGSTOP): %m\n", pid); RETURN (EXIT_FAILURE); } pid_t wpid = waitpid (pid, &fail, WUNTRACED); if (wpid < 0) { - error (0, errno, "waitpid WUNTRACED on stopped"); + printf ("waitpid WUNTRACED on stopped: %m\n"); RETURN (EXIT_FAILURE); } else if (wpid != pid) { - error (0, 0, - "waitpid WUNTRACED on stopped returned %d != %d (status %x)", - wpid, pid, fail); + printf ("waitpid WUNTRACED on stopped returned %d != %d (status %x)\n", + wpid, pid, fail); RETURN (EXIT_FAILURE); } else if (!WIFSTOPPED (fail) || WIFSIGNALED (fail) || WIFEXITED (fail) || WIFCONTINUED (fail) || WSTOPSIG (fail) != SIGSTOP) { - error (0, 0, "waitpid WUNTRACED on stopped: status %x", fail); + printf ("waitpid WUNTRACED on stopped: status %x\n", fail); RETURN (EXIT_FAILURE); } CHECK_SIGCHLD ("stopped", CLD_STOPPED, SIGSTOP); @@ -367,7 +360,7 @@ do_test (int argc, char *argv[]) expecting_sigchld = 1; if (kill (pid, SIGCONT) != 0) { - error (0, errno, "kill (%d, SIGCONT)", pid); + printf ("kill (%d, SIGCONT): %m\n", pid); RETURN (EXIT_FAILURE); } @@ -376,7 +369,7 @@ do_test (int argc, char *argv[]) if (expecting_sigchld) { - error (0, 0, "no SIGCHLD seen for SIGCONT (optional)"); + printf ("no SIGCHLD seen for SIGCONT (optional)\n"); expecting_sigchld = 0; } else @@ -386,24 +379,24 @@ do_test (int argc, char *argv[]) if (wpid < 0) { if (errno == EINVAL) - error (0, 0, "waitpid does not support WCONTINUED"); + printf ("waitpid does not support WCONTINUED\n"); else { - error (0, errno, "waitpid WCONTINUED on continued"); + printf ("waitpid WCONTINUED on continued: %m\n"); RETURN (EXIT_FAILURE); } } else if (wpid != pid) { - error (0, 0, - "waitpid WCONTINUED on continued returned %d != %d (status %x)", + printf ("\ +waitpid WCONTINUED on continued returned %d != %d (status %x)\n", wpid, pid, fail); RETURN (EXIT_FAILURE); } else if (WIFSTOPPED (fail) || WIFSIGNALED (fail) || WIFEXITED (fail) || !WIFCONTINUED (fail)) { - error (0, 0, "waitpid WCONTINUED on continued: status %x", fail); + printf ("waitpid WCONTINUED on continued: status %x\n", fail); RETURN (EXIT_FAILURE); } #endif @@ -413,7 +406,7 @@ do_test (int argc, char *argv[]) /* Die, child, die! */ if (kill (pid, SIGKILL) != 0) { - error (0, errno, "kill (%d, SIGKILL)", pid); + printf ("kill (%d, SIGKILL): %m\n", pid); RETURN (EXIT_FAILURE); } @@ -425,34 +418,30 @@ do_test (int argc, char *argv[]) switch (fail) { default: - error (0, 0, "waitid WNOWAIT returned bogus value %d\n", fail); + printf ("waitid WNOWAIT returned bogus value %d\n", fail); RETURN (EXIT_FAILURE); case -1: - error (0, errno, "waitid WNOWAIT on killed"); + printf ("waitid WNOWAIT on killed: %m\n"); RETURN (errno == ENOTSUP ? EXIT_SUCCESS : EXIT_FAILURE); case 0: if (info.si_signo != SIGCHLD) { - error (0, 0, "waitid WNOWAIT on killed signal %d\n", - info.si_signo); + printf ("waitid WNOWAIT on killed signal %d\n", info.si_signo); RETURN (EXIT_FAILURE); } if (info.si_code != CLD_KILLED) { - error (0, 0, "waitid WNOWAIT on killed code %d\n", - info.si_code); + printf ("waitid WNOWAIT on killed code %d\n", info.si_code); RETURN (EXIT_FAILURE); } if (info.si_status != SIGKILL) { - error (0, 0, "waitid WNOWAIT on killed status %d\n", - info.si_status); + printf ("waitid WNOWAIT on killed status %d\n", info.si_status); RETURN (EXIT_FAILURE); } if (info.si_pid != pid) { - error (0, 0, "waitid WNOWAIT on killed pid %d != %d\n", - info.si_pid, pid); + printf ("waitid WNOWAIT on killed pid %d != %d\n", info.si_pid, pid); RETURN (EXIT_FAILURE); } } @@ -470,34 +459,30 @@ do_test (int argc, char *argv[]) switch (fail) { default: - error (0, 0, "waitid WNOHANG returned bogus value %d\n", fail); + printf ("waitid WNOHANG returned bogus value %d\n", fail); RETURN (EXIT_FAILURE); case -1: - error (0, errno, "waitid WNOHANG on killed"); + printf ("waitid WNOHANG on killed: %m\n"); RETURN (EXIT_FAILURE); case 0: if (info.si_signo != SIGCHLD) { - error (0, 0, "waitid WNOHANG on killed signal %d\n", - info.si_signo); + printf ("waitid WNOHANG on killed signal %d\n", info.si_signo); RETURN (EXIT_FAILURE); } if (info.si_code != CLD_KILLED) { - error (0, 0, "waitid WNOHANG on killed code %d\n", - info.si_code); + printf ("waitid WNOHANG on killed code %d\n", info.si_code); RETURN (EXIT_FAILURE); } if (info.si_status != SIGKILL) { - error (0, 0, "waitid WNOHANG on killed status %d\n", - info.si_status); + printf ("waitid WNOHANG on killed status %d\n", info.si_status); RETURN (EXIT_FAILURE); } if (info.si_pid != pid) { - error (0, 0, "waitid WNOHANG on killed pid %d != %d\n", - info.si_pid, pid); + printf ("waitid WNOHANG on killed pid %d != %d\n", info.si_pid, pid); RETURN (EXIT_FAILURE); } } @@ -507,13 +492,13 @@ do_test (int argc, char *argv[]) { if (errno != ECHILD) { - error (0, errno, "waitid WEXITED on killed"); + printf ("waitid WEXITED on killed: %m\n"); RETURN (EXIT_FAILURE); } } else { - error (0, 0, "waitid WEXITED returned bogus value %d\n", fail); + printf ("waitid WEXITED returned bogus value %d\n", fail); RETURN (EXIT_FAILURE); } diff --git a/sysdeps/generic/strtok_r.c b/sysdeps/generic/strtok_r.c index 3a5c047b8c..b11cb520f6 100644 --- a/sysdeps/generic/strtok_r.c +++ b/sysdeps/generic/strtok_r.c @@ -17,11 +17,22 @@ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + #include <string.h> #undef strtok_r #undef __strtok_r +#ifndef _LIBC +/* Get specification. */ +# include "strtok_r.h" +# define __strtok_r strtok_r +# define __rawmemchr strchr +#endif + /* Parse S into tokens separated by characters in DELIM. If S is NULL, the saved pointer in SAVE_PTR is used as the next starting point. For example: @@ -33,10 +44,7 @@ // s = "abc\0-def\0" */ char * -__strtok_r (s, delim, save_ptr) - char *s; - const char *delim; - char **save_ptr; +__strtok_r (char *s, const char *delim, char **save_ptr) { char *token; @@ -65,5 +73,7 @@ __strtok_r (s, delim, save_ptr) } return token; } +#ifdef weak_alias libc_hidden_def (__strtok_r) weak_alias (__strtok_r, strtok_r) +#endif diff --git a/sysdeps/unix/setxid.h b/sysdeps/unix/setxid.h new file mode 100644 index 0000000000..c18e2d4a6b --- /dev/null +++ b/sysdeps/unix/setxid.h @@ -0,0 +1,4 @@ +#include <sysdep.h> + +#define INLINE_SETXID_SYSCALL(name, nr, args...) \ + INLINE_SYSCALL (name, nr, args) diff --git a/sysdeps/unix/sysv/linux/alpha/setregid.c b/sysdeps/unix/sysv/linux/alpha/setregid.c index cfc8283c3a..0973fe4ac1 100644 --- a/sysdeps/unix/sysv/linux/alpha/setregid.c +++ b/sysdeps/unix/sysv/linux/alpha/setregid.c @@ -18,35 +18,13 @@ #include <errno.h> #include <unistd.h> -#include <sys/types.h> - -#include <sysdep.h> -#include <sys/syscall.h> - -#include <linux/posix_types.h> -#include "kernel-features.h" -#include <pthread-functions.h> +#include <setxid.h> int __setregid (gid_t rgid, gid_t egid) { - int result; - - result = INLINE_SYSCALL (setregid, 2, (signed int)rgid, (signed int)egid); - -#if defined HAVE_PTR__NPTL_SETXID && !defined SINGLE_THREAD - if (result == 0 && __libc_pthread_functions.ptr__nptl_setxid != NULL) - { - struct xid_command cmd; - cmd.syscall_no = __NR_setregid; - cmd.id[0] = rgid; - cmd.id[1] = egid; - __libc_pthread_functions.ptr__nptl_setxid (&cmd); - } -#endif - - return result; + return INLINE_SETXID_SYSCALL (setregid, 2, (int) rgid, (int) egid); } #ifndef __setregid weak_alias (__setregid, setregid) diff --git a/sysdeps/unix/sysv/linux/alpha/setresgid.c b/sysdeps/unix/sysv/linux/alpha/setresgid.c index fdfa486534..50e29e3c76 100644 --- a/sysdeps/unix/sysv/linux/alpha/setresgid.c +++ b/sysdeps/unix/sysv/linux/alpha/setresgid.c @@ -18,36 +18,14 @@ #include <errno.h> #include <unistd.h> -#include <sys/types.h> - -#include <sysdep.h> -#include <sys/syscall.h> - -#include <linux/posix_types.h> -#include "kernel-features.h" -#include <pthread-functions.h> +#include <setxid.h> int __setresgid (gid_t rgid, gid_t egid, gid_t sgid) { - int result; - - result = INLINE_SYSCALL (setresgid, 3, (signed int)rgid, (signed int)egid, (signed int)sgid); - -#if defined HAVE_PTR__NPTL_SETXID && !defined SINGLE_THREAD - if (result == 0 && __libc_pthread_functions.ptr__nptl_setxid != NULL) - { - struct xid_command cmd; - cmd.syscall_no = __NR_setresgid; - cmd.id[0] = rgid; - cmd.id[1] = egid; - cmd.id[2] = sgid; - __libc_pthread_functions.ptr__nptl_setxid (&cmd); - } -#endif - - return result; + return INLINE_SETXID_SYSCALL (setresgid, 3, (int) rgid, + (int) egid, (int) sgid); } libc_hidden_def (__setresgid) #ifndef __setresgid diff --git a/sysdeps/unix/sysv/linux/alpha/setresuid.c b/sysdeps/unix/sysv/linux/alpha/setresuid.c index 49671278ee..e76413bf6a 100644 --- a/sysdeps/unix/sysv/linux/alpha/setresuid.c +++ b/sysdeps/unix/sysv/linux/alpha/setresuid.c @@ -18,36 +18,14 @@ #include <errno.h> #include <unistd.h> -#include <sys/types.h> - -#include <sysdep.h> -#include <sys/syscall.h> - -#include <linux/posix_types.h> -#include "kernel-features.h" -#include <pthread-functions.h> +#include <setxid.h> int __setresuid (uid_t ruid, uid_t euid, uid_t suid) { - int result; - - result = INLINE_SYSCALL (setresuid, 3, (signed int)ruid, (signed int)euid, (signed int)suid); - -#if defined HAVE_PTR__NPTL_SETXID && !defined SINGLE_THREAD - if (result == 0 && __libc_pthread_functions.ptr__nptl_setxid != NULL) - { - struct xid_command cmd; - cmd.syscall_no = __NR_setresuid; - cmd.id[0] = ruid; - cmd.id[1] = euid; - cmd.id[2] = suid; - __libc_pthread_functions.ptr__nptl_setxid (&cmd); - } -#endif - - return result; + return INLINE_SETXID_SYSCALL (setresuid, 3, (int) ruid, + (int) euid, (int) suid); } libc_hidden_def (__setresuid) #ifndef __setresuid diff --git a/sysdeps/unix/sysv/linux/alpha/setreuid.c b/sysdeps/unix/sysv/linux/alpha/setreuid.c index b29aed479e..a23a34792e 100644 --- a/sysdeps/unix/sysv/linux/alpha/setreuid.c +++ b/sysdeps/unix/sysv/linux/alpha/setreuid.c @@ -18,35 +18,13 @@ #include <errno.h> #include <unistd.h> -#include <sys/types.h> - -#include <sysdep.h> -#include <sys/syscall.h> - -#include <linux/posix_types.h> -#include "kernel-features.h" -#include <pthread-functions.h> +#include <setxid.h> int __setreuid (uid_t ruid, uid_t euid) { - int result; - - result = INLINE_SYSCALL (setreuid, 2, (signed int)ruid, (signed int)euid); - -#if defined HAVE_PTR__NPTL_SETXID && !defined SINGLE_THREAD - if (result == 0 && __libc_pthread_functions.ptr__nptl_setxid != NULL) - { - struct xid_command cmd; - cmd.syscall_no = __NR_setreuid; - cmd.id[0] = ruid; - cmd.id[1] = euid; - __libc_pthread_functions.ptr__nptl_setxid (&cmd); - } -#endif - - return result; + return INLINE_SETXID_SYSCALL (setreuid, 2, (int) ruid, (int) euid); } #ifndef __setreuid weak_alias (__setreuid, setreuid) diff --git a/sysdeps/unix/sysv/linux/i386/setegid.c b/sysdeps/unix/sysv/linux/i386/setegid.c index b8682e3681..b4bf33f18f 100644 --- a/sysdeps/unix/sysv/linux/i386/setegid.c +++ b/sysdeps/unix/sysv/linux/i386/setegid.c @@ -18,11 +18,8 @@ #include <errno.h> #include <unistd.h> -#include <sys/types.h> - -#include <sysdep.h> +#include <setxid.h> #include "kernel-features.h" -#include <pthread-functions.h> #ifdef __NR_setresgid @@ -42,7 +39,7 @@ setegid (gid) } #if __ASSUME_32BITUIDS > 0 - result = INLINE_SYSCALL (setresgid32, 3, -1, gid, -1); + result = INLINE_SETXID_SYSCALL (setresgid32, 3, -1, gid, -1); #else /* First try the syscall. */ # ifdef __NR_setresgid @@ -59,18 +56,6 @@ setegid (gid) result = __setregid (-1, gid); #endif -#if defined HAVE_PTR__NPTL_SETXID && !defined SINGLE_THREAD - if (result == 0 && __libc_pthread_functions.ptr__nptl_setxid != NULL) - { - struct xid_command cmd; - cmd.syscall_no = __NR_setresgid32; - cmd.id[0] = -1; - cmd.id[1] = gid; - cmd.id[2] = -1; - __libc_pthread_functions.ptr__nptl_setxid (&cmd); - } -#endif - return result; } libc_hidden_def (setegid) diff --git a/sysdeps/unix/sysv/linux/i386/seteuid.c b/sysdeps/unix/sysv/linux/i386/seteuid.c index 0abdac832f..c139684d04 100644 --- a/sysdeps/unix/sysv/linux/i386/seteuid.c +++ b/sysdeps/unix/sysv/linux/i386/seteuid.c @@ -17,12 +17,9 @@ 02111-1307 USA. */ #include <errno.h> -#include <sys/types.h> #include <unistd.h> - -#include <sysdep.h> +#include <setxid.h> #include "kernel-features.h" -#include <pthread-functions.h> #ifdef __NR_setresuid @@ -41,7 +38,7 @@ seteuid (uid_t uid) } #if __ASSUME_32BITUIDS > 0 - result = INLINE_SYSCALL (setresuid32, 3, -1, uid, -1); + result = INLINE_SETXID_SYSCALL (setresuid32, 3, -1, uid, -1); #else /* First try the syscall. */ # ifdef __NR_setresuid @@ -58,18 +55,6 @@ seteuid (uid_t uid) result = __setreuid (-1, uid); #endif -#if defined HAVE_PTR__NPTL_SETXID && !defined SINGLE_THREAD - if (result == 0 && __libc_pthread_functions.ptr__nptl_setxid != NULL) - { - struct xid_command cmd; - cmd.syscall_no = __NR_setresuid32; - cmd.id[0] = -1; - cmd.id[1] = uid; - cmd.id[2] = -1; - __libc_pthread_functions.ptr__nptl_setxid (&cmd); - } -#endif - return result; } libc_hidden_def (seteuid) diff --git a/sysdeps/unix/sysv/linux/i386/setgid.c b/sysdeps/unix/sysv/linux/i386/setgid.c index 17bfc3e58a..19b1e9f500 100644 --- a/sysdeps/unix/sysv/linux/i386/setgid.c +++ b/sysdeps/unix/sysv/linux/i386/setgid.c @@ -1,5 +1,4 @@ -/* Copyright (C) 1998, 2000, 2003, 2004 - Free Software Foundation, Inc. +/* Copyright (C) 1998, 2000, 2003, 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -19,15 +18,8 @@ #include <errno.h> #include <unistd.h> -#include <sys/types.h> - -#include <sysdep.h> -#include <sys/syscall.h> - -#include <linux/posix_types.h> - +#include <setxid.h> #include "kernel-features.h" -#include <pthread-functions.h> #ifdef __NR_setgid32 @@ -44,14 +36,14 @@ __setgid (gid_t gid) int result; #if __ASSUME_32BITUIDS > 0 - result = INLINE_SYSCALL (setgid32, 1, gid); + result = INLINE_SETXID_SYSCALL (setgid32, 1, gid); #else # ifdef __NR_setgid32 if (__libc_missing_32bit_uids <= 0) { int saved_errno = errno; - result = INLINE_SYSCALL (setgid32, 1, gid); + result = INLINE_SETXID_SYSCALL (setgid32, 1, gid); if (result == 0) goto out; @@ -70,22 +62,12 @@ __setgid (gid_t gid) return -1; } - result = INLINE_SYSCALL (setgid, 1, gid); + result = INLINE_SETXID_SYSCALL (setgid, 1, gid); # ifdef __NR_setgid32 out: # endif #endif -#if defined HAVE_PTR__NPTL_SETXID && !defined SINGLE_THREAD - if (result == 0 && __libc_pthread_functions.ptr__nptl_setxid != NULL) - { - struct xid_command cmd; - cmd.syscall_no = __NR_setgid32; - cmd.id[0] = gid; - __libc_pthread_functions.ptr__nptl_setxid (&cmd); - } -#endif - return result; } #ifndef __setgid diff --git a/sysdeps/unix/sysv/linux/i386/setregid.c b/sysdeps/unix/sysv/linux/i386/setregid.c index f883497fae..be7870d3b7 100644 --- a/sysdeps/unix/sysv/linux/i386/setregid.c +++ b/sysdeps/unix/sysv/linux/i386/setregid.c @@ -17,15 +17,9 @@ 02111-1307 USA. */ #include <errno.h> -#include <sys/types.h> #include <unistd.h> - -#include <sysdep.h> -#include <sys/syscall.h> - -#include <linux/posix_types.h> +#include <setxid.h> #include "kernel-features.h" -#include <pthread-functions.h> #ifdef __NR_setregid32 @@ -42,14 +36,14 @@ __setregid (gid_t rgid, gid_t egid) int result; #if __ASSUME_32BITUIDS > 0 - result = INLINE_SYSCALL (setregid32, 2, rgid, egid); + result = INLINE_SETXID_SYSCALL (setregid32, 2, rgid, egid); #else # ifdef __NR_setregid32 if (__libc_missing_32bit_uids <= 0) { int saved_errno = errno; - result = INLINE_SYSCALL (setregid32, 2, rgid, egid); + result = INLINE_SETXID_SYSCALL (setregid32, 2, rgid, egid); if (result == 0) goto out; @@ -67,23 +61,12 @@ __setregid (gid_t rgid, gid_t egid) return -1; } - result = INLINE_SYSCALL (setregid, 2, rgid, egid); + result = INLINE_SETXID_SYSCALL (setregid, 2, rgid, egid); # ifdef __NR_setregid32 out: # endif #endif -#if defined HAVE_PTR__NPTL_SETXID && !defined SINGLE_THREAD - if (result == 0 && __libc_pthread_functions.ptr__nptl_setxid != NULL) - { - struct xid_command cmd; - cmd.syscall_no = __NR_setregid32; - cmd.id[0] = rgid; - cmd.id[1] = egid; - __libc_pthread_functions.ptr__nptl_setxid (&cmd); - } -#endif - return result; } #ifndef __setregid diff --git a/sysdeps/unix/sysv/linux/i386/setresgid.c b/sysdeps/unix/sysv/linux/i386/setresgid.c index 614e2c256d..c8b17ee7fc 100644 --- a/sysdeps/unix/sysv/linux/i386/setresgid.c +++ b/sysdeps/unix/sysv/linux/i386/setresgid.c @@ -18,14 +18,8 @@ #include <errno.h> #include <unistd.h> -#include <sys/types.h> - -#include <linux/posix_types.h> - -#include <sysdep.h> -#include <sys/syscall.h> +#include <setxid.h> #include "kernel-features.h" -#include <pthread-functions.h> #if defined __NR_setresgid || defined __NR_setresgid32 @@ -44,14 +38,14 @@ __setresgid (gid_t rgid, gid_t egid, gid_t sgid) int result; # if __ASSUME_32BITUIDS > 0 || !defined __NR_setresgid - result = INLINE_SYSCALL (setresgid32, 3, rgid, egid, sgid); + result = INLINE_SETXID_SYSCALL (setresgid32, 3, rgid, egid, sgid); # else # ifdef __NR_setresgid32 if (__libc_missing_32bit_uids <= 0) { int saved_errno = errno; - result = INLINE_SYSCALL (setresgid32, 3, rgid, egid, sgid); + result = INLINE_SETXID_SYSCALL (setresgid32, 3, rgid, egid, sgid); if (result == 0) goto out; if (errno != ENOSYS) @@ -70,24 +64,12 @@ __setresgid (gid_t rgid, gid_t egid, gid_t sgid) return -1; } - result = INLINE_SYSCALL (setresgid, 3, rgid, egid, sgid); + result = INLINE_SETXID_SYSCALL (setresgid, 3, rgid, egid, sgid); # ifdef __NR_setresgid32 out: # endif # endif -#if defined HAVE_PTR__NPTL_SETXID && !defined SINGLE_THREAD - if (result == 0 && __libc_pthread_functions.ptr__nptl_setxid != NULL) - { - struct xid_command cmd; - cmd.syscall_no = __NR_setresgid32; - cmd.id[0] = rgid; - cmd.id[1] = egid; - cmd.id[2] = sgid; - __libc_pthread_functions.ptr__nptl_setxid (&cmd); - } -#endif - return result; } libc_hidden_def (__setresgid) diff --git a/sysdeps/unix/sysv/linux/i386/setresuid.c b/sysdeps/unix/sysv/linux/i386/setresuid.c index 4d735ca0f9..a91896a1a4 100644 --- a/sysdeps/unix/sysv/linux/i386/setresuid.c +++ b/sysdeps/unix/sysv/linux/i386/setresuid.c @@ -18,14 +18,8 @@ #include <errno.h> #include <unistd.h> -#include <sys/types.h> - -#include <linux/posix_types.h> - -#include <sysdep.h> -#include <sys/syscall.h> +#include <setxid.h> #include "kernel-features.h" -#include <pthread-functions.h> #if defined __NR_setresuid || defined __NR_setresuid32 @@ -44,14 +38,14 @@ __setresuid (uid_t ruid, uid_t euid, uid_t suid) int result; # if __ASSUME_32BITUIDS > 0 || !defined __NR_setresuid - result = INLINE_SYSCALL (setresuid32, 3, ruid, euid, suid); + result = INLINE_SETXID_SYSCALL (setresuid32, 3, ruid, euid, suid); # else # ifdef __NR_setresuid32 if (__libc_missing_32bit_uids <= 0) { int saved_errno = errno; - result = INLINE_SYSCALL (setresuid32, 3, ruid, euid, suid); + result = INLINE_SETXID_SYSCALL (setresuid32, 3, ruid, euid, suid); if (result == 0) goto out; if (errno != ENOSYS) @@ -70,24 +64,12 @@ __setresuid (uid_t ruid, uid_t euid, uid_t suid) return -1; } - result = INLINE_SYSCALL (setresuid, 3, ruid, euid, suid); + result = INLINE_SETXID_SYSCALL (setresuid, 3, ruid, euid, suid); # ifdef __NR_setresuid32 out: # endif # endif -#if defined HAVE_PTR__NPTL_SETXID && !defined SINGLE_THREAD - if (result == 0 && __libc_pthread_functions.ptr__nptl_setxid != NULL) - { - struct xid_command cmd; - cmd.syscall_no = __NR_setresuid32; - cmd.id[0] = ruid; - cmd.id[1] = euid; - cmd.id[2] = suid; - __libc_pthread_functions.ptr__nptl_setxid (&cmd); - } -#endif - return result; } libc_hidden_def (__setresuid) diff --git a/sysdeps/unix/sysv/linux/i386/setreuid.c b/sysdeps/unix/sysv/linux/i386/setreuid.c index 1e1bfcf0d4..55dae1ebab 100644 --- a/sysdeps/unix/sysv/linux/i386/setreuid.c +++ b/sysdeps/unix/sysv/linux/i386/setreuid.c @@ -17,15 +17,9 @@ 02111-1307 USA. */ #include <errno.h> -#include <sys/types.h> #include <unistd.h> - -#include <sysdep.h> -#include <sys/syscall.h> - -#include <linux/posix_types.h> +#include <setxid.h> #include "kernel-features.h" -#include <pthread-functions.h> #ifdef __NR_setreuid32 @@ -42,14 +36,14 @@ __setreuid (uid_t ruid, uid_t euid) int result; #if __ASSUME_32BITUIDS > 0 - result = INLINE_SYSCALL (setreuid32, 2, ruid, euid); + result = INLINE_SETXID_SYSCALL (setreuid32, 2, ruid, euid); #else # ifdef __NR_setreuid32 if (__libc_missing_32bit_uids <= 0) { int saved_errno = errno; - result = INLINE_SYSCALL (setreuid32, 2, ruid, euid); + result = INLINE_SETXID_SYSCALL (setreuid32, 2, ruid, euid); if (result == 0) goto out; @@ -67,23 +61,12 @@ __setreuid (uid_t ruid, uid_t euid) return -1; } - result = INLINE_SYSCALL (setreuid, 2, ruid, euid); + result = INLINE_SETXID_SYSCALL (setreuid, 2, ruid, euid); # ifdef __NR_setreuid32 out: # endif #endif -#if defined HAVE_PTR__NPTL_SETXID && !defined SINGLE_THREAD - if (result == 0 && __libc_pthread_functions.ptr__nptl_setxid != NULL) - { - struct xid_command cmd; - cmd.syscall_no = __NR_setreuid32; - cmd.id[0] = ruid; - cmd.id[1] = euid; - __libc_pthread_functions.ptr__nptl_setxid (&cmd); - } -#endif - return result; } #ifndef __setreuid diff --git a/sysdeps/unix/sysv/linux/i386/setuid.c b/sysdeps/unix/sysv/linux/i386/setuid.c index 0d948fb775..9ebf76267f 100644 --- a/sysdeps/unix/sysv/linux/i386/setuid.c +++ b/sysdeps/unix/sysv/linux/i386/setuid.c @@ -18,14 +18,8 @@ #include <errno.h> #include <unistd.h> -#include <sys/types.h> - -#include <sysdep.h> -#include <sys/syscall.h> - -#include <linux/posix_types.h> +#include <setxid.h> #include "kernel-features.h" -#include <pthread-functions.h> #ifdef __NR_setuid32 @@ -42,14 +36,14 @@ __setuid (uid_t uid) int result; #if __ASSUME_32BITUIDS > 0 && defined __NR_setuid32 - result = INLINE_SYSCALL (setuid32, 1, uid); + result = INLINE_SETXID_SYSCALL (setuid32, 1, uid); #else # ifdef __NR_setuid32 if (__libc_missing_32bit_uids <= 0) { int saved_errno = errno; - result = INLINE_SYSCALL (setuid32, 1, uid); + result = INLINE_SETXID_SYSCALL (setuid32, 1, uid); if (result == 0) goto out; if (errno != ENOSYS) @@ -67,22 +61,12 @@ __setuid (uid_t uid) return -1; } - result = INLINE_SYSCALL (setuid, 1, uid); + result = INLINE_SETXID_SYSCALL (setuid, 1, uid); # ifdef __NR_setuid32 out: # endif #endif -#if defined HAVE_PTR__NPTL_SETXID && !defined SINGLE_THREAD - if (result == 0 && __libc_pthread_functions.ptr__nptl_setxid != NULL) - { - struct xid_command cmd; - cmd.syscall_no = __NR_setuid32; - cmd.id[0] = uid; - __libc_pthread_functions.ptr__nptl_setxid (&cmd); - } -#endif - return result; } #ifndef __setuid diff --git a/sysdeps/unix/sysv/linux/setegid.c b/sysdeps/unix/sysv/linux/setegid.c index 33e91c773a..f87af0d16f 100644 --- a/sysdeps/unix/sysv/linux/setegid.c +++ b/sysdeps/unix/sysv/linux/setegid.c @@ -17,13 +17,9 @@ 02111-1307 USA. */ #include <errno.h> -#include <sys/syscall.h> -#include <sys/types.h> #include <unistd.h> - -#include <sysdep.h> +#include <setxid.h> #include "kernel-features.h" -#include <pthread-functions.h> #if defined __NR_setresgid || __ASSUME_SETRESGID_SYSCALL > 0 @@ -42,10 +38,10 @@ setegid (gid_t gid) } # if __ASSUME_32BITUIDS > 0 && defined __NR_setresgid32 - result = INLINE_SYSCALL (setresgid32, 3, -1, gid, -1); + result = INLINE_SETXID_SYSCALL (setresgid32, 3, -1, gid, -1); # else /* First try the syscall. */ - result = INLINE_SYSCALL (setresgid, 3, -1, gid, -1); + result = INLINE_SETXID_SYSCALL (setresgid, 3, -1, gid, -1); # if __ASSUME_SETRESGID_SYSCALL == 0 if (result == -1 && errno == ENOSYS) /* No system call available. Use emulation. This may not work @@ -55,22 +51,6 @@ setegid (gid_t gid) # endif # endif -#if defined HAVE_PTR__NPTL_SETXID && !defined SINGLE_THREAD - if (result == 0 && __libc_pthread_functions.ptr__nptl_setxid != NULL) - { - struct xid_command cmd; -# ifdef __NR_setresgid32 - cmd.syscall_no = __NR_setresgid32; -# else - cmd.syscall_no = __NR_setresgid; -# endif - cmd.id[0] = -1; - cmd.id[1] = gid; - cmd.id[2] = -1; - __libc_pthread_functions.ptr__nptl_setxid (&cmd); - } -#endif - return result; } #ifndef setegid diff --git a/sysdeps/unix/sysv/linux/seteuid.c b/sysdeps/unix/sysv/linux/seteuid.c index da03a1e6ef..5e5d1e184f 100644 --- a/sysdeps/unix/sysv/linux/seteuid.c +++ b/sysdeps/unix/sysv/linux/seteuid.c @@ -17,13 +17,9 @@ 02111-1307 USA. */ #include <errno.h> -#include <sys/syscall.h> -#include <sys/types.h> #include <unistd.h> - -#include <sysdep.h> +#include <setxid.h> #include "kernel-features.h" -#include <pthread-functions.h> #if defined __NR_setresuid || __ASSUME_SETRESUID_SYSCALL > 0 @@ -42,10 +38,10 @@ seteuid (uid_t uid) } # if __ASSUME_32BITUIDS > 0 && defined __NR_setresuid32 - result = INLINE_SYSCALL (setresuid32, 3, -1, uid, -1); + result = INLINE_SETXID_SYSCALL (setresuid32, 3, -1, uid, -1); # else /* First try the syscall. */ - result = INLINE_SYSCALL (setresuid, 3, -1, uid, -1); + result = INLINE_SETXID_SYSCALL (setresuid, 3, -1, uid, -1); # if __ASSUME_SETRESUID_SYSCALL == 0 if (result == -1 && errno == ENOSYS) /* No system call available. Use emulation. This may not work @@ -55,22 +51,6 @@ seteuid (uid_t uid) # endif # endif -#if defined HAVE_PTR__NPTL_SETXID && !defined SINGLE_THREAD - if (result == 0 && __libc_pthread_functions.ptr__nptl_setxid != NULL) - { - struct xid_command cmd; -# ifdef __NR_setresuid32 - cmd.syscall_no = __NR_setresuid32; -# else - cmd.syscall_no = __NR_setresuid; -# endif - cmd.id[0] = -1; - cmd.id[1] = uid; - cmd.id[2] = -1; - __libc_pthread_functions.ptr__nptl_setxid (&cmd); - } -#endif - return result; } #ifndef seteuid diff --git a/sysdeps/unix/sysv/linux/setgid.c b/sysdeps/unix/sysv/linux/setgid.c index dae642abb5..1411f53659 100644 --- a/sysdeps/unix/sysv/linux/setgid.c +++ b/sysdeps/unix/sysv/linux/setgid.c @@ -18,35 +18,13 @@ #include <errno.h> #include <unistd.h> -#include <sys/types.h> - -#include <sysdep.h> -#include <sys/syscall.h> - -#include <linux/posix_types.h> -#include "kernel-features.h" -#include <pthread-functions.h> - +#include <setxid.h> int __setgid (gid_t gid) { - int result; - - result = INLINE_SYSCALL (setgid, 1, gid); - -#if defined HAVE_PTR__NPTL_SETXID && !defined SINGLE_THREAD - if (result == 0 && __libc_pthread_functions.ptr__nptl_setxid != NULL) - { - struct xid_command cmd; - cmd.syscall_no = __NR_setgid; - cmd.id[0] = gid; - __libc_pthread_functions.ptr__nptl_setxid (&cmd); - } -#endif - - return result; + return INLINE_SETXID_SYSCALL (setgid, 1, gid); } #ifndef __setgid weak_alias (__setgid, setgid) diff --git a/sysdeps/unix/sysv/linux/setregid.c b/sysdeps/unix/sysv/linux/setregid.c index 1d539260ed..df79eae913 100644 --- a/sysdeps/unix/sysv/linux/setregid.c +++ b/sysdeps/unix/sysv/linux/setregid.c @@ -18,35 +18,13 @@ #include <errno.h> #include <unistd.h> -#include <sys/types.h> - -#include <sysdep.h> -#include <sys/syscall.h> - -#include <linux/posix_types.h> -#include "kernel-features.h" -#include <pthread-functions.h> +#include <setxid.h> int __setregid (gid_t rgid, gid_t egid) { - int result; - - result = INLINE_SYSCALL (setregid, 2, rgid, egid); - -#if defined HAVE_PTR__NPTL_SETXID && !defined SINGLE_THREAD - if (result == 0 && __libc_pthread_functions.ptr__nptl_setxid != NULL) - { - struct xid_command cmd; - cmd.syscall_no = __NR_setregid; - cmd.id[0] = rgid; - cmd.id[1] = egid; - __libc_pthread_functions.ptr__nptl_setxid (&cmd); - } -#endif - - return result; + return INLINE_SETXID_SYSCALL (setregid, 2, rgid, egid); } #ifndef __setregid weak_alias (__setregid, setregid) diff --git a/sysdeps/unix/sysv/linux/setresgid.c b/sysdeps/unix/sysv/linux/setresgid.c index ae61d42e6b..d6c9758d71 100644 --- a/sysdeps/unix/sysv/linux/setresgid.c +++ b/sysdeps/unix/sysv/linux/setresgid.c @@ -18,37 +18,15 @@ #include <errno.h> #include <unistd.h> -#include <sys/types.h> - -#include <sysdep.h> -#include <sys/syscall.h> - -#include <linux/posix_types.h> -#include "kernel-features.h" -#include <pthread-functions.h> +#include <setxid.h> int __setresgid (gid_t rgid, gid_t egid, gid_t sgid) { - int result; - - result = INLINE_SYSCALL (setresgid, 3, rgid, egid, sgid); - -#if defined HAVE_PTR__NPTL_SETXID && !defined SINGLE_THREAD - if (result == 0 && __libc_pthread_functions.ptr__nptl_setxid != NULL) - { - struct xid_command cmd; - cmd.syscall_no = __NR_setresgid; - cmd.id[0] = rgid; - cmd.id[1] = egid; - cmd.id[2] = sgid; - __libc_pthread_functions.ptr__nptl_setxid (&cmd); - } -#endif - - return result; + return INLINE_SETXID_SYSCALL (setresgid, 3, rgid, egid, sgid); } +libc_hidden_def (__setresgid) #ifndef __setresgid weak_alias (__setresgid, setresgid) #endif diff --git a/sysdeps/unix/sysv/linux/setresuid.c b/sysdeps/unix/sysv/linux/setresuid.c index 962d944aa4..e7feeefce0 100644 --- a/sysdeps/unix/sysv/linux/setresuid.c +++ b/sysdeps/unix/sysv/linux/setresuid.c @@ -18,37 +18,15 @@ #include <errno.h> #include <unistd.h> -#include <sys/types.h> - -#include <sysdep.h> -#include <sys/syscall.h> - -#include <linux/posix_types.h> -#include "kernel-features.h" -#include <pthread-functions.h> +#include <setxid.h> int __setresuid (uid_t ruid, uid_t euid, uid_t suid) { - int result; - - result = INLINE_SYSCALL (setresuid, 3, ruid, euid, suid); - -#if defined HAVE_PTR__NPTL_SETXID && !defined SINGLE_THREAD - if (result == 0 && __libc_pthread_functions.ptr__nptl_setxid != NULL) - { - struct xid_command cmd; - cmd.syscall_no = __NR_setresuid; - cmd.id[0] = ruid; - cmd.id[1] = euid; - cmd.id[2] = suid; - __libc_pthread_functions.ptr__nptl_setxid (&cmd); - } -#endif - - return result; + return INLINE_SETXID_SYSCALL (setresuid, 3, ruid, euid, suid); } +libc_hidden_def (__setresuid) #ifndef __setresuid weak_alias (__setresuid, setresuid) #endif diff --git a/sysdeps/unix/sysv/linux/setreuid.c b/sysdeps/unix/sysv/linux/setreuid.c index c9d841eca0..ce30d3c696 100644 --- a/sysdeps/unix/sysv/linux/setreuid.c +++ b/sysdeps/unix/sysv/linux/setreuid.c @@ -18,35 +18,13 @@ #include <errno.h> #include <unistd.h> -#include <sys/types.h> - -#include <sysdep.h> -#include <sys/syscall.h> - -#include <linux/posix_types.h> -#include "kernel-features.h" -#include <pthread-functions.h> +#include <setxid.h> int __setreuid (uid_t ruid, uid_t euid) { - int result; - - result = INLINE_SYSCALL (setreuid, 2, ruid, euid); - -#if defined HAVE_PTR__NPTL_SETXID && !defined SINGLE_THREAD - if (result == 0 && __libc_pthread_functions.ptr__nptl_setxid != NULL) - { - struct xid_command cmd; - cmd.syscall_no = __NR_setreuid; - cmd.id[0] = ruid; - cmd.id[1] = euid; - __libc_pthread_functions.ptr__nptl_setxid (&cmd); - } -#endif - - return result; + return INLINE_SETXID_SYSCALL (setreuid, 2, ruid, euid); } #ifndef __setreuid weak_alias (__setreuid, setreuid) diff --git a/sysdeps/unix/sysv/linux/setuid.c b/sysdeps/unix/sysv/linux/setuid.c index 84f35176a1..a523dfdbd2 100644 --- a/sysdeps/unix/sysv/linux/setuid.c +++ b/sysdeps/unix/sysv/linux/setuid.c @@ -18,34 +18,12 @@ #include <errno.h> #include <unistd.h> -#include <sys/types.h> - -#include <sysdep.h> -#include <sys/syscall.h> - -#include <linux/posix_types.h> -#include "kernel-features.h" -#include <pthread-functions.h> - +#include <setxid.h> int __setuid (uid_t uid) { - int result; - - result = INLINE_SYSCALL (setuid, 1, uid); - -#if defined HAVE_PTR__NPTL_SETXID && !defined SINGLE_THREAD - if (result == 0 && __libc_pthread_functions.ptr__nptl_setxid != NULL) - { - struct xid_command cmd; - cmd.syscall_no = __NR_setuid; - cmd.id[0] = uid; - __libc_pthread_functions.ptr__nptl_setxid (&cmd); - } -#endif - - return result; + return INLINE_SETXID_SYSCALL (setuid, 1, uid); } #ifndef __setuid weak_alias (__setuid, setuid) diff --git a/sysdeps/unix/sysv/linux/syscalls.list b/sysdeps/unix/sysv/linux/syscalls.list index d7c8b443c4..a97305e822 100644 --- a/sysdeps/unix/sysv/linux/syscalls.list +++ b/sysdeps/unix/sysv/linux/syscalls.list @@ -66,8 +66,6 @@ sendfile64 - sendfile64 i:iipi sendfile64 setfsgid EXTRA setfsgid i:i setfsgid setfsuid EXTRA setfsuid i:i setfsuid setpgid - setpgid i:ii __setpgid setpgid -setresuid - setresuid i:iii __setresuid setresuid -setresgid - setresgid i:iii __setresgid setresgid sigaltstack - sigaltstack i:PP __sigaltstack sigaltstack sysinfo EXTRA sysinfo i:p sysinfo swapon - swapon i:si __swapon swapon diff --git a/time/difftime.c b/time/difftime.c index 228090c057..ad896e207d 100644 --- a/time/difftime.c +++ b/time/difftime.c @@ -16,52 +16,107 @@ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ +/* Written by Paul Eggert <eggert@cs.ucla.edu>. */ + #include <time.h> -#include <values.h> +#include <limits.h> +#include <float.h> +#include <stdint.h> + +#define TYPE_BITS(type) (sizeof (type) * CHAR_BIT) +#define TYPE_FLOATING(type) ((type) 0.5 == 0.5) +#define TYPE_SIGNED(type) ((type) -1 < 0) + +/* Return the difference between TIME1 and TIME0, where TIME0 <= TIME1. + time_t is known to be an integer type. */ + +static double +subtract (time_t time1, time_t time0) +{ + if (! TYPE_SIGNED (time_t)) + return time1 - time0; + else + { + /* Optimize the common special cases where time_t + can be converted to uintmax_t without losing information. */ + uintmax_t dt = (uintmax_t) time1 - (uintmax_t) time0; + double delta = dt; + + if (UINTMAX_MAX / 2 < INTMAX_MAX) + { + /* This is a rare host where uintmax_t has padding bits, and possibly + information was lost when converting time_t to uintmax_t. + Check for overflow by comparing dt/2 to (time1/2 - time0/2). + Overflow occurred if they differ by more than a small slop. + Thanks to Clive D.W. Feather for detailed technical advice about + hosts with padding bits. + + In the following code the "h" prefix means half. By range + analysis, we have: + + -0.5 <= ht1 - 0.5*time1 <= 0.5 + -0.5 <= ht0 - 0.5*time0 <= 0.5 + -1.0 <= dht - 0.5*(time1 - time0) <= 1.0 + + If overflow has not occurred, we also have: + + -0.5 <= hdt - 0.5*(time1 - time0) <= 0 + -1.0 <= dht - hdt <= 1.5 + + and since dht - hdt is an integer, we also have: + + -1 <= dht - hdt <= 1 + + or equivalently: + + 0 <= dht - hdt + 1 <= 2 + + In the above analysis, all the operators have their exact + mathematical semantics, not C semantics. However, dht - hdt + + 1 is unsigned in C, so it need not be compared to zero. */ + + uintmax_t hdt = dt / 2; + time_t ht1 = time1 / 2; + time_t ht0 = time0 / 2; + time_t dht = ht1 - ht0; + + if (2 < dht - hdt + 1) + { + /* Repair delta overflow. + + The following expression contains a second rounding, + so the result may not be the closest to the true answer. + This problem occurs only with very large differences. + It's too painful to fix this portably. */ + + delta = dt + 2.0L * (UINTMAX_MAX - UINTMAX_MAX / 2); + } + } + + return delta; + } +} /* Return the difference between TIME1 and TIME0. */ double -__difftime (time1, time0) - time_t time1; - time_t time0; +__difftime (time_t time1, time_t time0) { - /* Algorithm courtesy Paul Eggert (eggert@twinsun.com). */ - - time_t delta, hibit; + /* Convert to double and then subtract if no double-rounding error could + result. */ - if (sizeof (time_t) < sizeof (double)) + if (TYPE_BITS (time_t) <= DBL_MANT_DIG + || (TYPE_FLOATING (time_t) && sizeof (time_t) < sizeof (long double))) return (double) time1 - (double) time0; - if (sizeof (time_t) < sizeof (long double)) + + /* Likewise for long double. */ + + if (TYPE_BITS (time_t) <= LDBL_MANT_DIG || TYPE_FLOATING (time_t)) return (long double) time1 - (long double) time0; - if (time1 < time0) - return - __difftime (time0, time1); - - /* As much as possible, avoid loss of precision by computing the - difference before converting to double. */ - delta = time1 - time0; - if (delta >= 0) - return delta; - - /* Repair delta overflow. */ - hibit = (~ (time_t) 0) << (_TYPEBITS (time_t) - 1); - - /* The following expression rounds twice, which means the result may not - be the closest to the true answer. For example, suppose time_t is - 64-bit signed int, long_double is IEEE 754 double with default - rounding, time1 = 9223372036854775807 and time0 = -1536. Then the - true difference is 9223372036854777343, which rounds to - 9223372036854777856 with a total error of 513. But delta overflows to - -9223372036854774273, which rounds to -9223372036854774784, and - correcting this by subtracting 2 * (long_double) hibit (i.e. by adding - 2**64 = 18446744073709551616) yields 9223372036854776832, which rounds - to 9223372036854775808 with a total error of 1535 instead. This - problem occurs only with very large differences. It's too painful to - fix this portably. We are not alone in this problem; many C compilers - round twice when converting large unsigned types to small floating - types, so if time_t is unsigned the "return delta" above has the same - double-rounding problem. */ - return delta - 2 * (long double) hibit; + /* Subtract the smaller integer from the larger, convert the difference to + double, and then negate if needed. */ + + return time1 < time0 ? - subtract (time0, time1) : subtract (time1, time0); } strong_alias (__difftime, difftime) diff --git a/time/mktime.c b/time/mktime.c index 72b20128a3..280f5f47d5 100644 --- a/time/mktime.c +++ b/time/mktime.c @@ -46,6 +46,21 @@ # define mktime my_mktime #endif /* DEBUG */ +/* Shift A right by B bits portably, by dividing A by 2**B and + truncating towards minus infinity. A and B should be free of side + effects, and B should be in the range 0 <= B <= INT_BITS - 2, where + INT_BITS is the number of useful bits in an int. GNU code can + assume that INT_BITS is at least 32. + + ISO C99 says that A >> B is implementation-defined if A < 0. Some + implementations (e.g., UNICOS 9.0 on a Cray Y-MP EL) don't shift + right in the usual way when A < 0, so SHR falls back on division if + ordinary A >> B doesn't seem to be the usual signed shift. */ +#define SHR(a, b) \ + (-1 >> 1 == -1 \ + ? (a) >> (b) \ + : (a) / (1 << (b)) - ((a) % (1 << (b)) < 0)) + /* The extra casts work around common compiler bugs. */ #define TYPE_SIGNED(t) (! ((t) 0 < (t) -1)) /* The outer cast is needed to work around a bug in Cray C 5.0.3.0. @@ -60,14 +75,13 @@ #ifndef TIME_T_MAX # define TIME_T_MAX TYPE_MAXIMUM (time_t) #endif -#define TIME_T_MIDPOINT (((TIME_T_MIN + TIME_T_MAX) >> 1) + 1) +#define TIME_T_MIDPOINT (SHR (TIME_T_MIN + TIME_T_MAX, 1) + 1) /* Verify a requirement at compile-time (unlike assert, which is runtime). */ #define verify(name, assertion) struct name { char a[(assertion) ? 1 : -1]; } verify (time_t_is_integer, (time_t) 0.5 == 0); verify (twos_complement_arithmetic, -1 == ~1 + 1); -verify (right_shift_propagates_sign, -1 >> 1 == -1); /* The code also assumes that signed integer overflow silently wraps around, but this assumption can't be stated without causing a diagnostic on some hosts. */ @@ -133,12 +147,12 @@ ydhms_diff (long int year1, long int yday1, int hour1, int min1, int sec1, /* Compute intervening leap days correctly even if year is negative. Take care to avoid integer overflow here. */ - int a4 = (year1 >> 2) + (TM_YEAR_BASE >> 2) - ! (year1 & 3); - int b4 = (year0 >> 2) + (TM_YEAR_BASE >> 2) - ! (year0 & 3); + int a4 = SHR (year1, 2) + SHR (TM_YEAR_BASE, 2) - ! (year1 & 3); + int b4 = SHR (year0, 2) + SHR (TM_YEAR_BASE, 2) - ! (year0 & 3); int a100 = a4 / 25 - (a4 % 25 < 0); int b100 = b4 / 25 - (b4 % 25 < 0); - int a400 = a100 >> 2; - int b400 = b100 >> 2; + int a400 = SHR (a100, 2); + int b400 = SHR (b100, 2); int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400); /* Compute the desired time in time_t precision. Overflow might @@ -322,14 +336,16 @@ __mktime_internal (struct tm *tp, int LOG2_YEARS_PER_BIENNIUM = 1; int approx_requested_biennia = - ((year_requested >> LOG2_YEARS_PER_BIENNIUM) - - ((EPOCH_YEAR - TM_YEAR_BASE) >> LOG2_YEARS_PER_BIENNIUM) - + (mday >> ALOG2_DAYS_PER_BIENNIUM) - + (hour >> ALOG2_HOURS_PER_BIENNIUM) - + (min >> ALOG2_MINUTES_PER_BIENNIUM) - + (LEAP_SECONDS_POSSIBLE ? 0 : sec >> ALOG2_SECONDS_PER_BIENNIUM)); - - int approx_biennia = t0 >> ALOG2_SECONDS_PER_BIENNIUM; + (SHR (year_requested, LOG2_YEARS_PER_BIENNIUM) + - SHR (EPOCH_YEAR - TM_YEAR_BASE, LOG2_YEARS_PER_BIENNIUM) + + SHR (mday, ALOG2_DAYS_PER_BIENNIUM) + + SHR (hour, ALOG2_HOURS_PER_BIENNIUM) + + SHR (min, ALOG2_MINUTES_PER_BIENNIUM) + + (LEAP_SECONDS_POSSIBLE + ? 0 + : SHR (sec, ALOG2_SECONDS_PER_BIENNIUM))); + + int approx_biennia = SHR (t0, ALOG2_SECONDS_PER_BIENNIUM); int diff = approx_biennia - approx_requested_biennia; int abs_diff = diff < 0 ? - diff : diff; @@ -347,7 +363,7 @@ __mktime_internal (struct tm *tp, /* Overflow occurred. Try repairing it; this might work if the time zone offset is enough to undo the overflow. */ time_t repaired_t0 = -1 - t0; - approx_biennia = repaired_t0 >> ALOG2_SECONDS_PER_BIENNIUM; + approx_biennia = SHR (repaired_t0, ALOG2_SECONDS_PER_BIENNIUM); diff = approx_biennia - approx_requested_biennia; abs_diff = diff < 0 ? - diff : diff; if (overflow_threshold < abs_diff) |