diff options
43 files changed, 1054 insertions, 419 deletions
diff --git a/ChangeLog b/ChangeLog index 0bbe073a7a..bf062849e9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,12 +1,138 @@ -2004-11-02 Jakub Jelinek <jakub@redhat.com> +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_getai.c: Use map from nscd_gethost.c. + * nscd/nscd_initgroups.c: Use map from nscd_getgr.c. + + * nscd/nscd_getai.c: Add some checks to detect corrupt databases. + * nscd/nscd_getgr_r.c: Likewise + * nscd/nscd_gethst_r.c: Likewise. + * nscd/nscd_getpw_r.c: Likewise - * include/features.h (__USE_FORTIFY_LEVEL): Also set for Red Hat - GCC 3.4.x-RH >= 3.4.2-8. - * libio/bits/features.h (printf, fprintf, vprintf, vfprintf): For - GCC 3.4.x-RH use __builtin___{,v}{,f}printf_chk instead of - __{,v}{,f}printf_chk. - * debug/tst-chk1.c (do_test): Deal with GCC 3.4.x-RH not - being able to recognize subobjects. +2004-11-09 Jakub Jelinek <jakub@redhat.com> + + * posix/regcomp.c (calc_eclosure_iter): Don't access + dfa->edests[node].elems[0] if dfa->edests[node].nelem == 0. + * posix/rxspencer/tests: Add 5 new tests. + +2004-11-09 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/ifaddrs.c: Determine sin6_scope_id field + value correctly. Patch by Mitsuru Kanda <mk@karaba.org>. + +2004-11-04 Jakub Jelinek <jakub@redhat.com> + + * libio/fileops.c (_IO_new_file_seekoff): If mode is 0 and + fp->_offset == _IO_pos_BAD, just call _IO_SYSSEEK (fp, 0, dir) + and if successful set fp->_offset. + * libio/Makefile (tests): Add bug-ungetc3. + * libio/bug-ungetc3.c: New test. + +2004-11-03 Marcus Brinkmann <marcus@gnu.org> + + * sysdeps/gnu/_G_config.h (_G_HAVE_MREMAP): Define symbol. + * sysdeps/mach/hurd/_G_config.h: New file. + * libio/fileops.c (mmap_remap_check) [__linux__]: Replaced with + [_G_HAVE_MREMAP]. + +2004-11-08 Ulrich Drepper <drepper@redhat.com> + + * posix/regcomp.c (utf8_sb_map): Define. + (free_dfa_content): Don't free dfa->sb_char if it's a pointer to + utf8_sb_map. + (init_dfa): Use utf8_sb_map instead of initializing memory when the + encoding is UTF-8. + +2004-11-03 Paolo Bonzini <bonzini@gnu.org> + + * posix/regcomp.c (init_dfa): Get the codeset name outside glibc as + well. Check if it is spelled UTF8 as well as UTF-8, and check + case-insensitively. Set dfa->map_notascii manually when outside + glibc. + * posix/regex_internal.c (build_wcs_upper_buffer) [!_LIBC]: Enable + optimizations based on map_notascii. + * posix/regex_internal.h [HAVE_LANGINFO_H || HAVE_LANGINFO_CODESET + || _LIBC]: Include langinfo.h. + + * posix/regex_internal.h (struct re_backref_cache_entry): Add "more" + field. + * posix/regexec.c (check_dst_limits): Hoist computation of the source + and destination bkref_idx out of the loop. Pass it to + check_dst_limits_calc_pos. + (check_dst_limits_calc_pos_1): New function, containing the recursive + loop of check_dst_limits_calc_pos; uses the "more" field of + struct re_backref_cache to control the loop. + (check_dst_limits_calc_pos): Store into "boundaries" the position + relative to lim's start and end positions. Do not accept eclosures, + accept bkref_idx instead. Call check_dst_limits_calc_pos_1 to do the + work. + (sift_states_bkref): Use the "more" field of struct re_backref_cache + to control the loop. A big "if" was turned into a continue and the + function was reindented. + (get_subexp): Use the "more" field of struct re_backref_cache + to control the loop. + (match_ctx_add_entry): Initialize the bkref_ents' "more" field. + (search_cur_bkref_entry): Return -1 if out of bounds. + + * posix/regexec.c (empty_set): Remove. + (sift_states_backward): Remove cur_src variable. Move inner loop + to build_sifted_states. + (build_sifted_states): Extract from sift_states_backward. Do not + use empty_set. + (update_cur_sifted_state): Do not use empty_set. Special case + dest_nodes->nelem == 0. + + * posix/regex_internal.h (struct re_backref_cache_entry): Remove flag + field. + (struct re_sift_context_t): Remove cur_bkref, cls_subexp_idx, + check_subexp fields. Move limits last. + * posix/regexec.c (match_ctx_clear_flag): Remove. + (sift_ctx_init): Remove check_subexp parameter. Do not set removed + fields. Callers adjusted. + (expand_bkref_cache): Remove last_str parameter. Callers adjusted. + (re_search_internal): Remove fast_translate variable. + (update_cur_sifted_state): Pass candidates as the final parameter + to sift_states_bkref. + (sift_states_bkref): Change last unused parameter to be "candidates", + do not fetch candidates into a local variable. + Remove dead test for "node == sctx->bkref", and the cur_bkref_idx + variable. + Remove loops that set/reset the flag field of backref cache entries. + (check_arrival_add_next_nodes): Use a signed int to hold the return + value of re_node_set_insert. + (group_nodes_into_DFAstates): Likewise. + (match_ctx_add_entry): Do not set the flag field of the new entry. + +2004-11-05 Roland McGrath <roland@redhat.com> + + * sysdeps/generic/ldsodefs.h (struct rtld_global_ro): Define + _dl_sysinfo_dso under [NEED_DL_SYSINFO_DSO] as well. + * elf/rtld.c (dl_main): Set up GLRO(dl_sysinfo_dso) under + [NEED_DL_SYSINFO_DSO] as well. + * sysdeps/generic/dl-sysdep.c (_dl_show_auxv): Always include + AT_SYSINFO and AT_SYSINFO_EHDR in name table. + (_dl_sysdep_start) [NEED_DL_SYSINFO_DSO]: Match AT_SYSINFO_EHDR. + * elf/dl-support.c (_dl_sysinfo_dso): Define also under + [NEED_DL_SYSINFO_DSO]. + (_dl_aux_init) [NEED_DL_SYSINFO || NEED_DL_SYSINFO_DSO]: + Match AT_SYSINFO_EHDR and set GL(dl_sysinfo_dso). + +2004-11-05 Roland McGrath <roland@redhat.com> + + * manual/errno.texi (Error Codes): Revert last change for now. + * sysdeps/gnu/errlist.c: Regenerated. + +2004-11-04 Roland McGrath <roland@frob.com> + + * Makeconfig (link-libc, rpath-dirs): Remove AIX cruft definitions. + (LDFLAGS-rpath-ORIGIN, LDFLAGS-soname-fname): Likewise. + (LDFLAGS-rdynamic, LDFLAGS-Bsymbolic): Likewise. + ($(common-objpfx)gnu/lib-names.stmp): Likewise. 2004-11-01 Jakub Jelinek <jakub@redhat.com> @@ -24,6 +150,54 @@ * sysdeps/x86_64/fpu/bits/fenv.h: Include bits/wordsize.h. (fenv_t): Remove __mxcsr field for -m32. +2004-11-04 Jakub Jelinek <jakub@redhat.com> + + * libio/ftello.c (ftello): Don't subtract save_end - save_base + if pos is _IO_pos_BAD. + * libio/ftello64.c (ftello64): Likewise. + * libio/iofgetpos.c (_IO_new_fgetpos): Likewise. + * libio/iofgetpos64.c (_IO_new_fgetpos64): Likewise. + * libio/oldiofgetpos.c (_IO_old_fgetpos): Likewise. + * libio/oldiofgetpos64.c (_IO_old_fgetpos64): Likewise. + * libio/ioftell.c (_IO_ftell): Likewise. + Cast to long int instead of off_t when checking for overflow. + +2004-11-04 Richard Henderson <rth@redhat.com> + + * sysdeps/unix/sysv/linux/alpha/register-dump.h (regnames): Align. + (linefeed): Remove. + (register_dump): Rewrite to generate into a flat buffer instead + of into iovecs. + +2004-11-02 Jakub Jelinek <jakub@redhat.com> + + * debug/tst-chk1.c (ret): New volatile variable. + (CHK_FAIL_END): Remove redundant ret setting. + (do_test): Remote ret variable. + +2004-01-03 Paolo Bonzini <bonzini@gnu.org> + + * posix/regex_internal.h (__regfree) [!_LIBC]: Define to regfree. + +2004-11-03 Marcus Brinkmann <marcus@gnu.org> + + * sysdeps/generic/utime.c: Include <stddef.h>. + + * sysdeps/generic/sysconf.c: Include <grp.h> and <pwd.h>. + + * sysdeps/generic/tempname.c (__path_search): Add missing argument + TRY_TMPDIR. + +2004-11-02 Jakub Jelinek <jakub@redhat.com> + + * include/features.h (__USE_FORTIFY_LEVEL): Also set for Red Hat + GCC 3.4.x-RH >= 3.4.2-8. + * libio/bits/features.h (printf, fprintf, vprintf, vfprintf): For + GCC 3.4.x-RH use __builtin___{,v}{,f}printf_chk instead of + __{,v}{,f}printf_chk. + * debug/tst-chk1.c (do_test): Deal with GCC 3.4.x-RH not + being able to recognize subobjects. + 2004-10-31 Mariusz Mazur <mmazur@kernel.pl> * sysdeps/unix/sysv/linux/alpha/setregid.c: New file. diff --git a/Makeconfig b/Makeconfig index ea3a782cda..dc70aa68c4 100644 --- a/Makeconfig +++ b/Makeconfig @@ -452,12 +452,6 @@ link-libc = -Wl,-rpath-link=$(rpath-link) \ $(common-objpfx)$(patsubst %,$(libtype.oS),c) $(gnulib) # This is how to find at build-time things that will be installed there. rpath-dirs = math elf dlfcn nss nis rt resolv crypt -else -ifneq (,$(filter aix aix%,$(config-os))) -link-libc = $(common-objpfx)libc.a \ - $(common-objpfx)$(patsubst %,$(libtype.oS),c) $(gnulib) -rpath-dirs = math dlfcn nss nis rt resolv crypt -endif endif rpath-link = \ $(common-objdir):$(subst $(empty) ,:,$(patsubst ../$(subdir),.,$(rpath-dirs:%=$(common-objpfx)%))) @@ -475,13 +469,6 @@ LDFLAGS-rpath-ORIGIN = -Wl,-rpath,'$$ORIGIN' LDFLAGS-soname-fname = -Wl,-soname,$(@F) LDFLAGS-rdynamic = -rdynamic LDFLAGS-Bsymbolic = -Bsymbolic -else -ifneq (,$(filter aix aix%,$(config-os))) -LDFLAGS-rpath-ORIGIN = -LDFLAGS-soname-fname = -LDFLAGS-rdynamic = -Wl,-bdynamic -LDFLAGS-Bsymbolic = -Wl,-bsymbolic -endif endif # Choose the default search path for the dynamic linker based on @@ -835,13 +822,6 @@ postclean-generated += soversions.mk soversions.i \ before-compile += $(common-objpfx)gnu/lib-names.h ifeq ($(soversions.mk-done),t) $(common-objpfx)gnu/lib-names.h: $(common-objpfx)gnu/lib-names.stmp; @: -ifneq (,$(findstring aix,$(config-os))) -$(common-objpfx)gnu/lib-names.stmp: $(..)sysdeps/unix/sysv/aix/gnu/lib-names.h - $(make-target-directory) - @rm -f ${@:stmp=T} $@ - @cp $(..)sysdeps/unix/sysv/aix/gnu/lib-names.h $(common-objpfx)gnu - touch $@ -else $(common-objpfx)gnu/lib-names.stmp: $(common-objpfx)soversions.mk $(make-target-directory) @rm -f ${@:stmp=T} $@ @@ -870,7 +850,6 @@ $(common-objpfx)gnu/lib-names.stmp: $(common-objpfx)soversions.mk $(move-if-change) ${@:stmp=T} ${@:stmp=h} touch $@ endif -endif common-generated += gnu/lib-names.h gnu/lib-names.stmp diff --git a/debug/tst-chk1.c b/debug/tst-chk1.c index 27b4f15346..9c9f82a3af 100644 --- a/debug/tst-chk1.c +++ b/debug/tst-chk1.c @@ -51,6 +51,7 @@ do_prepare (void) } volatile int chk_fail_ok; +volatile int ret; jmp_buf chk_fail_buf; static void @@ -86,7 +87,6 @@ int num2 = 987654; #define CHK_FAIL_END \ chk_fail_ok = 0; \ FAIL (); \ - ret = 1; \ } #if __USE_FORTIFY_LEVEL >= 2 #define CHK_FAIL2_START CHK_FAIL_START @@ -99,7 +99,6 @@ int num2 = 987654; static int do_test (void) { - int ret = 0; struct sigaction sa; sa.sa_handler = handler; sa.sa_flags = 0; diff --git a/elf/dl-support.c b/elf/dl-support.c index 88378a60a6..cfe01babbf 100644 --- a/elf/dl-support.c +++ b/elf/dl-support.c @@ -136,6 +136,8 @@ int (*_dl_make_stack_executable_hook) (void **) internal_function #ifdef NEED_DL_SYSINFO /* Needed for improved syscall handling on at least x86/Linux. */ uintptr_t _dl_sysinfo = DL_SYSINFO_DEFAULT; +#endif +#if defined NEED_DL_SYSINFO || defined NEED_DL_SYSINFO_DSO /* Address of the ELF headers in the vsyscall page. */ const ElfW(Ehdr) *_dl_sysinfo_dso; #endif @@ -184,6 +186,11 @@ _dl_aux_init (ElfW(auxv_t) *av) GL(dl_sysinfo) = av->a_un.a_val; break; #endif +#if defined NEED_DL_SYSINFO || defined NEED_DL_SYSINFO_DSO + case AT_SYSINFO_EHDR: + GL(dl_sysinfo_dso) = av->a_un.a_ptr; + break; +#endif case AT_UID: uid ^= av->a_un.a_val; seen |= 1; diff --git a/elf/rtld.c b/elf/rtld.c index 4adbb437bf..e53273c2bb 100644 --- a/elf/rtld.c +++ b/elf/rtld.c @@ -1382,7 +1382,7 @@ ERROR: ld.so: object '%s' from %s cannot be preloaded: ignored.\n", assert (i == npreloads); } -#ifdef NEED_DL_SYSINFO +#if defined NEED_DL_SYSINFO || defined NEED_DL_SYSINFO_DSO struct link_map *sysinfo_map = NULL; if (GLRO(dl_sysinfo_dso) != NULL) { @@ -1446,9 +1446,11 @@ ERROR: ld.so: object '%s' from %s cannot be preloaded: ignored.\n", } /* We have a prelinked DSO preloaded by the system. */ + sysinfo_map = l; +# ifdef NEED_DL_SYSINFO if (GLRO(dl_sysinfo) == DL_SYSINFO_DEFAULT) GLRO(dl_sysinfo) = GLRO(dl_sysinfo_dso)->e_entry + l->l_addr; - sysinfo_map = l; +# endif } } #endif @@ -1497,7 +1499,7 @@ ERROR: ld.so: object '%s' from %s cannot be preloaded: ignored.\n", GL(dl_rtld_map).l_next = (i + 1 < main_map->l_searchlist.r_nlist ? main_map->l_searchlist.r_list[i + 1] : NULL); -#ifdef NEED_DL_SYSINFO +#if defined NEED_DL_SYSINFO || defined NEED_DL_SYSINFO_DSO if (sysinfo_map != NULL && GL(dl_rtld_map).l_prev->l_next == sysinfo_map && GL(dl_rtld_map).l_next != sysinfo_map) diff --git a/fedora/branch.mk b/fedora/branch.mk index 2483250036..b07840623e 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-02 11:53 UTC -fedora-sync-tag := fedora-glibc-20041102T1153 +fedora-sync-date := 2004-11-10 08:39 UTC +fedora-sync-tag := fedora-glibc-20041110T0839 diff --git a/fedora/glibc.spec.in b/fedora/glibc.spec.in index 7dfa25a4f9..735419c94a 100644 --- a/fedora/glibc.spec.in +++ b/fedora/glibc.spec.in @@ -1,4 +1,4 @@ -%define glibcrelease 75 +%define glibcrelease 76 %define auxarches i586 i686 athlon sparcv9 alphaev6 %define prelinkarches noarch %define nptlarches i386 i686 athlon x86_64 ia64 s390 s390x sparcv9 ppc ppc64 @@ -1256,9 +1256,17 @@ rm -f *.filelist* %endif %changelog +* Wed Nov 10 2004 Jakub Jelinek <jakub@redhat.com> 2.3.3-76 +- update from CVS + - fix regcomp crash (#138439) + - fix ftell{,o,o64} (#137885) + - robustification of nscd to cope with corrupt databases (#137140) + - fix NPTL with pthread_exit immediately after pthread_create (BZ #530) + - some regex optimizations + * Tue Nov 2 2004 Jakub Jelinek <jakub@redhat.com> 2.3.3-75 - update from CVS - - mktime cleanups (BZ #487, #473, + - mktime cleanups (BZ #487, #473) - unique comments in free(3) check error messages - adjust some x86_64 headers for -m32 (#129712) - object size checking support even with GCC-3.4.2-RH >= 3.4.2-8 diff --git a/libio/Makefile b/libio/Makefile index a9384b55a9..1d7611d252 100644 --- a/libio/Makefile +++ b/libio/Makefile @@ -54,7 +54,7 @@ tests = tst_swprintf tst_wprintf tst_swscanf tst_wscanf tst_getwc tst_putwc \ tst-freopen bug-rewind bug-rewind2 bug-ungetc bug-fseek \ tst-mmap-eofsync tst-mmap-fflushsync bug-mmap-fflush \ tst-mmap2-eofsync tst-mmap-offend bug-fopena+ bug-wfflush \ - bug-ungetc2 bug-ftell + bug-ungetc2 bug-ftell bug-ungetc3 test-srcs = test-freopen all: # Make this the default target; it will be defined in Rules. diff --git a/libio/bug-ungetc3.c b/libio/bug-ungetc3.c new file mode 100644 index 0000000000..0c83c1161e --- /dev/null +++ b/libio/bug-ungetc3.c @@ -0,0 +1,94 @@ +/* Test program for ungetc/ftell interaction bug. */ + +#include <stdio.h> + +static void do_prepare (void); +#define PREPARE(argc, argv) do_prepare () +static int do_test (void); +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" + +static const char pattern[] = "12345"; +static char *temp_file; + +static void +do_prepare (void) +{ + int fd = create_temp_file ("bug-ungetc.", &temp_file); + if (fd == -1) + { + printf ("cannot create temporary file: %m\n"); + exit (1); + } + write (fd, pattern, sizeof (pattern)); + close (fd); +} + +static int +do_one_test (int mode) +{ + FILE *f; + + f = fopen (temp_file, "r"); + if (f == NULL) + { + printf ("could not open temporary file: %m\n"); + return 1; + } + + if (mode == 1 && ftell (f) != 0) + { + printf ("first ftell returned wrong position %ld\n", ftell (f)); + return 1; + } + + if (fgetc (f) != '1' || fgetc (f) != '2') + { + puts ("fgetc failed"); + return 1; + } + + if (mode == 2 && ftell (f) != 2) + { + printf ("second ftell returned wrong position %ld\n", ftell (f)); + return 1; + } + + if (ungetc ('6', f) != '6') + { + puts ("ungetc failed"); + return 1; + } + + if (ftell (f) != 1) + { + printf ("third ftell returned wrong position %ld\n", ftell (f)); + return 1; + } + + if (fgetc (f) != '6') + { + puts ("fgetc failed"); + return 1; + } + + if (ftell (f) != 2) + { + printf ("fourth ftell returned wrong position %ld\n", ftell (f)); + return 1; + } + + fclose (f); + + return 0; +} + +static int +do_test (void) +{ + int mode; + for (mode = 0; mode <= 2; mode++) + if (do_one_test (mode)) + return 1; + return 0; +} diff --git a/libio/fileops.c b/libio/fileops.c index 7d90cbaa2d..2d787d296f 100644 --- a/libio/fileops.c +++ b/libio/fileops.c @@ -635,7 +635,7 @@ mmap_remap_check (_IO_FILE *fp) { /* The file added some pages. We need to remap it. */ void *p; -#if defined __linux__ /* XXX */ +#ifdef _G_HAVE_MREMAP p = __mremap (fp->_IO_buf_base, ROUNDED (fp->_IO_buf_end - fp->_IO_buf_base), ROUNDED (st.st_size), MREMAP_MAYMOVE); @@ -989,7 +989,18 @@ _IO_new_file_seekoff (fp, offset, dir, mode) /* Adjust for read-ahead (bytes is buffer). */ offset -= fp->_IO_read_end - fp->_IO_read_ptr; if (fp->_offset == _IO_pos_BAD) - goto dumb; + { + if (mode != 0) + goto dumb; + else + { + result = _IO_SYSSEEK (fp, 0, dir); + if (result == EOF) + return result; + + fp->_offset = result; + } + } /* Make offset absolute, assuming current pointer is file_ptr(). */ offset += fp->_offset; if (offset < 0) diff --git a/libio/ftello.c b/libio/ftello.c index 4975a0bd73..e58daacad4 100644 --- a/libio/ftello.c +++ b/libio/ftello.c @@ -1,4 +1,5 @@ -/* Copyright (C) 1993, 1995-2001, 2002, 2003 Free Software Foundation, Inc. +/* Copyright (C) 1993, 1995-2001, 2002, 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 @@ -39,7 +40,7 @@ ftello (fp) CHECK_FILE (fp, -1L); _IO_acquire_lock (fp); pos = _IO_seekoff_unlocked (fp, 0, _IO_seek_cur, 0); - if (_IO_in_backup (fp)) + if (_IO_in_backup (fp) && pos != _IO_pos_BAD) { if (fp->_mode <= 0) pos -= fp->_IO_save_end - fp->_IO_save_base; diff --git a/libio/ftello64.c b/libio/ftello64.c index 0275c0ca35..d39fc2d1b2 100644 --- a/libio/ftello64.c +++ b/libio/ftello64.c @@ -1,4 +1,5 @@ -/* Copyright (C) 1993, 1995-2001, 2002, 2003 Free Software Foundation, Inc. +/* Copyright (C) 1993, 1995-2001, 2002, 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 @@ -40,7 +41,7 @@ ftello64 (fp) CHECK_FILE (fp, -1L); _IO_acquire_lock (fp); pos = _IO_seekoff_unlocked (fp, 0, _IO_seek_cur, 0); - if (_IO_in_backup (fp)) + if (_IO_in_backup (fp) && pos != _IO_pos_BAD) { if (fp->_mode <= 0) pos -= fp->_IO_save_end - fp->_IO_save_base; diff --git a/libio/iofgetpos.c b/libio/iofgetpos.c index aff39bbed4..8b7ef9f34d 100644 --- a/libio/iofgetpos.c +++ b/libio/iofgetpos.c @@ -1,4 +1,5 @@ -/* Copyright (C) 1993, 1995-2001, 2002, 2003 Free Software Foundation, Inc. +/* Copyright (C) 1993, 1995-2001, 2002, 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 @@ -40,7 +41,7 @@ _IO_new_fgetpos (fp, posp) CHECK_FILE (fp, EOF); _IO_acquire_lock (fp); pos = _IO_seekoff_unlocked (fp, 0, _IO_seek_cur, 0); - if (_IO_in_backup (fp)) + if (_IO_in_backup (fp) && pos != _IO_pos_BAD) { if (fp->_mode <= 0) pos -= fp->_IO_save_end - fp->_IO_save_base; diff --git a/libio/iofgetpos64.c b/libio/iofgetpos64.c index be224ca103..10446857e7 100644 --- a/libio/iofgetpos64.c +++ b/libio/iofgetpos64.c @@ -1,4 +1,5 @@ -/* Copyright (C) 1993, 1995-2001, 2002, 2003 Free Software Foundation, Inc. +/* Copyright (C) 1993, 1995-2001, 2002, 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 @@ -41,7 +42,7 @@ _IO_new_fgetpos64 (fp, posp) CHECK_FILE (fp, EOF); _IO_acquire_lock (fp); pos = _IO_seekoff_unlocked (fp, 0, _IO_seek_cur, 0); - if (_IO_in_backup (fp)) + if (_IO_in_backup (fp) && pos != _IO_pos_BAD) { if (fp->_mode <= 0) pos -= fp->_IO_save_end - fp->_IO_save_base; diff --git a/libio/ioftell.c b/libio/ioftell.c index b991ef69ea..03e5f28404 100644 --- a/libio/ioftell.c +++ b/libio/ioftell.c @@ -1,4 +1,5 @@ -/* Copyright (C) 1993,1995-2000,2001,2002,2003 Free Software Foundation, Inc. +/* Copyright (C) 1993, 1995-2000, 2001, 2002, 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 @@ -38,7 +39,7 @@ _IO_ftell (fp) CHECK_FILE (fp, -1L); _IO_acquire_lock (fp); pos = _IO_seekoff_unlocked (fp, 0, _IO_seek_cur, 0); - if (_IO_in_backup (fp)) + if (_IO_in_backup (fp) && pos != _IO_pos_BAD) { if (_IO_vtable_offset (fp) != 0 || fp->_mode <= 0) pos -= fp->_IO_save_end - fp->_IO_save_base; @@ -52,7 +53,7 @@ _IO_ftell (fp) #endif return -1L; } - if ((_IO_off64_t) (off_t) pos != pos) + if ((_IO_off64_t) (long int) pos != pos) { #ifdef EOVERFLOW __set_errno (EOVERFLOW); diff --git a/libio/oldiofgetpos.c b/libio/oldiofgetpos.c index fbac21bdd4..6b14e1970f 100644 --- a/libio/oldiofgetpos.c +++ b/libio/oldiofgetpos.c @@ -42,7 +42,7 @@ _IO_old_fgetpos (fp, posp) CHECK_FILE (fp, EOF); _IO_acquire_lock (fp); pos = _IO_seekoff_unlocked (fp, 0, _IO_seek_cur, 0); - if (_IO_in_backup (fp)) + if (_IO_in_backup (fp) && pos != _IO_pos_BAD) pos -= fp->_IO_save_end - fp->_IO_save_base; _IO_release_lock (fp); if (pos == _IO_pos_BAD) diff --git a/libio/oldiofgetpos64.c b/libio/oldiofgetpos64.c index 996ad2075b..1c1adb3884 100644 --- a/libio/oldiofgetpos64.c +++ b/libio/oldiofgetpos64.c @@ -43,7 +43,7 @@ _IO_old_fgetpos64 (fp, posp) CHECK_FILE (fp, EOF); _IO_acquire_lock (fp); pos = _IO_seekoff_unlocked (fp, 0, _IO_seek_cur, 0); - if (_IO_in_backup (fp)) + if (_IO_in_backup (fp) && pos != _IO_pos_BAD) pos -= fp->_IO_save_end - fp->_IO_save_base; _IO_release_lock (fp); if (pos == _IO_pos_BAD) diff --git a/nptl/ChangeLog b/nptl/ChangeLog index 31be4c37bb..98df5cf228 100644 --- a/nptl/ChangeLog +++ b/nptl/ChangeLog @@ -1,3 +1,28 @@ +2004-11-10 Jakub Jelinek <jakub@redhat.com> + + * Makefile (tests): Add tst-exit3. + * tst-exit3.c: New test. + +2004-11-09 Ulrich Drepper <drepper@redhat.com> + + * Makefile (tests): Add tst-exit2. + * tst-exit2.c: New file. + +2004-11-09 Roland McGrath <roland@redhat.com> + + [BZ #530] + * sysdeps/pthread/createthread.c (do_clone): Increment __nptl_nthreads + here, before calling clone. + * pthread_create.c (start_thread): Don't do it here. + +2004-11-04 Roland McGrath <roland@redhat.com> + + * sysdeps/unix/sysv/linux/pthread_getcpuclockid.c: New file. + +2004-11-02 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/smp.h: Include <errno.h>. + 2004-10-29 Kaz Kojima <kkojima@rr.iij4u.or.jp> * sysdeps/unix/sysv/linux/sh/sem_timedwait.S (sem_timedwait): diff --git a/nptl/Makefile b/nptl/Makefile index f39e0bd303..564eaca6c5 100644 --- a/nptl/Makefile +++ b/nptl/Makefile @@ -227,7 +227,7 @@ tests = tst-attr1 tst-attr2 tst-attr3 \ tst-signal1 tst-signal2 tst-signal3 tst-signal4 tst-signal5 \ tst-signal6 \ tst-exec1 tst-exec2 tst-exec3 tst-exec4 \ - tst-exit1 \ + tst-exit1 tst-exit2 tst-exit3 \ tst-stdio1 tst-stdio2 \ tst-stack1 tst-stack2 tst-stack3 \ tst-unload \ diff --git a/nptl/pthread_create.c b/nptl/pthread_create.c index 7293f4c71c..82a3c683aa 100644 --- a/nptl/pthread_create.c +++ b/nptl/pthread_create.c @@ -222,9 +222,6 @@ __free_tcb (struct pthread *pd) static int start_thread (void *arg) { - /* One more thread. */ - atomic_increment (&__nptl_nthreads); - struct pthread *pd = (struct pthread *) arg; #if HP_TIMING_AVAIL diff --git a/nptl/sysdeps/pthread/createthread.c b/nptl/sysdeps/pthread/createthread.c index 8620519887..25a2703ae1 100644 --- a/nptl/sysdeps/pthread/createthread.c +++ b/nptl/sysdeps/pthread/createthread.c @@ -64,9 +64,21 @@ do_clone (struct pthread *pd, const struct pthread_attr *attr, until we tell it to. */ lll_lock (pd->lock); + /* One more thread. We cannot have the thread do this itself, since it + might exist but not have been scheduled yet by the time we've returned + and need to check the value to behave correctly. We must do it before + creating the thread, in case it does get scheduled first and then + might mistakenly think it was the only thread. In the failure case, + we momentarily store a false value; this doesn't matter because there + is no kosher thing a signal handler interrupting us right here can do + that cares whether the thread count is correct. */ + atomic_increment (&__nptl_nthreads); + if (ARCH_CLONE (fct, STACK_VARIABLES_ARGS, clone_flags, pd, &pd->tid, TLS_VALUE, &pd->tid) == -1) { + atomic_decrement (&__nptl_nthreads); /* Oops, we lied for a second. */ + /* Failed. If the thread is detached, remove the TCB here since the caller cannot do this. The caller remembered the thread as detached and cannot reverify that it is not since it must diff --git a/nptl/tst-exit2.c b/nptl/tst-exit2.c new file mode 100644 index 0000000000..3f5ff27b0f --- /dev/null +++ b/nptl/tst-exit2.c @@ -0,0 +1,40 @@ +#include <pthread.h> +#include <signal.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> + + +static void * +tf (void *arg) +{ + while (1) + sleep (100); + + /* NOTREACHED */ + return NULL; +} + + +static int +do_test (void) +{ + pthread_t th; + + int e = pthread_create (&th, NULL, tf, NULL); + if (e != 0) + { + printf ("create failed: %s\n", strerror (e)); + return 1; + } + + /* Terminate only this thread. */ + pthread_exit (NULL); + + /* NOTREACHED */ + return 1; +} + +#define EXPECTED_SIGNAL SIGALRM +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/nptl/tst-exit3.c b/nptl/tst-exit3.c new file mode 100644 index 0000000000..da92c82c0e --- /dev/null +++ b/nptl/tst-exit3.c @@ -0,0 +1,81 @@ +#include <pthread.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + + +static pthread_barrier_t b; + + +static void * +tf2 (void *arg) +{ + while (1) + sleep (100); + + /* NOTREACHED */ + return NULL; +} + + +static void * +tf (void *arg) +{ + pthread_t th; + + int e = pthread_barrier_wait (&b); + if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD) + { + puts ("barrier_wait failed"); + exit (1); + } + + e = pthread_create (&th, NULL, tf2, NULL); + if (e != 0) + { + printf ("create failed: %s\n", strerror (e)); + exit (1); + } + + /* Terminate only this thread. */ + return NULL; +} + + +static int +do_test (void) +{ + pthread_t th; + + if (pthread_barrier_init (&b, NULL, 2) != 0) + { + puts ("barrier_init failed"); + exit (1); + } + + int e = pthread_create (&th, NULL, tf, NULL); + if (e != 0) + { + printf ("create failed: %s\n", strerror (e)); + exit (1); + } + + e = pthread_barrier_wait (&b); + if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD) + { + puts ("barrier_wait failed"); + exit (1); + } + + /* Terminate only this thread. */ + pthread_exit (NULL); + + /* NOTREACHED */ + return 1; +} + +#define EXPECTED_SIGNAL SIGALRM +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/nscd/nscd-client.h b/nscd/nscd-client.h index 2e7f27b8d5..d49cb8136c 100644 --- a/nscd/nscd-client.h +++ b/nscd/nscd-client.h @@ -264,7 +264,7 @@ struct locked_map_ptr int lock; struct mapped_database *mapped; }; -#define libc_locked_map_ptr(name) static struct locked_map_ptr name +#define libc_locked_map_ptr(class, name) class struct locked_map_ptr name /* Open socket connection to nscd server. */ diff --git a/nscd/nscd_getai.c b/nscd/nscd_getai.c index a683976d87..f0b2082baa 100644 --- a/nscd/nscd_getai.c +++ b/nscd/nscd_getai.c @@ -33,15 +33,8 @@ extern int __nss_not_use_nscd_hosts; -libc_locked_map_ptr (map_handle); -/* Note that we only free the structure if necessary. The memory - mapping is not removed since it is not visible to the malloc - handling. */ -libc_freeres_fn (ai_map_free) -{ - if (map_handle.mapped != NO_MAPPING) - free (map_handle.mapped); -} +/* We use the mapping from nscd_gethst. */ +libc_locked_map_ptr (extern, __hst_map_handle); int @@ -53,7 +46,8 @@ __nscd_getai (const char *key, struct nscd_ai_result **result, int *h_errnop) /* If the mapping is available, try to search there instead of communicating with the nscd. */ struct mapped_database *mapped; - mapped = __nscd_get_map_ref (GETFDHST, "hosts", &map_handle, &gc_cycle); + mapped = __nscd_get_map_ref (GETFDHST, "hosts", &__hst_map_handle, + &gc_cycle); retry:; const ai_response_header *ai_resp = NULL; @@ -142,6 +136,12 @@ __nscd_getai (const char *key, struct nscd_ai_result **result, int *h_errnop) /* Copy the data in the block. */ memcpy (resultbuf + 1, respdata, datalen); + /* Try to detect corrupt databases. */ + if (resultbuf->canon != NULL + && resultbuf->canon[ai_resp->canonlen - 1] != '\0') + /* We cannot use the database. */ + goto out_close; + retval = 0; *result = resultbuf; } @@ -157,6 +157,7 @@ __nscd_getai (const char *key, struct nscd_ai_result **result, int *h_errnop) retval = 0; } + out_close: if (sock != -1) close_not_cancel_no_status (sock); out: diff --git a/nscd/nscd_getgr_r.c b/nscd/nscd_getgr_r.c index 1b94bf584f..282912db3e 100644 --- a/nscd/nscd_getgr_r.c +++ b/nscd/nscd_getgr_r.c @@ -67,14 +67,18 @@ __nscd_getgrgid_r (gid_t gid, struct group *resultbuf, char *buffer, } -libc_locked_map_ptr (map_handle); +libc_locked_map_ptr (,__gr_map_handle); /* Note that we only free the structure if necessary. The memory mapping is not removed since it is not visible to the malloc handling. */ libc_freeres_fn (gr_map_free) { - if (map_handle.mapped != NO_MAPPING) - free (map_handle.mapped); + if (__gr_map_handle.mapped != NO_MAPPING) + { + void *p = __gr_map_handle.mapped; + __gr_map_handle.mapped = NO_MAPPING; + free (p); + } } @@ -91,7 +95,8 @@ nscd_getgr_r (const char *key, size_t keylen, request_type type, /* If the mapping is available, try to search there instead of communicating with the nscd. */ struct mapped_database *mapped = __nscd_get_map_ref (GETFDGR, "group", - &map_handle, &gc_cycle); + &__gr_map_handle, + &gc_cycle); retry:; const gr_response_header *gr_resp = NULL; const char *gr_name = NULL; @@ -204,7 +209,8 @@ nscd_getgr_r (const char *key, size_t keylen, request_type type, else /* We already have the data. Just copy the group name and password. */ - memcpy (resultbuf->gr_name, gr_name, gr_name_len); + memcpy (resultbuf->gr_name, gr_name, + gr_resp->gr_name_len + gr_resp->gr_passwd_len); /* Clear the terminating entry. */ resultbuf->gr_mem[gr_resp->gr_mem_cnt] = NULL; @@ -242,6 +248,19 @@ nscd_getgr_r (const char *key, size_t keylen, request_type type, /* Copy the group member names. */ memcpy (resultbuf->gr_mem[0], gr_name + gr_name_len, total_len); + /* Try to detect corrupt databases. */ + if (resultbuf->gr_name[gr_name_len - 1] != '\0' + || resultbuf->gr_passwd[gr_resp->gr_passwd_len - 1] != '\0' + || ({for (cnt = 0; cnt < gr_resp->gr_mem_cnt; ++cnt) + if (resultbuf->gr_mem[cnt][len[cnt] - 1] != '\0') + break; + cnt < gr_resp->gr_mem_cnt; })) + { + /* We cannot use the database. */ + retval = -1; + goto out_close; + } + *result = resultbuf; } } diff --git a/nscd/nscd_gethst_r.c b/nscd/nscd_gethst_r.c index 407be1441f..5d9d569107 100644 --- a/nscd/nscd_gethst_r.c +++ b/nscd/nscd_gethst_r.c @@ -87,14 +87,18 @@ __nscd_gethostbyaddr_r (const void *addr, socklen_t len, int type, } -libc_locked_map_ptr (map_handle); +libc_locked_map_ptr (, __hst_map_handle); /* Note that we only free the structure if necessary. The memory mapping is not removed since it is not visible to the malloc handling. */ -libc_freeres_fn (gr_map_free) +libc_freeres_fn (hst_map_free) { - if (map_handle.mapped != NO_MAPPING) - free (map_handle.mapped); + if (__hst_map_handle.mapped != NO_MAPPING) + { + void *p = __hst_map_handle.mapped; + __hst_map_handle.mapped = NO_MAPPING; + free (p); + } } @@ -110,7 +114,8 @@ nscd_gethst_r (const char *key, size_t keylen, request_type type, /* If the mapping is available, try to search there instead of communicating with the nscd. */ struct mapped_database *mapped; - mapped = __nscd_get_map_ref (GETFDHST, "hosts", &map_handle, &gc_cycle); + mapped = __nscd_get_map_ref (GETFDHST, "hosts", &__hst_map_handle, + &gc_cycle); retry:; const hst_response_header *hst_resp = NULL; @@ -336,6 +341,16 @@ nscd_gethst_r (const char *key, size_t keylen, request_type type, memcpy (resultbuf->h_aliases[0], (const char *) addr_list + addr_list_len, total_len); + /* Try to detect corrupt databases. */ + if (resultbuf->h_name[hst_resp->h_name_len - 1] != '\0' + || ({for (cnt = 0; cnt < hst_resp->h_aliases_cnt; ++cnt) + if (resultbuf->h_aliases[cnt][aliases_len[cnt] - 1] + != '\0') + break; + cnt < hst_resp->h_aliases_cnt; })) + /* We cannot use the database. */ + goto out_close; + retval = 0; *result = resultbuf; } diff --git a/nscd/nscd_getpw_r.c b/nscd/nscd_getpw_r.c index b04dcfaa99..fe5fb43ca1 100644 --- a/nscd/nscd_getpw_r.c +++ b/nscd/nscd_getpw_r.c @@ -66,14 +66,18 @@ __nscd_getpwuid_r (uid_t uid, struct passwd *resultbuf, char *buffer, } -libc_locked_map_ptr (map_handle); +libc_locked_map_ptr (static, map_handle); /* Note that we only free the structure if necessary. The memory mapping is not removed since it is not visible to the malloc handling. */ -libc_freeres_fn (gr_map_free) +libc_freeres_fn (pw_map_free) { if (map_handle.mapped != NO_MAPPING) - free (map_handle.mapped); + { + void *p = map_handle.mapped; + map_handle.mapped = NO_MAPPING; + free (p); + } } @@ -184,6 +188,18 @@ nscd_getpw_r (const char *key, size_t keylen, request_type type, /* Copy the various strings. */ memcpy (resultbuf->pw_name, pw_name, total); + /* Try to detect corrupt databases. */ + if (resultbuf->pw_name[pw_resp->pw_name_len - 1] != '\0' + || resultbuf->pw_passwd[pw_resp->pw_passwd_len - 1] != '\0' + || resultbuf->pw_gecos[pw_resp->pw_gecos_len - 1] != '\0' + || resultbuf->pw_dir[pw_resp->pw_dir_len - 1] != '\0' + || resultbuf->pw_shell[pw_resp->pw_shell_len - 1] != '\0') + { + /* We cannot use the database. */ + retval = -1; + goto out_close; + } + *result = resultbuf; } } diff --git a/nscd/nscd_initgroups.c b/nscd/nscd_initgroups.c index ce44f654d7..2ea9e7f862 100644 --- a/nscd/nscd_initgroups.c +++ b/nscd/nscd_initgroups.c @@ -29,15 +29,8 @@ #include "nscd_proto.h" -libc_locked_map_ptr (map_handle); -/* Note that we only free the structure if necessary. The memory - mapping is not removed since it is not visible to the malloc - handling. */ -libc_freeres_fn (gr_map_free) -{ - if (map_handle.mapped != NO_MAPPING) - free (map_handle.mapped); -} +/* We use the same mapping as in nscd_getgr. */ +libc_locked_map_ptr (extern, __gr_map_handle); int @@ -50,7 +43,7 @@ __nscd_getgrouplist (const char *user, gid_t group, long int *size, /* If the mapping is available, try to search there instead of communicating with the nscd. */ struct mapped_database *mapped; - mapped = __nscd_get_map_ref (GETFDGR, "group", &map_handle, &gc_cycle); + mapped = __nscd_get_map_ref (GETFDGR, "group", &__gr_map_handle, &gc_cycle); retry:; const initgr_response_header *initgr_resp = NULL; diff --git a/posix/regcomp.c b/posix/regcomp.c index 9b435a885e..ba7a1cc5d4 100644 --- a/posix/regcomp.c +++ b/posix/regcomp.c @@ -566,6 +566,23 @@ weak_alias (__regerror, regerror) #endif +#ifdef RE_ENABLE_I18N +/* This static array is used for the map to single-byte characters when + UTF-8 is used. Otherwise we would allocate memory just to initialize + it the same all the time. UTF-8 is the preferred encoding so this is + a worthwhile optimization. */ +static const bitset utf8_sb_map = +{ + /* Set the first 128 bits. */ +# if UINT_MAX == 0xffffffff + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff +# else +# error "Add case for new unsigned int size" +# endif +}; +#endif + + static void free_dfa_content (re_dfa_t *dfa) { @@ -613,7 +630,8 @@ free_dfa_content (re_dfa_t *dfa) } re_free (dfa->state_table); #ifdef RE_ENABLE_I18N - re_free (dfa->sb_char); + if (dfa->sb_char != utf8_sb_map) + re_free (dfa->sb_char); #endif #ifdef DEBUG re_free (dfa->re_str); @@ -824,6 +842,9 @@ init_dfa (dfa, pat_len) int pat_len; { int table_size; +#ifndef _LIBC + char *codeset_name; +#endif memset (dfa, '\0', sizeof (re_dfa_t)); @@ -853,22 +874,59 @@ init_dfa (dfa, pat_len) dfa->is_utf8 = 1; dfa->map_notascii = (_NL_CURRENT_WORD (LC_CTYPE, _NL_CTYPE_MAP_TO_NONASCII) != 0); +#else +# ifdef HAVE_LANGINFO_CODESET + codeset_name = nl_langinfo (CODESET); +# else + codeset_name = getenv ("LC_ALL"); + if (codeset_name == NULL || codeset[0] == '\0') + codeset_name = getenv ("LC_CTYPE"); + if (codeset_name == NULL || codeset[0] == '\0') + codeset_name = getenv ("LANG"); + if (codeset_name == NULL) + codeset_name = ""; + else if (strchr (codeset_name, '.') != NULL) + codeset_name = strchr (codeset_name, '.') + 1; +# endif + + if (strcasecmp (codeset_name, "UTF-8") == 0 + || strcasecmp (codeset_name, "UTF8") == 0) + dfa->is_utf8 = 1; + + /* We check exhaustively in the loop below if this charset is a + superset of ASCII. */ + dfa->map_notascii = 0; #endif + #ifdef RE_ENABLE_I18N if (dfa->mb_cur_max > 1) { - int i, j, ch; - - dfa->sb_char = (re_bitset_ptr_t) calloc (sizeof (bitset), 1); - if (BE (dfa->sb_char == NULL, 0)) - return REG_ESPACE; if (dfa->is_utf8) - memset (dfa->sb_char, 255, sizeof (unsigned int) * BITSET_UINTS / 2); + dfa->sb_char = (re_bitset_ptr_t) utf8_sb_map; else - for (i = 0, ch = 0; i < BITSET_UINTS; ++i) - for (j = 0; j < UINT_BITS; ++j, ++ch) - if (__btowc (ch) != WEOF) - dfa->sb_char[i] |= 1 << j; + { + int i, j, ch; + + dfa->sb_char = (re_bitset_ptr_t) calloc (sizeof (bitset), 1); + if (BE (dfa->sb_char == NULL, 0)) + return REG_ESPACE; + + /* Clear all bits by, then set those corresponding to single + byte chars. */ + bitset_empty (dfa->sb_char); + + for (i = 0, ch = 0; i < BITSET_UINTS; ++i) + for (j = 0; j < UINT_BITS; ++j, ++ch) + { + wchar_t wch = __btowc (ch); + if (wch != WEOF) + dfa->sb_char[i] |= 1 << j; +# ifndef _LIBC + if (isascii (ch) && wch != (wchar_t) ch) + dfa->map_notascii = 1; +# endif + } + } } #endif @@ -1544,7 +1602,9 @@ calc_eclosure_iter (new_set, dfa, node, root) ? dfa->nodes[node].opr.ctx_type : 0); /* If the current node has constraints, duplicate all nodes. Since they must inherit the constraints. */ - if (constraint && !dfa->nodes[dfa->edests[node].elems[0]].duplicated) + if (constraint + && dfa->edests[node].nelem + && !dfa->nodes[dfa->edests[node].elems[0]].duplicated) { int org_node, cur_node; org_node = cur_node = node; diff --git a/posix/regex_internal.c b/posix/regex_internal.c index 96f113745f..609719f79c 100644 --- a/posix/regex_internal.c +++ b/posix/regex_internal.c @@ -293,9 +293,8 @@ build_wcs_upper_buffer (pstr) byte_idx = pstr->valid_len; end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len; -#ifdef _LIBC - /* The following optimization assumes that the wchar_t encoding is - always ISO 10646. */ + /* The following optimization assumes that ASCII characters can be + mapped to wide characters with a simple cast. */ if (! pstr->map_notascii && pstr->trans == NULL && !pstr->offsets_needed) { while (byte_idx < end_idx) @@ -309,8 +308,7 @@ build_wcs_upper_buffer (pstr) pstr->mbs[byte_idx] = toupper (pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx]); /* The next step uses the assumption that wchar_t is encoded - with ISO 10646: all ASCII values can be converted like - this. */ + ASCII-safe: all ASCII values can be converted like this. */ pstr->wcs[byte_idx] = (wchar_t) pstr->mbs[byte_idx]; ++byte_idx; continue; @@ -368,14 +366,11 @@ build_wcs_upper_buffer (pstr) return REG_NOERROR; } else -#endif for (src_idx = pstr->valid_raw_len; byte_idx < end_idx;) { wchar_t wc; const char *p; -#ifdef _LIBC -offsets_needed: -#endif + offsets_needed: remain_len = end_idx - byte_idx; prev_st = pstr->cur_state; if (BE (pstr->trans != NULL, 0)) @@ -647,7 +642,6 @@ re_string_reconstruct (pstr, idx, eflags) int wcs_idx; wint_t wc = WEOF; -#ifdef _LIBC if (pstr->is_utf8) { const unsigned char *raw, *p, *q, *end; @@ -687,7 +681,7 @@ re_string_reconstruct (pstr, idx, eflags) break; } } -#endif + if (wc == WEOF) pstr->valid_len = re_string_skip_chars (pstr, idx, &wc) - idx; if (BE (pstr->valid_len, 0)) diff --git a/posix/regex_internal.h b/posix/regex_internal.h index d7d7d9a8b1..023056c028 100644 --- a/posix/regex_internal.h +++ b/posix/regex_internal.h @@ -27,6 +27,9 @@ #include <stdlib.h> #include <string.h> +#if defined HAVE_LANGINFO_H || defined HAVE_LANGINFO_CODESET || defined _LIBC +# include <langinfo.h> +#endif #if defined HAVE_LOCALE_H || defined _LIBC # include <locale.h> #endif @@ -98,6 +101,7 @@ # define __btowc btowc # define __mempcpy mempcpy # define __wcrtomb wcrtomb +# define __regfree regfree # define attribute_hidden #endif /* not _LIBC */ @@ -544,7 +548,9 @@ struct re_backref_cache_entry int str_idx; int subexp_from; int subexp_to; - int flag; + /* We need only one byte from the following field. If other small + fields are added the type could be changed to 'char'. */ + int more; }; typedef struct @@ -576,17 +582,11 @@ typedef struct typedef struct { - int cur_bkref; - int cls_subexp_idx; - re_dfastate_t **sifted_states; re_dfastate_t **limited_states; - - re_node_set limits; - int last_node; int last_str_idx; - int check_subexp; + re_node_set limits; } re_sift_context_t; struct re_fail_stack_ent_t diff --git a/posix/regexec.c b/posix/regexec.c index b7b5b1a6d4..72ae70b916 100644 --- a/posix/regexec.c +++ b/posix/regexec.c @@ -29,7 +29,6 @@ static reg_errcode_t match_ctx_add_entry (re_match_context_t *cache, int node, internal_function; static int search_cur_bkref_entry (re_match_context_t *mctx, int str_idx) internal_function; -static void match_ctx_clear_flag (re_match_context_t *mctx) internal_function; static reg_errcode_t match_ctx_add_subtop (re_match_context_t *mctx, int node, int str_idx) internal_function; static re_sub_match_last_t * match_ctx_add_sublast (re_sub_match_top_t *subtop, @@ -37,7 +36,7 @@ static re_sub_match_last_t * match_ctx_add_sublast (re_sub_match_top_t *subtop, internal_function; static void sift_ctx_init (re_sift_context_t *sctx, re_dfastate_t **sifted_sts, re_dfastate_t **limited_sts, int last_node, - int last_str_idx, int check_subexp) + int last_str_idx) internal_function; static reg_errcode_t re_search_internal (const regex_t *preg, const char *string, int length, @@ -94,6 +93,9 @@ static int sift_states_iter_mb (const re_match_context_t *mctx, #endif /* RE_ENABLE_I18N */ static reg_errcode_t sift_states_backward (re_match_context_t *mctx, re_sift_context_t *sctx) internal_function; +static reg_errcode_t build_sifted_states (re_match_context_t *mctx, + re_sift_context_t *sctx, int str_idx, + re_node_set *cur_dest) internal_function; static reg_errcode_t update_cur_sifted_state (re_match_context_t *mctx, re_sift_context_t *sctx, int str_idx, @@ -107,9 +109,13 @@ static reg_errcode_t sub_epsilon_src_nodes (re_dfa_t *dfa, int node, static int check_dst_limits (re_match_context_t *mctx, re_node_set *limits, int dst_node, int dst_idx, int src_node, int src_idx) internal_function; +static int check_dst_limits_calc_pos_1 (re_match_context_t *mctx, + int boundaries, int subexp_idx, + int from_node, int bkref_idx) internal_function; static int check_dst_limits_calc_pos (re_match_context_t *mctx, - int limit, re_node_set *eclosures, - int subexp_idx, int node, int str_idx) internal_function; + int limit, int subexp_idx, + int node, int str_idx, + int bkref_idx) internal_function; static reg_errcode_t check_subexp_limits (re_dfa_t *dfa, re_node_set *dest_nodes, const re_node_set *candidates, @@ -118,7 +124,7 @@ static reg_errcode_t check_subexp_limits (re_dfa_t *dfa, int str_idx) internal_function; static reg_errcode_t sift_states_bkref (re_match_context_t *mctx, re_sift_context_t *sctx, - int str_idx, re_node_set *dest_nodes) internal_function; + int str_idx, const re_node_set *candidates) internal_function; static reg_errcode_t clean_state_log_if_needed (re_match_context_t *mctx, int next_state_log_idx) internal_function; static reg_errcode_t merge_state_array (re_dfa_t *dfa, re_dfastate_t **dst, @@ -170,8 +176,7 @@ static reg_errcode_t check_arrival_expand_ecl_sub (re_dfa_t *dfa, int type) internal_function; static reg_errcode_t expand_bkref_cache (re_match_context_t *mctx, re_node_set *cur_nodes, int cur_str, - int last_str, int subexp_num, - int type) internal_function; + int subexp_num, int type) internal_function; static re_dfastate_t **build_trtable (re_dfa_t *dfa, re_dfastate_t *state) internal_function; #ifdef RE_ENABLE_I18N @@ -578,8 +583,6 @@ re_exec (s) } #endif /* _REGEX_RE_COMP */ -static re_node_set empty_set; - /* Internal entry point. */ /* Searches for a compiled pattern PREG in the string STRING, whose @@ -642,8 +645,6 @@ re_search_internal (preg, string, length, start, range, stop, nmatch, pmatch, start = range = 0; } - re_node_set_init_empty (&empty_set); - /* We must check the longest matching, if nmatch > 0. */ fl_longest_match = (nmatch != 0 || dfa->nbackref); @@ -910,9 +911,8 @@ prune_impossible_nodes (mctx) { memset (lim_states, '\0', sizeof (re_dfastate_t *) * (match_last + 1)); - match_ctx_clear_flag (mctx); sift_ctx_init (&sctx, sifted_states, lim_states, halt_node, - match_last, 0); + match_last); ret = sift_states_backward (mctx, &sctx); re_node_set_free (&sctx.limits); if (BE (ret != REG_NOERROR, 0)) @@ -942,8 +942,7 @@ prune_impossible_nodes (mctx) } else { - sift_ctx_init (&sctx, sifted_states, lim_states, halt_node, - match_last, 0); + sift_ctx_init (&sctx, sifted_states, lim_states, halt_node, match_last); ret = sift_states_backward (mctx, &sctx); re_node_set_free (&sctx.limits); if (BE (ret != REG_NOERROR, 0)) @@ -1496,17 +1495,14 @@ sift_states_backward (mctx, sctx) re_match_context_t *mctx; re_sift_context_t *sctx; { - re_dfa_t *const dfa = mctx->dfa; reg_errcode_t err; int null_cnt = 0; int str_idx = sctx->last_str_idx; re_node_set cur_dest; - re_node_set *cur_src; /* Points the state_log[str_idx]->nodes */ #ifdef DEBUG assert (mctx->state_log != NULL && mctx->state_log[str_idx] != NULL); #endif - cur_src = &mctx->state_log[str_idx]->nodes; /* Build sifted state_log[str_idx]. It has the nodes which can epsilon transit to the last_node and the last_node itself. */ @@ -1520,7 +1516,6 @@ sift_states_backward (mctx, sctx) /* Then check each states in the state_log. */ while (str_idx > 0) { - int i, ret; /* Update counters. */ null_cnt = (sctx->sifted_states[str_idx] == NULL) ? null_cnt + 1 : 0; if (null_cnt > mctx->max_mb_elem_len) @@ -1532,56 +1527,12 @@ sift_states_backward (mctx, sctx) } re_node_set_empty (&cur_dest); --str_idx; - cur_src = ((mctx->state_log[str_idx] == NULL) ? &empty_set - : &mctx->state_log[str_idx]->nodes); - - /* Then build the next sifted state. - We build the next sifted state on `cur_dest', and update - `sifted_states[str_idx]' with `cur_dest'. - Note: - `cur_dest' is the sifted state from `state_log[str_idx + 1]'. - `cur_src' points the node_set of the old `state_log[str_idx]'. */ - for (i = 0; i < cur_src->nelem; i++) - { - int prev_node = cur_src->elems[i]; - int naccepted = 0; - re_token_type_t type = dfa->nodes[prev_node].type; - - if (IS_EPSILON_NODE (type)) - continue; -#ifdef RE_ENABLE_I18N - /* If the node may accept `multi byte'. */ - if (ACCEPT_MB_NODE (type)) - naccepted = sift_states_iter_mb (mctx, sctx, prev_node, - str_idx, sctx->last_str_idx); - -#endif /* RE_ENABLE_I18N */ - /* We don't check backreferences here. - See update_cur_sifted_state(). */ - - if (!naccepted - && check_node_accept (mctx, dfa->nodes + prev_node, str_idx) - && STATE_NODE_CONTAINS (sctx->sifted_states[str_idx + 1], - dfa->nexts[prev_node])) - naccepted = 1; - - if (naccepted == 0) - continue; - if (sctx->limits.nelem) - { - int to_idx = str_idx + naccepted; - if (check_dst_limits (mctx, &sctx->limits, - dfa->nexts[prev_node], to_idx, - prev_node, str_idx)) - continue; - } - ret = re_node_set_insert (&cur_dest, prev_node); - if (BE (ret == -1, 0)) - { - err = REG_ESPACE; - goto free_return; - } + if (mctx->state_log[str_idx]) + { + err = build_sifted_states (mctx, sctx, str_idx, &cur_dest); + if (BE (err != REG_NOERROR, 0)) + goto free_return; } /* Add all the nodes which satisfy the following conditions: @@ -1598,6 +1549,66 @@ sift_states_backward (mctx, sctx) return err; } +static reg_errcode_t +build_sifted_states (mctx, sctx, str_idx, cur_dest) + re_match_context_t *mctx; + re_sift_context_t *sctx; + int str_idx; + re_node_set *cur_dest; +{ + re_dfa_t *const dfa = mctx->dfa; + re_node_set *cur_src = &mctx->state_log[str_idx]->nodes; + int i; + + /* Then build the next sifted state. + We build the next sifted state on `cur_dest', and update + `sifted_states[str_idx]' with `cur_dest'. + Note: + `cur_dest' is the sifted state from `state_log[str_idx + 1]'. + `cur_src' points the node_set of the old `state_log[str_idx]'. */ + for (i = 0; i < cur_src->nelem; i++) + { + int prev_node = cur_src->elems[i]; + int naccepted = 0; + re_token_type_t type = dfa->nodes[prev_node].type; + int ret; + + if (IS_EPSILON_NODE (type)) + continue; +#ifdef RE_ENABLE_I18N + /* If the node may accept `multi byte'. */ + if (ACCEPT_MB_NODE (type)) + naccepted = sift_states_iter_mb (mctx, sctx, prev_node, + str_idx, sctx->last_str_idx); +#endif /* RE_ENABLE_I18N */ + + /* We don't check backreferences here. + See update_cur_sifted_state(). */ + if (!naccepted + && check_node_accept (mctx, dfa->nodes + prev_node, str_idx) + && STATE_NODE_CONTAINS (sctx->sifted_states[str_idx + 1], + dfa->nexts[prev_node])) + naccepted = 1; + + if (naccepted == 0) + continue; + + if (sctx->limits.nelem) + { + int to_idx = str_idx + naccepted; + if (check_dst_limits (mctx, &sctx->limits, + dfa->nexts[prev_node], to_idx, + prev_node, str_idx)) + continue; + } + ret = re_node_set_insert (cur_dest, prev_node); + if (BE (ret == -1, 0)) + return REG_ESPACE; + } + + return REG_NOERROR; +} + /* Helper functions. */ static reg_errcode_t @@ -1665,36 +1676,39 @@ update_cur_sifted_state (mctx, sctx, str_idx, dest_nodes) re_dfa_t *const dfa = mctx->dfa; reg_errcode_t err; const re_node_set *candidates; - candidates = ((mctx->state_log[str_idx] == NULL) ? &empty_set + candidates = ((mctx->state_log[str_idx] == NULL) ? NULL : &mctx->state_log[str_idx]->nodes); - /* At first, add the nodes which can epsilon transit to a node in - DEST_NODE. */ - if (dest_nodes->nelem) + if (dest_nodes->nelem == 0) + sctx->sifted_states[str_idx] = NULL; + else { - err = add_epsilon_src_nodes (dfa, dest_nodes, candidates); - if (BE (err != REG_NOERROR, 0)) - return err; - } + if (candidates) + { + /* At first, add the nodes which can epsilon transit to a node in + DEST_NODE. */ + err = add_epsilon_src_nodes (dfa, dest_nodes, candidates); + if (BE (err != REG_NOERROR, 0)) + return err; - /* Then, check the limitations in the current sift_context. */ - if (dest_nodes->nelem && sctx->limits.nelem) - { - err = check_subexp_limits (dfa, dest_nodes, candidates, &sctx->limits, - mctx->bkref_ents, str_idx); + /* Then, check the limitations in the current sift_context. */ + if (sctx->limits.nelem) + { + err = check_subexp_limits (dfa, dest_nodes, candidates, &sctx->limits, + mctx->bkref_ents, str_idx); + if (BE (err != REG_NOERROR, 0)) + return err; + } + } + + sctx->sifted_states[str_idx] = re_acquire_state (&err, dfa, dest_nodes); if (BE (err != REG_NOERROR, 0)) return err; } - /* Update state_log. */ - sctx->sifted_states[str_idx] = re_acquire_state (&err, dfa, dest_nodes); - if (BE (sctx->sifted_states[str_idx] == NULL && err != REG_NOERROR, 0)) - return err; - - if ((mctx->state_log[str_idx] != NULL - && mctx->state_log[str_idx]->has_backref)) + if (candidates && mctx->state_log[str_idx]->has_backref) { - err = sift_states_bkref (mctx, sctx, str_idx, dest_nodes); + err = sift_states_bkref (mctx, sctx, str_idx, candidates); if (BE (err != REG_NOERROR, 0)) return err; } @@ -1789,6 +1803,8 @@ check_dst_limits (mctx, limits, dst_node, dst_idx, src_node, src_idx) re_dfa_t *const dfa = mctx->dfa; int lim_idx, src_pos, dst_pos; + int dst_bkref_idx = search_cur_bkref_entry (mctx, dst_idx); + int src_bkref_idx = search_cur_bkref_entry (mctx, src_idx); for (lim_idx = 0; lim_idx < limits->nelem; ++lim_idx) { int subexp_idx; @@ -1797,11 +1813,11 @@ check_dst_limits (mctx, limits, dst_node, dst_idx, src_node, src_idx) subexp_idx = dfa->nodes[ent->node].opr.idx - 1; dst_pos = check_dst_limits_calc_pos (mctx, limits->elems[lim_idx], - dfa->eclosures + dst_node, - subexp_idx, dst_node, dst_idx); + subexp_idx, dst_node, dst_idx, + dst_bkref_idx); src_pos = check_dst_limits_calc_pos (mctx, limits->elems[lim_idx], - dfa->eclosures + src_node, - subexp_idx, src_node, src_idx); + subexp_idx, src_node, src_idx, + src_bkref_idx); /* In case of: <src> <dst> ( <subexp> ) @@ -1816,27 +1832,14 @@ check_dst_limits (mctx, limits, dst_node, dst_idx, src_node, src_idx) } static int -check_dst_limits_calc_pos (mctx, limit, eclosures, subexp_idx, from_node, - str_idx) +check_dst_limits_calc_pos_1 (mctx, boundaries, subexp_idx, from_node, bkref_idx) re_match_context_t *mctx; - re_node_set *eclosures; - int limit, subexp_idx, from_node, str_idx; + int boundaries, subexp_idx, from_node, bkref_idx; { re_dfa_t *const dfa = mctx->dfa; - struct re_backref_cache_entry *lim = mctx->bkref_ents + limit; + re_node_set *eclosures = dfa->eclosures + from_node; int node_idx; - /* If we are outside the range of the subexpression, return -1 or 1. */ - if (str_idx < lim->subexp_from) - return -1; - - if (lim->subexp_to < str_idx) - return 1; - - /* If we are within the subexpression, return 0. */ - if (str_idx != lim->subexp_from && str_idx != lim->subexp_to) - return 0; - /* Else, we are on the boundary: examine the nodes on the epsilon closure. */ for (node_idx = 0; node_idx < eclosures->nelem; ++node_idx) @@ -1846,17 +1849,11 @@ check_dst_limits_calc_pos (mctx, limit, eclosures, subexp_idx, from_node, { case OP_BACK_REF: { - int bi = search_cur_bkref_entry (mctx, str_idx); - for (; bi < mctx->nbkref_ents; ++bi) + struct re_backref_cache_entry *ent = mctx->bkref_ents + bkref_idx; + do { - struct re_backref_cache_entry *ent = mctx->bkref_ents + bi; int dst, cpos; - /* If this backreference goes beyond the point we're - examining, don't go any further. */ - if (ent->str_idx > str_idx) - break; - if (ent->node != node || ent->subexp_from != ent->subexp_to) continue; @@ -1869,33 +1866,32 @@ check_dst_limits_calc_pos (mctx, limit, eclosures, subexp_idx, from_node, dst = dfa->edests[node].elems[0]; if (dst == from_node) { - if (str_idx == lim->subexp_from) + if (boundaries & 1) return -1; - else /* if (str_idx == lim->subexp_to) */ + else /* if (boundaries & 2) */ return 0; } - cpos = check_dst_limits_calc_pos (mctx, limit, - dfa->eclosures + dst, - subexp_idx, dst, - str_idx); + cpos = check_dst_limits_calc_pos_1 (mctx, boundaries, + subexp_idx, dst, bkref_idx); - if (cpos == -1 && str_idx == lim->subexp_from) + if (cpos == -1 && (boundaries & 1)) return -1; - if (cpos == 0 /* && str_idx == lim->lim->subexp_to */) + if (cpos == 0 /* && (boundaries & 2) */) return 0; } - break; - } + while (ent++->more); + break; + } case OP_OPEN_SUBEXP: - if (str_idx == lim->subexp_from && subexp_idx == dfa->nodes[node].opr.idx) + if ((boundaries & 1) && subexp_idx == dfa->nodes[node].opr.idx) return -1; break; case OP_CLOSE_SUBEXP: - if (str_idx == lim->subexp_to && subexp_idx == dfa->nodes[node].opr.idx) + if ((boundaries & 2) && subexp_idx == dfa->nodes[node].opr.idx) return 0; break; @@ -1904,10 +1900,33 @@ check_dst_limits_calc_pos (mctx, limit, eclosures, subexp_idx, from_node, } } - if (str_idx == lim->subexp_to) + return (boundaries & 2) ? 1 : 0; +} + +static int +check_dst_limits_calc_pos (mctx, limit, subexp_idx, from_node, str_idx, bkref_idx) + re_match_context_t *mctx; + int limit, subexp_idx, from_node, str_idx, bkref_idx; +{ + struct re_backref_cache_entry *lim = mctx->bkref_ents + limit; + int boundaries; + + /* If we are outside the range of the subexpression, return -1 or 1. */ + if (str_idx < lim->subexp_from) + return -1; + + if (lim->subexp_to < str_idx) return 1; - else + + /* If we are within the subexpression, return 0. */ + boundaries = (str_idx == lim->subexp_from); + boundaries |= (str_idx == lim->subexp_to) << 1; + if (boundaries == 0) return 0; + + /* Else, examine epsilon closure. */ + return check_dst_limits_calc_pos_1 (mctx, boundaries, subexp_idx, + from_node, bkref_idx); } /* Check the limitations of sub expressions LIMITS, and remove the nodes @@ -2009,115 +2028,91 @@ check_subexp_limits (dfa, dest_nodes, candidates, limits, bkref_ents, str_idx) } static reg_errcode_t -sift_states_bkref (mctx, sctx, str_idx, dest_nodes) +sift_states_bkref (mctx, sctx, str_idx, candidates) re_match_context_t *mctx; re_sift_context_t *sctx; int str_idx; - re_node_set *dest_nodes; + const re_node_set *candidates; { re_dfa_t *const dfa = mctx->dfa; reg_errcode_t err; int node_idx, node; re_sift_context_t local_sctx; - const re_node_set *candidates; - candidates = ((mctx->state_log[str_idx] == NULL) ? &empty_set - : &mctx->state_log[str_idx]->nodes); + int first_idx = search_cur_bkref_entry (mctx, str_idx); + + if (first_idx == -1) + return REG_NOERROR; + local_sctx.sifted_states = NULL; /* Mark that it hasn't been initialized. */ for (node_idx = 0; node_idx < candidates->nelem; ++node_idx) { - int cur_bkref_idx = re_string_cur_idx (&mctx->input); + int enabled_idx; re_token_type_t type; + struct re_backref_cache_entry *entry; node = candidates->elems[node_idx]; type = dfa->nodes[node].type; - if (node == sctx->cur_bkref && str_idx == cur_bkref_idx) - continue; /* Avoid infinite loop for the REs like "()\1+". */ if (node == sctx->last_node && str_idx == sctx->last_str_idx) continue; - if (type == OP_BACK_REF) + if (type != OP_BACK_REF) + continue; + + entry = mctx->bkref_ents + first_idx; + enabled_idx = first_idx; + do { - int enabled_idx = search_cur_bkref_entry (mctx, str_idx); - for (; enabled_idx < mctx->nbkref_ents; ++enabled_idx) - { - int disabled_idx, subexp_len, to_idx, dst_node; - struct re_backref_cache_entry *entry; - entry = mctx->bkref_ents + enabled_idx; - if (entry->str_idx > str_idx) - break; - if (entry->node != node) - continue; - subexp_len = entry->subexp_to - entry->subexp_from; - to_idx = str_idx + subexp_len; - dst_node = (subexp_len ? dfa->nexts[node] - : dfa->edests[node].elems[0]); - - if (to_idx > sctx->last_str_idx - || sctx->sifted_states[to_idx] == NULL - || !STATE_NODE_CONTAINS (sctx->sifted_states[to_idx], - dst_node) - || check_dst_limits (mctx, &sctx->limits, node, - str_idx, dst_node, to_idx)) - continue; - { - re_dfastate_t *cur_state; - entry->flag = 0; - for (disabled_idx = enabled_idx + 1; - disabled_idx < mctx->nbkref_ents; ++disabled_idx) - { - struct re_backref_cache_entry *entry2; - entry2 = mctx->bkref_ents + disabled_idx; - if (entry2->str_idx > str_idx) - break; - entry2->flag = (entry2->node == node) ? 1 : entry2->flag; - } + int subexp_len, to_idx, dst_node; + re_dfastate_t *cur_state; - if (local_sctx.sifted_states == NULL) - { - local_sctx = *sctx; - err = re_node_set_init_copy (&local_sctx.limits, - &sctx->limits); - if (BE (err != REG_NOERROR, 0)) - goto free_return; - } - local_sctx.last_node = node; - local_sctx.last_str_idx = str_idx; - err = re_node_set_insert (&local_sctx.limits, enabled_idx); - if (BE (err < 0, 0)) - { - err = REG_ESPACE; - goto free_return; - } - cur_state = local_sctx.sifted_states[str_idx]; - err = sift_states_backward (mctx, &local_sctx); - if (BE (err != REG_NOERROR, 0)) - goto free_return; - if (sctx->limited_states != NULL) - { - err = merge_state_array (dfa, sctx->limited_states, - local_sctx.sifted_states, - str_idx + 1); - if (BE (err != REG_NOERROR, 0)) - goto free_return; - } - local_sctx.sifted_states[str_idx] = cur_state; - re_node_set_remove (&local_sctx.limits, enabled_idx); - /* We must not use the variable entry here, since - mctx->bkref_ents might be realloced. */ - mctx->bkref_ents[enabled_idx].flag = 1; - } + if (entry->node != node) + continue; + subexp_len = entry->subexp_to - entry->subexp_from; + to_idx = str_idx + subexp_len; + dst_node = (subexp_len ? dfa->nexts[node] + : dfa->edests[node].elems[0]); + + if (to_idx > sctx->last_str_idx + || sctx->sifted_states[to_idx] == NULL + || !STATE_NODE_CONTAINS (sctx->sifted_states[to_idx], dst_node) + || check_dst_limits (mctx, &sctx->limits, node, + str_idx, dst_node, to_idx)) + continue; + + if (local_sctx.sifted_states == NULL) + { + local_sctx = *sctx; + err = re_node_set_init_copy (&local_sctx.limits, &sctx->limits); + if (BE (err != REG_NOERROR, 0)) + goto free_return; } - enabled_idx = search_cur_bkref_entry (mctx, str_idx); - for (; enabled_idx < mctx->nbkref_ents; ++enabled_idx) + local_sctx.last_node = node; + local_sctx.last_str_idx = str_idx; + err = re_node_set_insert (&local_sctx.limits, enabled_idx); + if (BE (err < 0, 0)) { - struct re_backref_cache_entry *entry; - entry = mctx->bkref_ents + enabled_idx; - if (entry->str_idx > str_idx) - break; - if (entry->node == node) - entry->flag = 0; + err = REG_ESPACE; + goto free_return; } + cur_state = local_sctx.sifted_states[str_idx]; + err = sift_states_backward (mctx, &local_sctx); + if (BE (err != REG_NOERROR, 0)) + goto free_return; + if (sctx->limited_states != NULL) + { + err = merge_state_array (dfa, sctx->limited_states, + local_sctx.sifted_states, + str_idx + 1); + if (BE (err != REG_NOERROR, 0)) + goto free_return; + } + local_sctx.sifted_states[str_idx] = cur_state; + re_node_set_remove (&local_sctx.limits, enabled_idx); + + /* mctx->bkref_ents may have changed, reload the pointer. */ + entry = mctx->bkref_ents + enabled_idx; } + while (enabled_idx++, entry++->more); } err = REG_NOERROR; free_return: @@ -2611,15 +2606,15 @@ get_subexp (mctx, bkref_node, bkref_str_idx) const char *buf = (const char *) re_string_get_buffer (&mctx->input); /* Return if we have already checked BKREF_NODE at BKREF_STR_IDX. */ int cache_idx = search_cur_bkref_entry (mctx, bkref_str_idx); - for (; cache_idx < mctx->nbkref_ents; ++cache_idx) + if (cache_idx != -1) { - const struct re_backref_cache_entry *entry - = &mctx->bkref_ents[cache_idx]; - if (entry->str_idx > bkref_str_idx) - break; - if (entry->node == bkref_node) - return REG_NOERROR; /* We already checked it. */ + const struct re_backref_cache_entry *entry = mctx->bkref_ents + cache_idx; + do + if (entry->node == bkref_node) + return REG_NOERROR; /* We already checked it. */ + while (entry++->more); } + subexp_num = dfa->nodes[bkref_node].opr.idx - 1; /* For each sub expression */ @@ -2871,7 +2866,7 @@ check_arrival (mctx, path, top_node, top_str, last_node, last_str, { if (next_nodes.nelem) { - err = expand_bkref_cache (mctx, &next_nodes, str_idx, last_str, + err = expand_bkref_cache (mctx, &next_nodes, str_idx, subexp_num, type); if (BE ( err != REG_NOERROR, 0)) { @@ -2920,7 +2915,7 @@ check_arrival (mctx, path, top_node, top_str, last_node, last_str, re_node_set_free (&next_nodes); return err; } - err = expand_bkref_cache (mctx, &next_nodes, str_idx, last_str, + err = expand_bkref_cache (mctx, &next_nodes, str_idx, subexp_num, type); if (BE ( err != REG_NOERROR, 0)) { @@ -2969,6 +2964,7 @@ check_arrival_add_next_nodes (mctx, str_idx, cur_nodes, next_nodes) re_node_set *cur_nodes, *next_nodes; { re_dfa_t *const dfa = mctx->dfa; + int result; int cur_idx; reg_errcode_t err; re_node_set union_set; @@ -3002,8 +2998,8 @@ check_arrival_add_next_nodes (mctx, str_idx, cur_nodes, next_nodes) return err; } } - err = re_node_set_insert (&union_set, next_node); - if (BE (err < 0, 0)) + result = re_node_set_insert (&union_set, next_node); + if (BE (result < 0, 0)) { re_node_set_free (&union_set); return REG_ESPACE; @@ -3022,8 +3018,8 @@ check_arrival_add_next_nodes (mctx, str_idx, cur_nodes, next_nodes) if (naccepted || check_node_accept (mctx, dfa->nodes + cur_node, str_idx)) { - err = re_node_set_insert (next_nodes, dfa->nexts[cur_node]); - if (BE (err < 0, 0)) + result = re_node_set_insert (next_nodes, dfa->nexts[cur_node]); + if (BE (result < 0, 0)) { re_node_set_free (&union_set); return REG_ESPACE; @@ -3140,24 +3136,26 @@ check_arrival_expand_ecl_sub (dfa, dst_nodes, target, ex_subexp, type) in MCTX->BKREF_ENTS. */ static reg_errcode_t -expand_bkref_cache (mctx, cur_nodes, cur_str, last_str, subexp_num, +expand_bkref_cache (mctx, cur_nodes, cur_str, subexp_num, type) re_match_context_t *mctx; - int cur_str, last_str, subexp_num, type; + int cur_str, subexp_num, type; re_node_set *cur_nodes; { re_dfa_t *const dfa = mctx->dfa; reg_errcode_t err; - int cache_idx, cache_idx_start; - /* The current state. */ + int cache_idx_start = search_cur_bkref_entry (mctx, cur_str); + struct re_backref_cache_entry *ent; - cache_idx_start = search_cur_bkref_entry (mctx, cur_str); - for (cache_idx = cache_idx_start; cache_idx < mctx->nbkref_ents; ++cache_idx) + if (cache_idx_start == -1) + return REG_NOERROR; + + restart: + ent = mctx->bkref_ents + cache_idx_start; + do { int to_idx, next_node; - struct re_backref_cache_entry *ent = mctx->bkref_ents + cache_idx; - if (ent->str_idx > cur_str) - break; + /* Is this entry ENT is appropriate? */ if (!re_node_set_contains (cur_nodes, ent->node)) continue; /* No. */ @@ -3186,8 +3184,7 @@ expand_bkref_cache (mctx, cur_nodes, cur_str, last_str, subexp_num, return err; } /* TODO: It is still inefficient... */ - cache_idx = cache_idx_start - 1; - continue; + goto restart; } else { @@ -3222,6 +3219,7 @@ expand_bkref_cache (mctx, cur_nodes, cur_str, last_str, subexp_num, return err; } } + while (ent++->more); return REG_NOERROR; } @@ -3463,6 +3461,7 @@ group_nodes_into_DFAstates (dfa, state, dests_node, dests_ch) bitset *dests_ch; { reg_errcode_t err; + int result; int i, j, k; int ndests; /* Number of the destinations from `state'. */ bitset accepts; /* Characters a node can accept. */ @@ -3611,8 +3610,8 @@ group_nodes_into_DFAstates (dfa, state, dests_node, dests_ch) } /* Put the position in the current group. */ - err = re_node_set_insert (&dests_node[j], cur_nodes->elems[i]); - if (BE (err < 0, 0)) + result = re_node_set_insert (&dests_node[j], cur_nodes->elems[i]); + if (BE (result < 0, 0)) goto error_return; /* If all characters are consumed, go to next node. */ @@ -4147,26 +4146,30 @@ match_ctx_add_entry (mctx, node, str_idx, from, to) sizeof (struct re_backref_cache_entry) * mctx->abkref_ents); mctx->abkref_ents *= 2; } + if (mctx->nbkref_ents > 0 + && mctx->bkref_ents[mctx->nbkref_ents - 1].str_idx == str_idx) + mctx->bkref_ents[mctx->nbkref_ents - 1].more = 1; + mctx->bkref_ents[mctx->nbkref_ents].node = node; 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; - mctx->bkref_ents[mctx->nbkref_ents++].flag = 0; + mctx->bkref_ents[mctx->nbkref_ents++].more = 0; if (mctx->max_mb_elem_len < to - from) mctx->max_mb_elem_len = to - from; return REG_NOERROR; } -/* Search for the first entry which has the same str_idx. - Note that MCTX->BKREF_ENTS is already sorted by MCTX->STR_IDX. */ +/* Search for the first entry which has the same str_idx, or -1 if none is + found. Note that MCTX->BKREF_ENTS is already sorted by MCTX->STR_IDX. */ static int search_cur_bkref_entry (mctx, str_idx) re_match_context_t *mctx; int str_idx; { - int left, right, mid; - right = mctx->nbkref_ents; + int left, right, mid, last; + last = right = mctx->nbkref_ents; for (left = 0; left < right;) { mid = (left + right) / 2; @@ -4175,16 +4178,10 @@ search_cur_bkref_entry (mctx, str_idx) else right = mid; } - return left; -} - -static void -match_ctx_clear_flag (mctx) - re_match_context_t *mctx; -{ - int i; - for (i = 0; i < mctx->nbkref_ents; ++i) - mctx->bkref_ents[i].flag = 0; + if (left < last && mctx->bkref_ents[left].str_idx == str_idx) + return left; + else + return -1; } /* Register the node NODE, whose type is OP_OPEN_SUBEXP, and which matches @@ -4250,18 +4247,14 @@ match_ctx_add_sublast (subtop, node, str_idx) } static void -sift_ctx_init (sctx, sifted_sts, limited_sts, last_node, last_str_idx, - check_subexp) +sift_ctx_init (sctx, sifted_sts, limited_sts, last_node, last_str_idx) re_sift_context_t *sctx; re_dfastate_t **sifted_sts, **limited_sts; - int last_node, last_str_idx, check_subexp; + int last_node, last_str_idx; { sctx->sifted_states = sifted_sts; sctx->limited_states = limited_sts; sctx->last_node = last_node; sctx->last_str_idx = last_str_idx; - sctx->check_subexp = check_subexp; - sctx->cur_bkref = -1; - sctx->cls_subexp_idx = -1; re_node_set_init_empty (&sctx->limits); } diff --git a/posix/rxspencer/tests b/posix/rxspencer/tests index f4a3fb3df5..30fff15946 100644 --- a/posix/rxspencer/tests +++ b/posix/rxspencer/tests @@ -505,3 +505,8 @@ Char \([a-z0-9_]*\)\[.* b Char xyz[k Char xyz[k xyz a?b - ab ab -\{0,1\}[0-9]*$ b -5 -5 a*a*a*a*a*a*a* & aaaaaa aaaaaa +(\b){0} - x @x - +\(\b\)\{0,0\} b abc @abc - +a(\b){0}c - ac ac - +a(.*)b(\0){0}c - abc abc @bc,- +a(.*)b(\0){0}c - axbc axbc x,- diff --git a/sysdeps/generic/dl-sysdep.c b/sysdeps/generic/dl-sysdep.c index 429947ccd9..34498a880c 100644 --- a/sysdeps/generic/dl-sysdep.c +++ b/sysdeps/generic/dl-sysdep.c @@ -161,6 +161,8 @@ _dl_sysdep_start (void **start_argptr, case AT_SYSINFO: new_sysinfo = av->a_un.a_val; break; +#endif +#if defined NEED_DL_SYSINFO || defined NEED_DL_SYSINFO_DSO case AT_SYSINFO_EHDR: GLRO(dl_sysinfo_dso) = av->a_un.a_ptr; break; @@ -287,10 +289,8 @@ _dl_show_auxv (void) [AT_UCACHEBSIZE - 2] = { "AT_UCACHEBSIZE: 0x", hex }, [AT_IGNOREPPC - 2] = { "AT_IGNOREPPC", ignore }, [AT_SECURE - 2] = { "AT_SECURE: ", dec }, -#ifdef NEED_DL_SYSINFO [AT_SYSINFO - 2] = { "AT_SYSINFO: 0x", hex }, [AT_SYSINFO_EHDR - 2] = { "AT_SYSINFO_EHDR: 0x", hex }, -#endif }; unsigned int idx = (unsigned int) (av->a_type - 2); diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h index fd45bdc87f..ec68e1a565 100644 --- a/sysdeps/generic/ldsodefs.h +++ b/sysdeps/generic/ldsodefs.h @@ -470,7 +470,9 @@ struct rtld_global_ro #ifdef NEED_DL_SYSINFO /* Syscall handling improvements. This is very specific to x86. */ EXTERN uintptr_t _dl_sysinfo; +#endif +#if defined NEED_DL_SYSINFO || defined NEED_DL_SYSINFO_DSO /* The vsyscall page is a virtual DSO pre-mapped by the kernel. This points to its ELF header. */ EXTERN const ElfW(Ehdr) *_dl_sysinfo_dso; diff --git a/sysdeps/generic/sysconf.c b/sysdeps/generic/sysconf.c index d67e3568a3..f22685cb29 100644 --- a/sysdeps/generic/sysconf.c +++ b/sysdeps/generic/sysconf.c @@ -18,6 +18,8 @@ 02111-1307 USA. */ #include <errno.h> +#include <grp.h> +#include <pwd.h> #include <stdio.h> #include <unistd.h> #include <time.h> diff --git a/sysdeps/generic/tempname.c b/sysdeps/generic/tempname.c index fd4db36dc3..60c94d6409 100644 --- a/sysdeps/generic/tempname.c +++ b/sysdeps/generic/tempname.c @@ -25,11 +25,12 @@ template suitable for use in __gen_tempname into TMPL, bounded by TMPL_LEN. */ int -__path_search (tmpl, tmpl_len, dir, pfx) +__path_search (tmpl, tmpl_len, dir, pfx, try_tmpdir) char *tmpl; size_t tmpl_len; const char *dir; const char *pfx; + int try_tmpdir; { __set_errno (ENOSYS); return -1; diff --git a/sysdeps/generic/utime.c b/sysdeps/generic/utime.c index 09d0cc6679..3a3bcc38cc 100644 --- a/sysdeps/generic/utime.c +++ b/sysdeps/generic/utime.c @@ -17,6 +17,7 @@ 02111-1307 USA. */ #include <errno.h> +#include <stddef.h> #include <utime.h> diff --git a/sysdeps/gnu/_G_config.h b/sysdeps/gnu/_G_config.h index b643059234..83c78f0b93 100644 --- a/sysdeps/gnu/_G_config.h +++ b/sysdeps/gnu/_G_config.h @@ -69,6 +69,7 @@ typedef unsigned int _G_uint32_t __attribute__ ((__mode__ (__SI__))); #define _G_HAVE_PRINTF_FP 1 #define _G_HAVE_MMAP 1 +#define _G_HAVE_MREMAP 1 #define _G_HAVE_LONG_DOUBLE_IO 1 #define _G_HAVE_IO_FILE_OPEN 1 #define _G_HAVE_IO_GETLINE_INFO 1 diff --git a/sysdeps/mach/hurd/_G_config.h b/sysdeps/mach/hurd/_G_config.h new file mode 100644 index 0000000000..b643059234 --- /dev/null +++ b/sysdeps/mach/hurd/_G_config.h @@ -0,0 +1,102 @@ +/* This file is needed by libio to define various configuration parameters. + These are always the same in the GNU C library. */ + +#ifndef _G_config_h +#define _G_config_h 1 + +/* Define types for libio in terms of the standard internal type names. */ + +#include <bits/types.h> +#define __need_size_t +#define __need_wchar_t +#define __need_wint_t +#define __need_NULL +#include <stddef.h> +#ifndef _WINT_T +/* Integral type unchanged by default argument promotions that can + hold any value corresponding to members of the extended character + set, as well as at least one value that does not correspond to any + member of the extended character set. */ +# define _WINT_T +typedef unsigned int wint_t; +#endif +#define __need_mbstate_t +#include <wchar.h> +#define _G_size_t size_t +typedef struct +{ + __off_t __pos; + __mbstate_t __state; +} _G_fpos_t; +typedef struct +{ + __off64_t __pos; + __mbstate_t __state; +} _G_fpos64_t; +#define _G_ssize_t __ssize_t +#define _G_off_t __off_t +#define _G_off64_t __off64_t +#define _G_pid_t __pid_t +#define _G_uid_t __uid_t +#define _G_wchar_t wchar_t +#define _G_wint_t wint_t +#define _G_stat64 stat64 +#include <gconv.h> +typedef union +{ + struct __gconv_info __cd; + struct + { + struct __gconv_info __cd; + struct __gconv_step_data __data; + } __combined; +} _G_iconv_t; + +typedef int _G_int16_t __attribute__ ((__mode__ (__HI__))); +typedef int _G_int32_t __attribute__ ((__mode__ (__SI__))); +typedef unsigned int _G_uint16_t __attribute__ ((__mode__ (__HI__))); +typedef unsigned int _G_uint32_t __attribute__ ((__mode__ (__SI__))); + +#define _G_HAVE_BOOL 1 + + +/* These library features are always available in the GNU C library. */ +#define _G_HAVE_ATEXIT 1 +#define _G_HAVE_SYS_CDEFS 1 +#define _G_HAVE_SYS_WAIT 1 +#define _G_NEED_STDARG_H 1 +#define _G_va_list __gnuc_va_list + +#define _G_HAVE_PRINTF_FP 1 +#define _G_HAVE_MMAP 1 +#define _G_HAVE_LONG_DOUBLE_IO 1 +#define _G_HAVE_IO_FILE_OPEN 1 +#define _G_HAVE_IO_GETLINE_INFO 1 + +#define _G_IO_IO_FILE_VERSION 0x20001 + +#define _G_OPEN64 __open64 +#define _G_LSEEK64 __lseek64 +#define _G_MMAP64 __mmap64 +#define _G_FSTAT64(fd,buf) __fxstat64 (_STAT_VER, fd, buf) + +/* This is defined by <bits/stat.h> if `st_blksize' exists. */ +#define _G_HAVE_ST_BLKSIZE defined (_STATBUF_ST_BLKSIZE) + +#define _G_BUFSIZ 8192 + +/* These are the vtbl details for ELF. */ +#define _G_NAMES_HAVE_UNDERSCORE 0 +#define _G_VTABLE_LABEL_HAS_LENGTH 1 +#define _G_USING_THUNKS 1 +#define _G_VTABLE_LABEL_PREFIX "__vt_" +#define _G_VTABLE_LABEL_PREFIX_ID __vt_ + + +#if defined __cplusplus || defined __STDC__ +# define _G_ARGS(ARGLIST) ARGLIST +#else +# define _G_ARGS(ARGLIST) () +#endif + +#endif /* _G_config.h */ diff --git a/sysdeps/unix/sysv/linux/alpha/register-dump.h b/sysdeps/unix/sysv/linux/alpha/register-dump.h index d55899a2c1..77f962952a 100644 --- a/sysdeps/unix/sysv/linux/alpha/register-dump.h +++ b/sysdeps/unix/sysv/linux/alpha/register-dump.h @@ -18,7 +18,7 @@ 02111-1307 USA. */ #include <stddef.h> -#include <sys/uio.h> +#include <string.h> /* We will print the register dump in this format: @@ -51,7 +51,7 @@ #define NREGS (32+32+3) -static const char regnames[NREGS][8] = +static const char __attribute__((aligned(8))) regnames[NREGS][8] = { " V0: ", " T0: ", " T1: ", " T2: ", " T3: ", " T4: ", @@ -113,49 +113,45 @@ static const int offsets[NREGS] = #undef O -static const char linefeed[2] = "\n\n"; - static void register_dump (int fd, struct sigcontext *ctx) { - char regs[NREGS][16]; - struct iovec iov[2*NREGS+24]; - size_t iov_i = 0, i, j; + char buf[NREGS*(8+16) + 25 + 80]; + char *p = buf; + size_t i; -#define ADD_MEM(str, len) \ - (iov[iov_i].iov_base = (void *)(str), \ - iov[iov_i].iov_len = len, \ - ++iov_i) - -#define ADD_STRING(str) ADD_MEM(str, strlen(str)) - - ADD_STRING ("Register dump:\n\n"); + p = stpcpy (p, "Register dump:\n\n"); for (i = 0; i < NREGS; ++i) { int this_offset, this_lf; unsigned long val; + signed long j; this_offset = offsets[i]; this_lf = this_offset & 7; - this_offset &= -8; - val = *(unsigned long *)((char *)ctx + this_offset); + val = *(unsigned long *)(((size_t)ctx + this_offset) & -8); - for (j = 0; j < 16; ++j) + memcpy (p, regnames[i], 8); + p += 8; + + for (j = 60; j >= 0; j -= 4) { - unsigned long x = (val >> (64 - (j + 1) * 4)) & 15; + unsigned long x = (val >> j) & 15; x += x < 10 ? '0' : 'a' - 10; - regs[i][j] = x; + *p++ = x; } - ADD_MEM (regnames[i], 8); - ADD_MEM (regs[i], 16); - if (this_lf) - ADD_MEM (linefeed, this_lf); + if (this_lf > 0) + { + if (this_lf > 1) + *p++ = '\n'; + *p++ = '\n'; + } } - writev (fd, iov, iov_i); + write (fd, buf, p - buf); } #define REGISTER_DUMP register_dump (fd, ctx) diff --git a/sysdeps/unix/sysv/linux/ifaddrs.c b/sysdeps/unix/sysv/linux/ifaddrs.c index f4dce4cd61..8a052e212d 100644 --- a/sysdeps/unix/sysv/linux/ifaddrs.c +++ b/sysdeps/unix/sysv/linux/ifaddrs.c @@ -566,7 +566,7 @@ getifaddrs (struct ifaddrs **ifap) if (IN6_IS_ADDR_LINKLOCAL (rta_data) || IN6_IS_ADDR_MC_LINKLOCAL (rta_data)) ((struct sockaddr_in6 *) sa)->sin6_scope_id - = ifam->ifa_scope; + = ifam->ifa_index; } break; @@ -610,10 +610,10 @@ getifaddrs (struct ifaddrs **ifap) { memcpy (&ifas[ifa_index].addr.s6.sin6_addr, rta_data, rta_payload); - if (IN6_IS_ADDR_LINKLOCAL (rta_data) || - IN6_IS_ADDR_MC_LINKLOCAL (rta_data)) + if (IN6_IS_ADDR_LINKLOCAL (rta_data) + || IN6_IS_ADDR_MC_LINKLOCAL (rta_data)) ifas[ifa_index].addr.s6.sin6_scope_id = - ifam->ifa_scope; + ifam->ifa_index; } break; @@ -654,7 +654,7 @@ getifaddrs (struct ifaddrs **ifap) if (IN6_IS_ADDR_LINKLOCAL (rta_data) || IN6_IS_ADDR_MC_LINKLOCAL (rta_data)) ifas[ifa_index].broadaddr.s6.sin6_scope_id - = ifam->ifa_scope; + = ifam->ifa_index; } break; |