diff options
author | joseph <joseph@7b3dc134-2b1b-0410-93df-9e9f96275f8d> | 2013-03-03 17:10:55 +0000 |
---|---|---|
committer | joseph <joseph@7b3dc134-2b1b-0410-93df-9e9f96275f8d> | 2013-03-03 17:10:55 +0000 |
commit | d15f124ff59606604c0243ee19cd67bc99ecd09f (patch) | |
tree | f0b18e431b15b797d5f5dc980928cd1a26b8f74a /libc/posix | |
parent | c1078e9067234e88d5c1ca8af18ae67b64141d66 (diff) | |
download | eglibc2-d15f124ff59606604c0243ee19cd67bc99ecd09f.tar.gz |
Merge changes between r22241 and r22552 from /fsf/trunk.
git-svn-id: svn://svn.eglibc.org/trunk@22553 7b3dc134-2b1b-0410-93df-9e9f96275f8d
Diffstat (limited to 'libc/posix')
-rw-r--r-- | libc/posix/Makefile | 4 | ||||
-rw-r--r-- | libc/posix/Versions | 4 | ||||
-rw-r--r-- | libc/posix/bug-regex34.c | 46 | ||||
-rw-r--r-- | libc/posix/bug-regex35.c | 52 | ||||
-rw-r--r-- | libc/posix/regcomp.c | 72 | ||||
-rw-r--r-- | libc/posix/regex_internal.h | 27 | ||||
-rw-r--r-- | libc/posix/regexec.c | 16 | ||||
-rw-r--r-- | libc/posix/wordexp.c | 14 |
8 files changed, 163 insertions, 72 deletions
diff --git a/libc/posix/Makefile b/libc/posix/Makefile index 70d09ea17..489baab72 100644 --- a/libc/posix/Makefile +++ b/libc/posix/Makefile @@ -97,7 +97,7 @@ tests := tstgetopt testfnm runtests \ tst-execvp3 tst-execvp4 \ tst-fnmatch2 tst-cpucount tst-cpuset \ bug-getopt1 bug-getopt2 bug-getopt3 bug-getopt4 \ - bug-getopt5 tst-getopt_long1 + bug-getopt5 tst-getopt_long1 bug-regex34 bug-regex35 tests-$(OPTION_EGLIBC_LOCALE_CODE) \ += tst-fnmatch tst-regexloc bug-regex1 bug-regex5 \ bug-regex23 bug-regex25 bug-regex32 bug-regex33 @@ -229,6 +229,8 @@ bug-regex26-ENV = LOCPATH=$(common-objpfx)localedata bug-regex30-ENV = LOCPATH=$(common-objpfx)localedata bug-regex32-ENV = LOCPATH=$(common-objpfx)localedata bug-regex33-ENV = LOCPATH=$(common-objpfx)localedata +bug-regex34-ENV = LOCPATH=$(common-objpfx)localedata +bug-regex35-ENV = LOCPATH=$(common-objpfx)localedata tst-rxspencer-ARGS = rxspencer/tests ifeq (y,$(OPTION_EGLIBC_LOCALE_CODE)) tst-rxspencer-ARGS += --utf8 diff --git a/libc/posix/Versions b/libc/posix/Versions index 686c446bc..1bc235acd 100644 --- a/libc/posix/Versions +++ b/libc/posix/Versions @@ -1,7 +1,7 @@ libc { GLIBC_2.0 { # functions with special/multiple interfaces - __bsd_getpgrp; __setpgid; __getpgid; + __bsd_getpgrp; __getpgid; __setpgid; # functions with required interface outside normal name space _exit; @@ -114,7 +114,7 @@ libc { # under GLIBC_2.0; the first instance in the script is taken as the # default, so linux configurations put them in GLIBC_2.0 while other # configuration put them in GLIBC_2.3.2. - getresuid; getresgid; setresuid; setresgid; + getresgid; getresuid; setresgid; setresuid; } GLIBC_2.3.3 { sched_getaffinity; sched_setaffinity; diff --git a/libc/posix/bug-regex34.c b/libc/posix/bug-regex34.c new file mode 100644 index 000000000..bb3b6138f --- /dev/null +++ b/libc/posix/bug-regex34.c @@ -0,0 +1,46 @@ +/* Test re_search with multi-byte characters in UTF-8. + Copyright (C) 2013 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#define _GNU_SOURCE 1 +#include <stdio.h> +#include <string.h> +#include <locale.h> +#include <regex.h> + +static int +do_test (void) +{ + struct re_pattern_buffer r; + /* ကျွန်ုပ်x */ + const char *s = "\xe1\x80\x80\xe1\x80\xbb\xe1\x80\xbd\xe1\x80\x94\xe1\x80\xba\xe1\x80\xaf\xe1\x80\x95\xe1\x80\xbax"; + + if (setlocale (LC_ALL, "en_US.UTF-8") == NULL) + { + puts ("setlocale failed"); + return 1; + } + memset (&r, 0, sizeof (r)); + + re_compile_pattern ("[^x]x", 5, &r); + /* This was triggering a buffer overflow. */ + re_search (&r, s, strlen (s), 0, strlen (s), 0); + return 0; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/libc/posix/bug-regex35.c b/libc/posix/bug-regex35.c new file mode 100644 index 000000000..7957e7f86 --- /dev/null +++ b/libc/posix/bug-regex35.c @@ -0,0 +1,52 @@ +/* Test regcomp with collating symbols in bracket expressions + Copyright (C) 2013 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <stdio.h> +#include <string.h> +#include <locale.h> +#include <regex.h> + +static int +do_test (void) +{ + regex_t r; + + if (setlocale (LC_ALL, "cs_CZ.UTF-8") == NULL) + { + puts ("setlocale failed"); + return 1; + } + + if (regcomp (&r, "[[.ch.]]", REG_NOSUB) != 0) + { + puts ("regcomp failed"); + return 1; + } + + if (regexec (&r, "ch", 0, 0, 0) != 0) + { + puts ("regexec failed"); + return 1; + } + + regfree (&r); + return 0; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/libc/posix/regcomp.c b/libc/posix/regcomp.c index c6ef42068..b90c8fc25 100644 --- a/libc/posix/regcomp.c +++ b/libc/posix/regcomp.c @@ -2792,40 +2792,29 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token, /* Local function for parse_bracket_exp used in _LIBC environement. Seek the collating symbol entry correspondings to NAME. - Return the index of the symbol in the SYMB_TABLE. */ + Return the index of the symbol in the SYMB_TABLE, + or -1 if not found. */ auto inline int32_t __attribute ((always_inline)) - seek_collating_symbol_entry (name, name_len) - const unsigned char *name; - size_t name_len; + seek_collating_symbol_entry (const unsigned char *name, size_t name_len) { - int32_t hash = elem_hash ((const char *) name, name_len); - int32_t elem = hash % table_size; - if (symb_table[2 * elem] != 0) - { - int32_t second = hash % (table_size - 2) + 1; - - do - { - /* First compare the hashing value. */ - if (symb_table[2 * elem] == hash - /* Compare the length of the name. */ - && name_len == extra[symb_table[2 * elem + 1]] - /* Compare the name. */ - && memcmp (name, &extra[symb_table[2 * elem + 1] + 1], - name_len) == 0) - { - /* Yep, this is the entry. */ - break; - } + int32_t elem; - /* Next entry. */ - elem += second; - } - while (symb_table[2 * elem] != 0); - } - return elem; + for (elem = 0; elem < table_size; elem++) + if (symb_table[2 * elem] != 0) + { + int32_t idx = symb_table[2 * elem + 1]; + /* Skip the name of collating element name. */ + idx += 1 + extra[idx]; + if (/* Compare the length of the name. */ + name_len == extra[idx] + /* Compare the name. */ + && memcmp (name, &extra[idx + 1], name_len) == 0) + /* Yep, this is the entry. */ + return elem; + } + return -1; } /* Local function for parse_bracket_exp used in _LIBC environment. @@ -2834,8 +2823,7 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token, auto inline unsigned int __attribute ((always_inline)) - lookup_collation_sequence_value (br_elem) - bracket_elem_t *br_elem; + lookup_collation_sequence_value (bracket_elem_t *br_elem) { if (br_elem->type == SB_CHAR) { @@ -2865,7 +2853,7 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token, int32_t elem, idx; elem = seek_collating_symbol_entry (br_elem->opr.name, sym_name_len); - if (symb_table[2 * elem] != 0) + if (elem != -1) { /* We found the entry. */ idx = symb_table[2 * elem + 1]; @@ -2883,7 +2871,7 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token, /* Return the collation sequence value. */ return *(unsigned int *) (extra + idx); } - else if (symb_table[2 * elem] == 0 && sym_name_len == 1) + else if (sym_name_len == 1) { /* No valid character. Match it as a single byte character. */ @@ -2905,11 +2893,8 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token, auto inline reg_errcode_t __attribute ((always_inline)) - build_range_exp (sbcset, mbcset, range_alloc, start_elem, end_elem) - re_charset_t *mbcset; - int *range_alloc; - bitset_t sbcset; - bracket_elem_t *start_elem, *end_elem; + build_range_exp (bitset_t sbcset, re_charset_t *mbcset, int *range_alloc, + bracket_elem_t *start_elem, bracket_elem_t *end_elem) { unsigned int ch; uint32_t start_collseq; @@ -2988,25 +2973,22 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token, auto inline reg_errcode_t __attribute ((always_inline)) - build_collating_symbol (sbcset, mbcset, coll_sym_alloc, name) - re_charset_t *mbcset; - int *coll_sym_alloc; - bitset_t sbcset; - const unsigned char *name; + build_collating_symbol (bitset_t sbcset, re_charset_t *mbcset, + int *coll_sym_alloc, const unsigned char *name) { int32_t elem, idx; size_t name_len = strlen ((const char *) name); if (nrules != 0) { elem = seek_collating_symbol_entry (name, name_len); - if (symb_table[2 * elem] != 0) + if (elem != -1) { /* We found the entry. */ idx = symb_table[2 * elem + 1]; /* Skip the name of collating element name. */ idx += 1 + extra[idx]; } - else if (symb_table[2 * elem] == 0 && name_len == 1) + else if (name_len == 1) { /* No valid character, treat it as a normal character. */ diff --git a/libc/posix/regex_internal.h b/libc/posix/regex_internal.h index d24cded12..46a1ad2d4 100644 --- a/libc/posix/regex_internal.h +++ b/libc/posix/regex_internal.h @@ -102,7 +102,6 @@ # define BE(expr, val) __builtin_expect (expr, val) #else # define BE(expr, val) (expr) -# define inline #endif /* Number of single byte character. */ @@ -126,10 +125,8 @@ # define attribute_hidden #endif /* not _LIBC */ -#ifdef __GNUC__ -# define __attribute(arg) __attribute__ (arg) -#else -# define __attribute(arg) +#if __GNUC__ < 3 + (__GNUC_MINOR__ < 1) +# define __attribute__(arg) #endif extern const char __re_error_msgid[] attribute_hidden; @@ -390,7 +387,7 @@ typedef struct re_dfa_t re_dfa_t; #ifndef _LIBC # ifdef __i386__ -# define internal_function __attribute ((regparm (3), stdcall)) +# define internal_function __attribute__ ((regparm (3), stdcall)) # else # define internal_function # endif @@ -409,7 +406,7 @@ static void build_upper_buffer (re_string_t *pstr) internal_function; static void re_string_translate_buffer (re_string_t *pstr) internal_function; static unsigned int re_string_context_at (const re_string_t *input, int idx, int eflags) - internal_function __attribute ((pure)); + internal_function __attribute__ ((pure)); #endif #define re_string_peek_byte(pstr, offset) \ ((pstr)->mbs[(pstr)->cur_idx + offset]) @@ -706,7 +703,7 @@ typedef struct /* Inline functions for bitset operation. */ -static inline void +static void __attribute__ ((unused)) bitset_not (bitset_t set) { int bitset_i; @@ -714,7 +711,7 @@ bitset_not (bitset_t set) set[bitset_i] = ~set[bitset_i]; } -static inline void +static void __attribute__ ((unused)) bitset_merge (bitset_t dest, const bitset_t src) { int bitset_i; @@ -722,7 +719,7 @@ bitset_merge (bitset_t dest, const bitset_t src) dest[bitset_i] |= src[bitset_i]; } -static inline void +static void __attribute__ ((unused)) bitset_mask (bitset_t dest, const bitset_t src) { int bitset_i; @@ -732,8 +729,8 @@ bitset_mask (bitset_t dest, const bitset_t src) #ifdef RE_ENABLE_I18N /* Inline functions for re_string. */ -static inline int -internal_function __attribute ((pure)) +static int +internal_function __attribute__ ((pure, unused)) re_string_char_size_at (const re_string_t *pstr, int idx) { int byte_idx; @@ -745,8 +742,8 @@ re_string_char_size_at (const re_string_t *pstr, int idx) return byte_idx; } -static inline wint_t -internal_function __attribute ((pure)) +static wint_t +internal_function __attribute__ ((pure, unused)) re_string_wchar_at (const re_string_t *pstr, int idx) { if (string_mb_cur_max (pstr) == 1) @@ -756,7 +753,7 @@ re_string_wchar_at (const re_string_t *pstr, int idx) # ifndef NOT_IN_libc static int -internal_function __attribute ((pure)) +internal_function __attribute__ ((pure, unused)) re_string_elem_size_at (const re_string_t *pstr, int idx) { # ifdef _LIBC diff --git a/libc/posix/regexec.c b/libc/posix/regexec.c index 842f6163f..894d363d5 100644 --- a/libc/posix/regexec.c +++ b/libc/posix/regexec.c @@ -199,7 +199,7 @@ static int group_nodes_into_DFAstates (const re_dfa_t *dfa, static int check_node_accept (const re_match_context_t *mctx, const re_token_t *node, int idx) internal_function; -static reg_errcode_t extend_buffers (re_match_context_t *mctx) +static reg_errcode_t extend_buffers (re_match_context_t *mctx, int min_len) internal_function; /* Entry point for POSIX code. */ @@ -1146,7 +1146,7 @@ check_matching (re_match_context_t *mctx, int fl_longest_match, || (BE (next_char_idx >= mctx->input.valid_len, 0) && mctx->input.valid_len < mctx->input.len)) { - err = extend_buffers (mctx); + err = extend_buffers (mctx, next_char_idx + 1); if (BE (err != REG_NOERROR, 0)) { assert (err == REG_ESPACE); @@ -1724,7 +1724,7 @@ clean_state_log_if_needed (re_match_context_t *mctx, int next_state_log_idx) && mctx->input.valid_len < mctx->input.len)) { reg_errcode_t err; - err = extend_buffers (mctx); + err = extend_buffers (mctx, next_state_log_idx + 1); if (BE (err != REG_NOERROR, 0)) return err; } @@ -2778,7 +2778,7 @@ get_subexp (re_match_context_t *mctx, int bkref_node, int bkref_str_idx) if (bkref_str_off >= mctx->input.len) break; - err = extend_buffers (mctx); + err = extend_buffers (mctx, bkref_str_off + 1); if (BE (err != REG_NOERROR, 0)) return err; @@ -4096,7 +4096,7 @@ check_node_accept (const re_match_context_t *mctx, const re_token_t *node, static reg_errcode_t internal_function __attribute_warn_unused_result__ -extend_buffers (re_match_context_t *mctx) +extend_buffers (re_match_context_t *mctx, int min_len) { reg_errcode_t ret; re_string_t *pstr = &mctx->input; @@ -4105,8 +4105,10 @@ extend_buffers (re_match_context_t *mctx) if (BE (INT_MAX / 2 / sizeof (re_dfastate_t *) <= pstr->bufs_len, 0)) return REG_ESPACE; - /* Double the lengthes of the buffers. */ - ret = re_string_realloc_buffers (pstr, MIN (pstr->len, pstr->bufs_len * 2)); + /* Double the lengthes of the buffers, but allocate at least MIN_LEN. */ + ret = re_string_realloc_buffers (pstr, + MAX (min_len, + MIN (pstr->len, pstr->bufs_len * 2))); if (BE (ret != REG_NOERROR, 0)) return ret; diff --git a/libc/posix/wordexp.c b/libc/posix/wordexp.c index bf49baab9..96ce8a4b1 100644 --- a/libc/posix/wordexp.c +++ b/libc/posix/wordexp.c @@ -953,7 +953,12 @@ exec_comm (char *comm, char **word, size_t *word_length, size_t *max_length, if ((buflen = TEMP_FAILURE_RETRY (__read (fildes[0], buffer, bufsize))) < 1) { - if (TEMP_FAILURE_RETRY (__waitpid (pid, &status, WNOHANG)) == 0) + /* If read returned 0 then the process has closed its + stdout. Don't use WNOHANG in that case to avoid busy + looping until the process eventually exits. */ + if (TEMP_FAILURE_RETRY (__waitpid (pid, &status, + buflen == 0 ? 0 : WNOHANG)) + == 0) continue; if ((buflen = TEMP_FAILURE_RETRY (__read (fildes[0], buffer, bufsize))) < 1) @@ -983,7 +988,12 @@ exec_comm (char *comm, char **word, size_t *word_length, size_t *max_length, if ((buflen = TEMP_FAILURE_RETRY (__read (fildes[0], buffer, bufsize))) < 1) { - if (TEMP_FAILURE_RETRY (__waitpid (pid, &status, WNOHANG)) == 0) + /* If read returned 0 then the process has closed its + stdout. Don't use WNOHANG in that case to avoid busy + looping until the process eventually exits. */ + if (TEMP_FAILURE_RETRY (__waitpid (pid, &status, + buflen == 0 ? 0 : WNOHANG)) + == 0) continue; if ((buflen = TEMP_FAILURE_RETRY (__read (fildes[0], buffer, bufsize))) < 1) |