libroot: Synchronize glibc regex with upstream 2.20.

More recent versions require more changes to adapt.
This commit is contained in:
Augustin Cavalier
2024-07-22 19:56:48 -04:00
parent 708ea40201
commit d3f63a3e4c
6 changed files with 467 additions and 346 deletions
+1 -1
View File
@@ -1,7 +1,7 @@
SubDir HAIKU_TOP src system libroot posix glibc regex ; SubDir HAIKU_TOP src system libroot posix glibc regex ;
SubDirHdrs $(HAIKU_TOP) headers ; SubDirHdrs $(HAIKU_TOP) headers ;
SubDirCcFlags -D_REGEX_RE_COMP -D_DEFAULT_SOURCE -DHAVE_STDBOOL_H ; SubDirCcFlags -D_REGEX_RE_COMP -D_DEFAULT_SOURCE -DHAVE_STDBOOL_H -DHAVE_STDINT_H ;
local architectureObject ; local architectureObject ;
for architectureObject in [ MultiArchSubDirSetup ] { for architectureObject in [ MultiArchSubDirSetup ] {
+132 -77
View File
@@ -1,6 +1,5 @@
/* Extended regular expression matching and search library. /* Extended regular expression matching and search library.
Copyright (C) 2002,2003,2004,2005,2006,2007,2009 Copyright (C) 2002-2014 Free Software Foundation, Inc.
Free Software Foundation, Inc.
This file is part of the GNU C Library. This file is part of the GNU C Library.
Contributed by Isamu Hasegawa <[email protected]>. Contributed by Isamu Hasegawa <[email protected]>.
@@ -15,9 +14,14 @@
Lesser General Public License for more details. Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free License along with the GNU C Library; if not, see
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA <http://www.gnu.org/licenses/>. */
02111-1307 USA. */
#include <stdint.h>
#ifdef _LIBC
# include <locale/weight.h>
#endif
static reg_errcode_t re_compile_internal (regex_t *preg, const char * pattern, static reg_errcode_t re_compile_internal (regex_t *preg, const char * pattern,
size_t length, reg_syntax_t syntax); size_t length, reg_syntax_t syntax);
@@ -121,7 +125,7 @@ static bin_tree_t *duplicate_tree (const bin_tree_t *src, re_dfa_t *dfa);
static void free_token (re_token_t *node); static void free_token (re_token_t *node);
static reg_errcode_t free_tree (void *extra, bin_tree_t *node); static reg_errcode_t free_tree (void *extra, bin_tree_t *node);
static reg_errcode_t mark_opt_subexp (void *extra, bin_tree_t *node); static reg_errcode_t mark_opt_subexp (void *extra, bin_tree_t *node);
/* This table gives an error message for each of the error codes listed /* This table gives an error message for each of the error codes listed
in regex.h. Obviously the order here has to be same as there. in regex.h. Obviously the order here has to be same as there.
POSIX doesn't require that we do anything for REG_NOERROR, POSIX doesn't require that we do anything for REG_NOERROR,
@@ -201,7 +205,7 @@ const size_t __re_error_msgid_idx[] attribute_hidden =
REG_ESIZE_IDX, REG_ESIZE_IDX,
REG_ERPAREN_IDX REG_ERPAREN_IDX
}; };
/* Entry points for GNU code. */ /* Entry points for GNU code. */
/* re_compile_pattern is the GNU regular expression compiler: it /* re_compile_pattern is the GNU regular expression compiler: it
@@ -377,7 +381,7 @@ re_compile_fastmap_iter (regex_t *bufp, const re_dfastate_t *init_state,
applies to multibyte character sets; for single byte character applies to multibyte character sets; for single byte character
sets, the SIMPLE_BRACKET again suffices. */ sets, the SIMPLE_BRACKET again suffices. */
if (dfa->mb_cur_max > 1 if (dfa->mb_cur_max > 1
&& (cset->nchar_classes || cset->non_match && (cset->nchar_classes || cset->non_match || cset->nranges
# ifdef _LIBC # ifdef _LIBC
|| cset->nequiv_classes || cset->nequiv_classes
# endif /* _LIBC */ # endif /* _LIBC */
@@ -427,7 +431,7 @@ re_compile_fastmap_iter (regex_t *bufp, const re_dfastate_t *init_state,
} }
} }
} }
/* Entry point for POSIX code. */ /* Entry point for POSIX code. */
/* regcomp takes a regular expression as a string and compiles it. /* regcomp takes a regular expression as a string and compiles it.
@@ -653,7 +657,7 @@ regfree (preg)
#ifdef _LIBC #ifdef _LIBC
weak_alias (__regfree, regfree) weak_alias (__regfree, regfree)
#endif #endif
/* Entry points compatible with 4.2 BSD regex library. We don't define /* Entry points compatible with 4.2 BSD regex library. We don't define
them unless specifically requested. */ them unless specifically requested. */
@@ -722,7 +726,7 @@ libc_freeres_fn (free_mem)
#endif #endif
#endif /* _REGEX_RE_COMP */ #endif /* _REGEX_RE_COMP */
/* Internal entry point. /* Internal entry point.
Compile the regular expression PATTERN, whose length is LENGTH. Compile the regular expression PATTERN, whose length is LENGTH.
SYNTAX indicate regular expression's syntax. */ SYNTAX indicate regular expression's syntax. */
@@ -927,12 +931,49 @@ static void
internal_function internal_function
init_word_char (re_dfa_t *dfa) init_word_char (re_dfa_t *dfa)
{ {
int i, j, ch;
dfa->word_ops_used = 1; dfa->word_ops_used = 1;
for (i = 0, ch = 0; i < BITSET_WORDS; ++i) {
int i = 0;
int ch = 0;
if (BE (dfa->map_notascii == 0, 1))
{
if (sizeof (dfa->word_char[0]) == 8)
{
/* The extra temporaries here avoid "implicitly truncated"
warnings in the case when this is dead code, i.e. 32-bit. */
const uint64_t wc0 = UINT64_C (0x03ff000000000000);
const uint64_t wc1 = UINT64_C (0x07fffffe87fffffe);
dfa->word_char[0] = wc0;
dfa->word_char[1] = wc1;
i = 2;
}
else if (sizeof (dfa->word_char[0]) == 4)
{
dfa->word_char[0] = UINT32_C (0x00000000);
dfa->word_char[1] = UINT32_C (0x03ff0000);
dfa->word_char[2] = UINT32_C (0x87fffffe);
dfa->word_char[3] = UINT32_C (0x07fffffe);
i = 4;
}
else
abort ();
ch = 128;
if (BE (dfa->is_utf8, 1))
{
memset (&dfa->word_char[i], '\0', (SBC_MAX - ch) / 8);
return;
}
}
{
int j;
for (; i < BITSET_WORDS; ++i)
for (j = 0; j < BITSET_WORD_BITS; ++j, ++ch) for (j = 0; j < BITSET_WORD_BITS; ++j, ++ch)
if (isalnum (ch) || ch == '_') if (isalnum (ch) || ch == '_')
dfa->word_char[i] |= (bitset_word_t) 1 << j; dfa->word_char[i] |= (bitset_word_t) 1 << j;
}
}
} }
/* Free the work area which are only used while compiling. */ /* Free the work area which are only used while compiling. */
@@ -1000,7 +1041,11 @@ create_initial_state (re_dfa_t *dfa)
int dest_idx = dfa->edests[node_idx].elems[0]; int dest_idx = dfa->edests[node_idx].elems[0];
if (!re_node_set_contains (&init_nodes, dest_idx)) if (!re_node_set_contains (&init_nodes, dest_idx))
{ {
re_node_set_merge (&init_nodes, dfa->eclosures + dest_idx); reg_errcode_t err = re_node_set_merge (&init_nodes,
dfa->eclosures
+ dest_idx);
if (err != REG_NOERROR)
return err;
i = 0; i = 0;
} }
} }
@@ -1032,7 +1077,7 @@ create_initial_state (re_dfa_t *dfa)
re_node_set_free (&init_nodes); re_node_set_free (&init_nodes);
return REG_NOERROR; return REG_NOERROR;
} }
#ifdef RE_ENABLE_I18N #ifdef RE_ENABLE_I18N
/* If it is possible to do searching in single byte encoding instead of UTF-8 /* If it is possible to do searching in single byte encoding instead of UTF-8
to speed things up, set dfa->mb_cur_max to 1, clear is_utf8 and change to speed things up, set dfa->mb_cur_max to 1, clear is_utf8 and change
@@ -1104,7 +1149,7 @@ optimize_utf8 (re_dfa_t *dfa)
dfa->has_mb_node = dfa->nbackref > 0 || has_period; dfa->has_mb_node = dfa->nbackref > 0 || has_period;
} }
#endif #endif
/* Analyze the structure tree, and calculate "first", "next", "edest", /* Analyze the structure tree, and calculate "first", "next", "edest",
"eclosure", and "inveclosure". */ "eclosure", and "inveclosure". */
@@ -1415,7 +1460,7 @@ link_nfa_nodes (void *extra, bin_tree_t *node)
case OP_BACK_REF: case OP_BACK_REF:
dfa->nexts[idx] = node->next->node_idx; dfa->nexts[idx] = node->next->node_idx;
if (node->token.type == OP_BACK_REF) if (node->token.type == OP_BACK_REF)
re_node_set_init_1 (dfa->edests + idx, dfa->nexts[idx]); err = re_node_set_init_1 (dfa->edests + idx, dfa->nexts[idx]);
break; break;
default: default:
@@ -1643,9 +1688,10 @@ static reg_errcode_t
calc_eclosure_iter (re_node_set *new_set, re_dfa_t *dfa, int node, int root) calc_eclosure_iter (re_node_set *new_set, re_dfa_t *dfa, int node, int root)
{ {
reg_errcode_t err; reg_errcode_t err;
int i, incomplete; int i;
re_node_set eclosure; re_node_set eclosure;
incomplete = 0; int ret;
int incomplete = 0;
err = re_node_set_alloc (&eclosure, dfa->edests[node].nelem + 1); err = re_node_set_alloc (&eclosure, dfa->edests[node].nelem + 1);
if (BE (err != REG_NOERROR, 0)) if (BE (err != REG_NOERROR, 0))
return err; return err;
@@ -1690,7 +1736,9 @@ calc_eclosure_iter (re_node_set *new_set, re_dfa_t *dfa, int node, int root)
else else
eclosure_elem = dfa->eclosures[edest]; eclosure_elem = dfa->eclosures[edest];
/* Merge the epsilon closure of `edest'. */ /* Merge the epsilon closure of `edest'. */
re_node_set_merge (&eclosure, &eclosure_elem); err = re_node_set_merge (&eclosure, &eclosure_elem);
if (BE (err != REG_NOERROR, 0))
return err;
/* If the epsilon closure of `edest' is incomplete, /* If the epsilon closure of `edest' is incomplete,
the epsilon closure of this node is also incomplete. */ the epsilon closure of this node is also incomplete. */
if (dfa->eclosures[edest].nelem == 0) if (dfa->eclosures[edest].nelem == 0)
@@ -1700,8 +1748,10 @@ calc_eclosure_iter (re_node_set *new_set, re_dfa_t *dfa, int node, int root)
} }
} }
/* Epsilon closures include itself. */ /* An epsilon closure includes itself. */
re_node_set_insert (&eclosure, node); ret = re_node_set_insert (&eclosure, node);
if (BE (ret < 0, 0))
return REG_ESPACE;
if (incomplete && !root) if (incomplete && !root)
dfa->eclosures[node].nelem = 0; dfa->eclosures[node].nelem = 0;
else else
@@ -1709,7 +1759,7 @@ calc_eclosure_iter (re_node_set *new_set, re_dfa_t *dfa, int node, int root)
*new_set = eclosure; *new_set = eclosure;
return REG_NOERROR; return REG_NOERROR;
} }
/* Functions for token which are used in the parser. */ /* Functions for token which are used in the parser. */
/* Fetch a token from INPUT. /* Fetch a token from INPUT.
@@ -2046,7 +2096,7 @@ peek_token_bracket (re_token_t *token, re_string_t *input, reg_syntax_t syntax)
} }
return 1; return 1;
} }
/* Functions for parser. */ /* Functions for parser. */
/* Entry point of the parser. /* Entry point of the parser.
@@ -2113,8 +2163,12 @@ parse_reg_exp (re_string_t *regexp, regex_t *preg, re_token_t *token,
{ {
branch = parse_branch (regexp, preg, token, syntax, nest, err); branch = parse_branch (regexp, preg, token, syntax, nest, err);
if (BE (*err != REG_NOERROR && branch == NULL, 0)) if (BE (*err != REG_NOERROR && branch == NULL, 0))
{
if (tree != NULL)
postorder (tree, free_tree, NULL);
return NULL; return NULL;
} }
}
else else
branch = NULL; branch = NULL;
tree = create_tree (dfa, tree, branch, OP_ALT); tree = create_tree (dfa, tree, branch, OP_ALT);
@@ -2152,16 +2206,21 @@ parse_branch (re_string_t *regexp, regex_t *preg, re_token_t *token,
exp = parse_expression (regexp, preg, token, syntax, nest, err); exp = parse_expression (regexp, preg, token, syntax, nest, err);
if (BE (*err != REG_NOERROR && exp == NULL, 0)) if (BE (*err != REG_NOERROR && exp == NULL, 0))
{ {
if (tree != NULL)
postorder (tree, free_tree, NULL);
return NULL; return NULL;
} }
if (tree != NULL && exp != NULL) if (tree != NULL && exp != NULL)
{ {
tree = create_tree (dfa, tree, exp, CONCAT); bin_tree_t *newtree = create_tree (dfa, tree, exp, CONCAT);
if (tree == NULL) if (newtree == NULL)
{ {
postorder (exp, free_tree, NULL);
postorder (tree, free_tree, NULL);
*err = REG_ESPACE; *err = REG_ESPACE;
return NULL; return NULL;
} }
tree = newtree;
} }
else if (tree == NULL) else if (tree == NULL)
tree = exp; tree = exp;
@@ -2369,14 +2428,21 @@ parse_expression (re_string_t *regexp, regex_t *preg, re_token_t *token,
while (token->type == OP_DUP_ASTERISK || token->type == OP_DUP_PLUS while (token->type == OP_DUP_ASTERISK || token->type == OP_DUP_PLUS
|| token->type == OP_DUP_QUESTION || token->type == OP_OPEN_DUP_NUM) || token->type == OP_DUP_QUESTION || token->type == OP_OPEN_DUP_NUM)
{ {
tree = parse_dup_op (tree, regexp, dfa, token, syntax, err); bin_tree_t *dup_tree = parse_dup_op (tree, regexp, dfa, token, syntax, err);
if (BE (*err != REG_NOERROR && tree == NULL, 0)) if (BE (*err != REG_NOERROR && dup_tree == NULL, 0))
{
if (tree != NULL)
postorder (tree, free_tree, NULL);
return NULL; return NULL;
}
tree = dup_tree;
/* In BRE consecutive duplications are not allowed. */ /* In BRE consecutive duplications are not allowed. */
if ((syntax & RE_CONTEXT_INVALID_DUP) if ((syntax & RE_CONTEXT_INVALID_DUP)
&& (token->type == OP_DUP_ASTERISK && (token->type == OP_DUP_ASTERISK
|| token->type == OP_OPEN_DUP_NUM)) || token->type == OP_OPEN_DUP_NUM))
{ {
if (tree != NULL)
postorder (tree, free_tree, NULL);
*err = REG_BADRPT; *err = REG_BADRPT;
return NULL; return NULL;
} }
@@ -2410,7 +2476,11 @@ parse_sub_exp (re_string_t *regexp, regex_t *preg, re_token_t *token,
{ {
tree = parse_reg_exp (regexp, preg, token, syntax, nest, err); tree = parse_reg_exp (regexp, preg, token, syntax, nest, err);
if (BE (*err == REG_NOERROR && token->type != OP_CLOSE_SUBEXP, 0)) if (BE (*err == REG_NOERROR && token->type != OP_CLOSE_SUBEXP, 0))
{
if (tree != NULL)
postorder (tree, free_tree, NULL);
*err = REG_EPAREN; *err = REG_EPAREN;
}
if (BE (*err != REG_NOERROR, 0)) if (BE (*err != REG_NOERROR, 0))
return NULL; return NULL;
} }
@@ -2521,6 +2591,8 @@ parse_dup_op (bin_tree_t *elem, re_string_t *regexp, re_dfa_t *dfa,
/* Duplicate ELEM before it is marked optional. */ /* Duplicate ELEM before it is marked optional. */
elem = duplicate_tree (elem, dfa); elem = duplicate_tree (elem, dfa);
if (BE (elem == NULL, 0))
goto parse_dup_op_espace;
old_tree = tree; old_tree = tree;
} }
else else
@@ -2728,41 +2800,30 @@ 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. /* Local function for parse_bracket_exp used in _LIBC environement.
Seek the collating symbol entry correspondings to NAME. 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 auto inline int32_t
__attribute ((always_inline)) __attribute ((always_inline))
seek_collating_symbol_entry (name, name_len) seek_collating_symbol_entry (const unsigned char *name, size_t name_len)
const unsigned char *name;
size_t name_len;
{ {
int32_t hash = elem_hash ((const char *) name, name_len); int32_t elem;
int32_t elem = hash % table_size;
for (elem = 0; elem < table_size; elem++)
if (symb_table[2 * elem] != 0) if (symb_table[2 * elem] != 0)
{ {
int32_t second = hash % (table_size - 2) + 1; int32_t idx = symb_table[2 * elem + 1];
/* Skip the name of collating element name. */
do idx += 1 + extra[idx];
{ if (/* Compare the length of the name. */
/* First compare the hashing value. */ name_len == extra[idx]
if (symb_table[2 * elem] == hash
/* Compare the length of the name. */
&& name_len == extra[symb_table[2 * elem + 1]]
/* Compare the name. */ /* Compare the name. */
&& memcmp (name, &extra[symb_table[2 * elem + 1] + 1], && memcmp (name, &extra[idx + 1], name_len) == 0)
name_len) == 0)
{
/* Yep, this is the entry. */ /* Yep, this is the entry. */
break;
}
/* Next entry. */
elem += second;
}
while (symb_table[2 * elem] != 0);
}
return elem; return elem;
} }
return -1;
}
/* Local function for parse_bracket_exp used in _LIBC environment. /* Local function for parse_bracket_exp used in _LIBC environment.
Look up the collation sequence value of BR_ELEM. Look up the collation sequence value of BR_ELEM.
@@ -2770,8 +2831,7 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token,
auto inline unsigned int auto inline unsigned int
__attribute ((always_inline)) __attribute ((always_inline))
lookup_collation_sequence_value (br_elem) lookup_collation_sequence_value (bracket_elem_t *br_elem)
bracket_elem_t *br_elem;
{ {
if (br_elem->type == SB_CHAR) if (br_elem->type == SB_CHAR)
{ {
@@ -2799,7 +2859,7 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token,
int32_t elem, idx; int32_t elem, idx;
elem = seek_collating_symbol_entry (br_elem->opr.name, elem = seek_collating_symbol_entry (br_elem->opr.name,
sym_name_len); sym_name_len);
if (symb_table[2 * elem] != 0) if (elem != -1)
{ {
/* We found the entry. */ /* We found the entry. */
idx = symb_table[2 * elem + 1]; idx = symb_table[2 * elem + 1];
@@ -2817,7 +2877,7 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token,
/* Return the collation sequence value. */ /* Return the collation sequence value. */
return *(unsigned int *) (extra + idx); 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 /* No valid character. Match it as a single byte
character. */ character. */
@@ -2839,11 +2899,8 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token,
auto inline reg_errcode_t auto inline reg_errcode_t
__attribute ((always_inline)) __attribute ((always_inline))
build_range_exp (sbcset, mbcset, range_alloc, start_elem, end_elem) build_range_exp (bitset_t sbcset, re_charset_t *mbcset, int *range_alloc,
re_charset_t *mbcset; bracket_elem_t *start_elem, bracket_elem_t *end_elem)
int *range_alloc;
bitset_t sbcset;
bracket_elem_t *start_elem, *end_elem;
{ {
unsigned int ch; unsigned int ch;
uint32_t start_collseq; uint32_t start_collseq;
@@ -2922,25 +2979,22 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token,
auto inline reg_errcode_t auto inline reg_errcode_t
__attribute ((always_inline)) __attribute ((always_inline))
build_collating_symbol (sbcset, mbcset, coll_sym_alloc, name) build_collating_symbol (bitset_t sbcset, re_charset_t *mbcset,
re_charset_t *mbcset; int *coll_sym_alloc, const unsigned char *name)
int *coll_sym_alloc;
bitset_t sbcset;
const unsigned char *name;
{ {
int32_t elem, idx; int32_t elem, idx;
size_t name_len = strlen ((const char *) name); size_t name_len = strlen ((const char *) name);
if (nrules != 0) if (nrules != 0)
{ {
elem = seek_collating_symbol_entry (name, name_len); elem = seek_collating_symbol_entry (name, name_len);
if (symb_table[2 * elem] != 0) if (elem != -1)
{ {
/* We found the entry. */ /* We found the entry. */
idx = symb_table[2 * elem + 1]; idx = symb_table[2 * elem + 1];
/* Skip the name of collating element name. */ /* Skip the name of collating element name. */
idx += 1 + extra[idx]; 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 /* No valid character, treat it as a normal
character. */ character. */
@@ -3020,6 +3074,10 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token,
if (BE (sbcset == NULL, 0)) if (BE (sbcset == NULL, 0))
#endif /* RE_ENABLE_I18N */ #endif /* RE_ENABLE_I18N */
{ {
re_free (sbcset);
#ifdef RE_ENABLE_I18N
re_free (mbcset);
#endif
*err = REG_ESPACE; *err = REG_ESPACE;
return NULL; return NULL;
} }
@@ -3377,8 +3435,6 @@ build_equiv_class (bitset_t sbcset, const unsigned char *name)
int32_t idx1, idx2; int32_t idx1, idx2;
unsigned int ch; unsigned int ch;
size_t len; size_t len;
/* This #include defines a local function! */
# include <locale/weight.h>
/* Calculate the index for equivalence class. */ /* Calculate the index for equivalence class. */
cp = name; cp = name;
table = (const int32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB); table = (const int32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB);
@@ -3388,19 +3444,18 @@ build_equiv_class (bitset_t sbcset, const unsigned char *name)
_NL_COLLATE_EXTRAMB); _NL_COLLATE_EXTRAMB);
indirect = (const int32_t *) _NL_CURRENT (LC_COLLATE, indirect = (const int32_t *) _NL_CURRENT (LC_COLLATE,
_NL_COLLATE_INDIRECTMB); _NL_COLLATE_INDIRECTMB);
idx1 = findidx (&cp); idx1 = findidx (table, indirect, extra, &cp, -1);
if (BE (idx1 == 0 || cp < name + strlen ((const char *) name), 0)) if (BE (idx1 == 0 || *cp != '\0', 0))
/* This isn't a valid character. */ /* This isn't a valid character. */
return REG_ECOLLATE; return REG_ECOLLATE;
/* Build single byte matcing table for this equivalence class. */ /* Build single byte matcing table for this equivalence class. */
char_buf[1] = (unsigned char) '\0';
len = weights[idx1 & 0xffffff]; len = weights[idx1 & 0xffffff];
for (ch = 0; ch < SBC_MAX; ++ch) for (ch = 0; ch < SBC_MAX; ++ch)
{ {
char_buf[0] = ch; char_buf[0] = ch;
cp = char_buf; cp = char_buf;
idx2 = findidx (&cp); idx2 = findidx (table, indirect, extra, &cp, 1);
/* /*
idx2 = table[ch]; idx2 = table[ch];
*/ */
@@ -3670,7 +3725,7 @@ fetch_number (re_string_t *input, re_token_t *token, reg_syntax_t syntax)
} }
return num; return num;
} }
#ifdef RE_ENABLE_I18N #ifdef RE_ENABLE_I18N
static void static void
free_charset (re_charset_t *cset) free_charset (re_charset_t *cset)
@@ -3686,7 +3741,7 @@ free_charset (re_charset_t *cset)
re_free (cset); re_free (cset);
} }
#endif /* RE_ENABLE_I18N */ #endif /* RE_ENABLE_I18N */
/* Functions for binary tree operation. */ /* Functions for binary tree operation. */
/* Create a tree node. */ /* Create a tree node. */
+6 -4
View File
@@ -1,5 +1,5 @@
/* Extended regular expression matching and search library. /* Extended regular expression matching and search library.
Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc. Copyright (C) 2002-2014 Free Software Foundation, Inc.
This file is part of the GNU C Library. This file is part of the GNU C Library.
Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>. Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>.
@@ -14,9 +14,8 @@
Lesser General Public License for more details. Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free License along with the GNU C Library; if not, see
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA <http://www.gnu.org/licenses/>. */
02111-1307 USA. */
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
#include "config.h" #include "config.h"
@@ -57,6 +56,9 @@
#undefs RE_DUP_MAX and sets it to the right value. */ #undefs RE_DUP_MAX and sets it to the right value. */
#include <limits.h> #include <limits.h>
/* This header defines the MIN and MAX macros. */
#include <sys/param.h>
#include <regex.h> #include <regex.h>
#include "regex_internal.h" #include "regex_internal.h"
@@ -1,5 +1,5 @@
/* Extended regular expression matching and search library. /* Extended regular expression matching and search library.
Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. Copyright (C) 2002-2014 Free Software Foundation, Inc.
This file is part of the GNU C Library. This file is part of the GNU C Library.
Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>. Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>.
@@ -14,9 +14,8 @@
Lesser General Public License for more details. Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free License along with the GNU C Library; if not, see
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA <http://www.gnu.org/licenses/>. */
02111-1307 USA. */
static void re_string_construct_common (const char *str, int len, static void re_string_construct_common (const char *str, int len,
re_string_t *pstr, re_string_t *pstr,
@@ -36,7 +35,7 @@ static re_dfastate_t *create_cd_newstate (const re_dfa_t *dfa,
re_string_reconstruct before using the object. */ re_string_reconstruct before using the object. */
static reg_errcode_t static reg_errcode_t
internal_function internal_function __attribute_warn_unused_result__
re_string_allocate (re_string_t *pstr, const char *str, int len, int init_len, re_string_allocate (re_string_t *pstr, const char *str, int len, int init_len,
RE_TRANSLATE_TYPE trans, int icase, const re_dfa_t *dfa) RE_TRANSLATE_TYPE trans, int icase, const re_dfa_t *dfa)
{ {
@@ -64,7 +63,7 @@ re_string_allocate (re_string_t *pstr, const char *str, int len, int init_len,
/* This function allocate the buffers, and initialize them. */ /* This function allocate the buffers, and initialize them. */
static reg_errcode_t static reg_errcode_t
internal_function internal_function __attribute_warn_unused_result__
re_string_construct (re_string_t *pstr, const char *str, int len, re_string_construct (re_string_t *pstr, const char *str, int len,
RE_TRANSLATE_TYPE trans, int icase, const re_dfa_t *dfa) RE_TRANSLATE_TYPE trans, int icase, const re_dfa_t *dfa)
{ {
@@ -127,13 +126,20 @@ re_string_construct (re_string_t *pstr, const char *str, int len,
/* Helper functions for re_string_allocate, and re_string_construct. */ /* Helper functions for re_string_allocate, and re_string_construct. */
static reg_errcode_t static reg_errcode_t
internal_function internal_function __attribute_warn_unused_result__
re_string_realloc_buffers (re_string_t *pstr, int new_buf_len) re_string_realloc_buffers (re_string_t *pstr, int new_buf_len)
{ {
#ifdef RE_ENABLE_I18N #ifdef RE_ENABLE_I18N
if (pstr->mb_cur_max > 1) if (pstr->mb_cur_max > 1)
{ {
wint_t *new_wcs = re_realloc (pstr->wcs, wint_t, new_buf_len); wint_t *new_wcs;
/* Avoid overflow in realloc. */
const size_t max_object_size = MAX (sizeof (wint_t), sizeof (int));
if (BE (SIZE_MAX / max_object_size < new_buf_len, 0))
return REG_ESPACE;
new_wcs = re_realloc (pstr->wcs, wint_t, new_buf_len);
if (BE (new_wcs == NULL, 0)) if (BE (new_wcs == NULL, 0))
return REG_ESPACE; return REG_ESPACE;
pstr->wcs = new_wcs; pstr->wcs = new_wcs;
@@ -230,13 +236,8 @@ build_wcs_buffer (re_string_t *pstr)
else else
p = (const char *) pstr->raw_mbs + pstr->raw_mbs_idx + byte_idx; p = (const char *) pstr->raw_mbs + pstr->raw_mbs_idx + byte_idx;
mbclen = __mbrtowc (&wc, p, remain_len, &pstr->cur_state); mbclen = __mbrtowc (&wc, p, remain_len, &pstr->cur_state);
if (BE (mbclen == (size_t) -2, 0)) if (BE (mbclen == (size_t) -1 || mbclen == 0
{ || (mbclen == (size_t) -2 && pstr->bufs_len >= pstr->len), 0))
/* The buffer doesn't have enough space, finish to build. */
pstr->cur_state = prev_st;
break;
}
else if (BE (mbclen == (size_t) -1 || mbclen == 0, 0))
{ {
/* We treat these cases as a singlebyte character. */ /* We treat these cases as a singlebyte character. */
mbclen = 1; mbclen = 1;
@@ -245,6 +246,12 @@ build_wcs_buffer (re_string_t *pstr)
wc = pstr->trans[wc]; wc = pstr->trans[wc];
pstr->cur_state = prev_st; pstr->cur_state = prev_st;
} }
else if (BE (mbclen == (size_t) -2, 0))
{
/* The buffer doesn't have enough space, finish to build. */
pstr->cur_state = prev_st;
break;
}
/* Write wide character and padding. */ /* Write wide character and padding. */
pstr->wcs[byte_idx++] = wc; pstr->wcs[byte_idx++] = wc;
@@ -260,7 +267,7 @@ build_wcs_buffer (re_string_t *pstr)
but for REG_ICASE. */ but for REG_ICASE. */
static reg_errcode_t static reg_errcode_t
internal_function internal_function __attribute_warn_unused_result__
build_wcs_upper_buffer (re_string_t *pstr) build_wcs_upper_buffer (re_string_t *pstr)
{ {
mbstate_t prev_st; mbstate_t prev_st;
@@ -327,9 +334,11 @@ build_wcs_upper_buffer (re_string_t *pstr)
for (remain_len = byte_idx + mbclen - 1; byte_idx < remain_len ;) for (remain_len = byte_idx + mbclen - 1; byte_idx < remain_len ;)
pstr->wcs[byte_idx++] = WEOF; pstr->wcs[byte_idx++] = WEOF;
} }
else if (mbclen == (size_t) -1 || mbclen == 0) else if (mbclen == (size_t) -1 || mbclen == 0
|| (mbclen == (size_t) -2 && pstr->bufs_len >= pstr->len))
{ {
/* It is an invalid character or '\0'. Just use the byte. */ /* It is an invalid character, an incomplete character
at the end of the string, or '\0'. Just use the byte. */
int ch = pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx]; int ch = pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx];
pstr->mbs[byte_idx] = ch; pstr->mbs[byte_idx] = ch;
/* And also cast it to wide char. */ /* And also cast it to wide char. */
@@ -442,7 +451,8 @@ build_wcs_upper_buffer (re_string_t *pstr)
for (remain_len = byte_idx + mbclen - 1; byte_idx < remain_len ;) for (remain_len = byte_idx + mbclen - 1; byte_idx < remain_len ;)
pstr->wcs[byte_idx++] = WEOF; pstr->wcs[byte_idx++] = WEOF;
} }
else if (mbclen == (size_t) -1 || mbclen == 0) else if (mbclen == (size_t) -1 || mbclen == 0
|| (mbclen == (size_t) -2 && pstr->bufs_len >= pstr->len))
{ {
/* It is an invalid character or '\0'. Just use the byte. */ /* It is an invalid character or '\0'. Just use the byte. */
int ch = pstr->raw_mbs[pstr->raw_mbs_idx + src_idx]; int ch = pstr->raw_mbs[pstr->raw_mbs_idx + src_idx];
@@ -482,18 +492,18 @@ re_string_skip_chars (re_string_t *pstr, int new_raw_idx, wint_t *last_wc)
mbstate_t prev_st; mbstate_t prev_st;
int rawbuf_idx; int rawbuf_idx;
size_t mbclen; size_t mbclen;
wchar_t wc = WEOF; wint_t wc = WEOF;
/* Skip the characters which are not necessary to check. */ /* Skip the characters which are not necessary to check. */
for (rawbuf_idx = pstr->raw_mbs_idx + pstr->valid_raw_len; for (rawbuf_idx = pstr->raw_mbs_idx + pstr->valid_raw_len;
rawbuf_idx < new_raw_idx;) rawbuf_idx < new_raw_idx;)
{ {
int remain_len; wchar_t wc2;
remain_len = pstr->len - rawbuf_idx; int remain_len = pstr->raw_len - rawbuf_idx;
prev_st = pstr->cur_state; prev_st = pstr->cur_state;
mbclen = __mbrtowc (&wc, (const char *) pstr->raw_mbs + rawbuf_idx, mbclen = __mbrtowc (&wc2, (const char *) pstr->raw_mbs + rawbuf_idx,
remain_len, &pstr->cur_state); remain_len, &pstr->cur_state);
if (BE (mbclen == (size_t) -2 || mbclen == (size_t) -1 || mbclen == 0, 0)) if (BE ((ssize_t) mbclen <= 0, 0))
{ {
/* We treat these cases as a single byte character. */ /* We treat these cases as a single byte character. */
if (mbclen == 0 || remain_len == 0) if (mbclen == 0 || remain_len == 0)
@@ -503,10 +513,12 @@ re_string_skip_chars (re_string_t *pstr, int new_raw_idx, wint_t *last_wc)
mbclen = 1; mbclen = 1;
pstr->cur_state = prev_st; pstr->cur_state = prev_st;
} }
else
wc = (wint_t) wc2;
/* Then proceed the next character. */ /* Then proceed the next character. */
rawbuf_idx += mbclen; rawbuf_idx += mbclen;
} }
*last_wc = (wint_t) wc; *last_wc = wc;
return rawbuf_idx; return rawbuf_idx;
} }
#endif /* RE_ENABLE_I18N */ #endif /* RE_ENABLE_I18N */
@@ -559,7 +571,7 @@ re_string_translate_buffer (re_string_t *pstr)
convert to upper case in case of REG_ICASE, apply translation. */ convert to upper case in case of REG_ICASE, apply translation. */
static reg_errcode_t static reg_errcode_t
internal_function internal_function __attribute_warn_unused_result__
re_string_reconstruct (re_string_t *pstr, int idx, int eflags) re_string_reconstruct (re_string_t *pstr, int idx, int eflags)
{ {
int offset = idx - pstr->raw_mbs_idx; int offset = idx - pstr->raw_mbs_idx;
@@ -667,7 +679,7 @@ re_string_reconstruct (re_string_t *pstr, int idx, int eflags)
pstr->valid_len - offset); pstr->valid_len - offset);
pstr->valid_len -= offset; pstr->valid_len -= offset;
pstr->valid_raw_len -= offset; pstr->valid_raw_len -= offset;
#if DEBUG #if defined DEBUG && DEBUG
assert (pstr->valid_len > 0); assert (pstr->valid_len > 0);
#endif #endif
} }
@@ -694,7 +706,7 @@ re_string_reconstruct (re_string_t *pstr, int idx, int eflags)
if (pstr->is_utf8) if (pstr->is_utf8)
{ {
const unsigned char *raw, *p, *q, *end; const unsigned char *raw, *p, *end;
/* Special case UTF-8. Multi-byte chars start with any /* Special case UTF-8. Multi-byte chars start with any
byte other than 0x80 - 0xbf. */ byte other than 0x80 - 0xbf. */
@@ -723,18 +735,18 @@ re_string_reconstruct (re_string_t *pstr, int idx, int eflags)
unsigned char buf[6]; unsigned char buf[6];
size_t mbclen; size_t mbclen;
q = p; const unsigned char *pp = p;
if (BE (pstr->trans != NULL, 0)) if (BE (pstr->trans != NULL, 0))
{ {
int i = mlen < 6 ? mlen : 6; int i = mlen < 6 ? mlen : 6;
while (--i >= 0) while (--i >= 0)
buf[i] = pstr->trans[p[i]]; buf[i] = pstr->trans[p[i]];
q = buf; pp = buf;
} }
/* XXX Don't use mbrtowc, we know which conversion /* XXX Don't use mbrtowc, we know which conversion
to use (UTF-8 -> UCS4). */ to use (UTF-8 -> UCS4). */
memset (&cur_state, 0, sizeof (cur_state)); memset (&cur_state, 0, sizeof (cur_state));
mbclen = __mbrtowc (&wc2, (const char *) p, mlen, mbclen = __mbrtowc (&wc2, (const char *) pp, mlen,
&cur_state); &cur_state);
if (raw + offset - p <= mbclen if (raw + offset - p <= mbclen
&& mbclen < (size_t) -2) && mbclen < (size_t) -2)
@@ -855,7 +867,7 @@ re_string_peek_byte_case (const re_string_t *pstr, int idx)
} }
static unsigned char static unsigned char
internal_function __attribute ((pure)) internal_function
re_string_fetch_byte_case (re_string_t *pstr) re_string_fetch_byte_case (re_string_t *pstr)
{ {
if (BE (!pstr->mbs_allocated, 1)) if (BE (!pstr->mbs_allocated, 1))
@@ -924,7 +936,7 @@ re_string_context_at (const re_string_t *input, int idx, int eflags)
int wc_idx = idx; int wc_idx = idx;
while(input->wcs[wc_idx] == WEOF) while(input->wcs[wc_idx] == WEOF)
{ {
#ifdef DEBUG #if defined DEBUG && DEBUG
/* It must not happen. */ /* It must not happen. */
assert (wc_idx >= 0); assert (wc_idx >= 0);
#endif #endif
@@ -951,7 +963,7 @@ re_string_context_at (const re_string_t *input, int idx, int eflags)
/* Functions for set operation. */ /* Functions for set operation. */
static reg_errcode_t static reg_errcode_t
internal_function internal_function __attribute_warn_unused_result__
re_node_set_alloc (re_node_set *set, int size) re_node_set_alloc (re_node_set *set, int size)
{ {
set->alloc = size; set->alloc = size;
@@ -963,7 +975,7 @@ re_node_set_alloc (re_node_set *set, int size)
} }
static reg_errcode_t static reg_errcode_t
internal_function internal_function __attribute_warn_unused_result__
re_node_set_init_1 (re_node_set *set, int elem) re_node_set_init_1 (re_node_set *set, int elem)
{ {
set->alloc = 1; set->alloc = 1;
@@ -979,7 +991,7 @@ re_node_set_init_1 (re_node_set *set, int elem)
} }
static reg_errcode_t static reg_errcode_t
internal_function internal_function __attribute_warn_unused_result__
re_node_set_init_2 (re_node_set *set, int elem1, int elem2) re_node_set_init_2 (re_node_set *set, int elem1, int elem2)
{ {
set->alloc = 2; set->alloc = 2;
@@ -1009,7 +1021,7 @@ re_node_set_init_2 (re_node_set *set, int elem1, int elem2)
} }
static reg_errcode_t static reg_errcode_t
internal_function internal_function __attribute_warn_unused_result__
re_node_set_init_copy (re_node_set *dest, const re_node_set *src) re_node_set_init_copy (re_node_set *dest, const re_node_set *src)
{ {
dest->nelem = src->nelem; dest->nelem = src->nelem;
@@ -1034,7 +1046,7 @@ re_node_set_init_copy (re_node_set *dest, const re_node_set *src)
Note: We assume dest->elems is NULL, when dest->alloc is 0. */ Note: We assume dest->elems is NULL, when dest->alloc is 0. */
static reg_errcode_t static reg_errcode_t
internal_function internal_function __attribute_warn_unused_result__
re_node_set_add_intersect (re_node_set *dest, const re_node_set *src1, re_node_set_add_intersect (re_node_set *dest, const re_node_set *src1,
const re_node_set *src2) const re_node_set *src2)
{ {
@@ -1125,7 +1137,7 @@ re_node_set_add_intersect (re_node_set *dest, const re_node_set *src1,
DEST. Return value indicate the error code or REG_NOERROR if succeeded. */ DEST. Return value indicate the error code or REG_NOERROR if succeeded. */
static reg_errcode_t static reg_errcode_t
internal_function internal_function __attribute_warn_unused_result__
re_node_set_init_union (re_node_set *dest, const re_node_set *src1, re_node_set_init_union (re_node_set *dest, const re_node_set *src1,
const re_node_set *src2) const re_node_set *src2)
{ {
@@ -1178,7 +1190,7 @@ re_node_set_init_union (re_node_set *dest, const re_node_set *src1,
DEST. Return value indicate the error code or REG_NOERROR if succeeded. */ DEST. Return value indicate the error code or REG_NOERROR if succeeded. */
static reg_errcode_t static reg_errcode_t
internal_function internal_function __attribute_warn_unused_result__
re_node_set_merge (re_node_set *dest, const re_node_set *src) re_node_set_merge (re_node_set *dest, const re_node_set *src)
{ {
int is, id, sbase, delta; int is, id, sbase, delta;
@@ -1261,7 +1273,7 @@ re_node_set_merge (re_node_set *dest, const re_node_set *src)
return -1 if an error is occured, return 1 otherwise. */ return -1 if an error is occured, return 1 otherwise. */
static int static int
internal_function internal_function __attribute_warn_unused_result__
re_node_set_insert (re_node_set *set, int elem) re_node_set_insert (re_node_set *set, int elem)
{ {
int idx; int idx;
@@ -1318,7 +1330,7 @@ re_node_set_insert (re_node_set *set, int elem)
Return -1 if an error is occured, return 1 otherwise. */ Return -1 if an error is occured, return 1 otherwise. */
static int static int
internal_function internal_function __attribute_warn_unused_result__
re_node_set_insert_last (re_node_set *set, int elem) re_node_set_insert_last (re_node_set *set, int elem)
{ {
/* Realloc if we need. */ /* Realloc if we need. */
@@ -1404,8 +1416,11 @@ re_dfa_add_node (re_dfa_t *dfa, re_token_t token)
re_node_set *new_edests, *new_eclosures; re_node_set *new_edests, *new_eclosures;
re_token_t *new_nodes; re_token_t *new_nodes;
/* Avoid overflows. */ /* Avoid overflows in realloc. */
if (BE (new_nodes_alloc < dfa->nodes_alloc, 0)) const size_t max_object_size = MAX (sizeof (re_token_t),
MAX (sizeof (re_node_set),
sizeof (int)));
if (BE (SIZE_MAX / max_object_size < new_nodes_alloc, 0))
return -1; return -1;
new_nodes = re_realloc (dfa->nodes, re_token_t, new_nodes_alloc); new_nodes = re_realloc (dfa->nodes, re_token_t, new_nodes_alloc);
@@ -1458,7 +1473,7 @@ calc_state_hash (const re_node_set *nodes, unsigned int context)
optimization. */ optimization. */
static re_dfastate_t * static re_dfastate_t *
internal_function internal_function __attribute_warn_unused_result__
re_acquire_state (reg_errcode_t *err, const re_dfa_t *dfa, re_acquire_state (reg_errcode_t *err, const re_dfa_t *dfa,
const re_node_set *nodes) const re_node_set *nodes)
{ {
@@ -1502,7 +1517,7 @@ re_acquire_state (reg_errcode_t *err, const re_dfa_t *dfa,
optimization. */ optimization. */
static re_dfastate_t * static re_dfastate_t *
internal_function internal_function __attribute_warn_unused_result__
re_acquire_state_context (reg_errcode_t *err, const re_dfa_t *dfa, re_acquire_state_context (reg_errcode_t *err, const re_dfa_t *dfa,
const re_node_set *nodes, unsigned int context) const re_node_set *nodes, unsigned int context)
{ {
@@ -1539,6 +1554,7 @@ re_acquire_state_context (reg_errcode_t *err, const re_dfa_t *dfa,
indicates the error code if failed. */ indicates the error code if failed. */
static reg_errcode_t static reg_errcode_t
__attribute_warn_unused_result__
register_state (const re_dfa_t *dfa, re_dfastate_t *newstate, register_state (const re_dfa_t *dfa, re_dfastate_t *newstate,
unsigned int hash) unsigned int hash)
{ {
@@ -1554,7 +1570,8 @@ register_state (const re_dfa_t *dfa, re_dfastate_t *newstate,
{ {
int elem = newstate->nodes.elems[i]; int elem = newstate->nodes.elems[i];
if (!IS_EPSILON_NODE (dfa->nodes[elem].type)) if (!IS_EPSILON_NODE (dfa->nodes[elem].type))
re_node_set_insert_last (&newstate->non_eps_nodes, elem); if (re_node_set_insert_last (&newstate->non_eps_nodes, elem) < 0)
return REG_ESPACE;
} }
spot = dfa->state_table + (hash & dfa->state_hash_mask); spot = dfa->state_table + (hash & dfa->state_hash_mask);
@@ -1592,7 +1609,7 @@ free_state (re_dfastate_t *state)
Return the new state if succeeded, otherwise return NULL. */ Return the new state if succeeded, otherwise return NULL. */
static re_dfastate_t * static re_dfastate_t *
internal_function internal_function __attribute_warn_unused_result__
create_ci_newstate (const re_dfa_t *dfa, const re_node_set *nodes, create_ci_newstate (const re_dfa_t *dfa, const re_node_set *nodes,
unsigned int hash) unsigned int hash)
{ {
@@ -1642,7 +1659,7 @@ create_ci_newstate (const re_dfa_t *dfa, const re_node_set *nodes,
Return the new state if succeeded, otherwise return NULL. */ Return the new state if succeeded, otherwise return NULL. */
static re_dfastate_t * static re_dfastate_t *
internal_function internal_function __attribute_warn_unused_result__
create_cd_newstate (const re_dfa_t *dfa, const re_node_set *nodes, create_cd_newstate (const re_dfa_t *dfa, const re_node_set *nodes,
unsigned int context, unsigned int hash) unsigned int context, unsigned int hash)
{ {
@@ -1691,7 +1708,9 @@ create_cd_newstate (const re_dfa_t *dfa, const re_node_set *nodes,
free_state (newstate); free_state (newstate);
return NULL; return NULL;
} }
re_node_set_init_copy (newstate->entrance_nodes, nodes); if (re_node_set_init_copy (newstate->entrance_nodes, nodes)
!= REG_NOERROR)
return NULL;
nctx_nodes = 0; nctx_nodes = 0;
newstate->has_constraint = 1; newstate->has_constraint = 1;
} }
@@ -1,5 +1,5 @@
/* Extended regular expression matching and search library. /* Extended regular expression matching and search library.
Copyright (C) 2002-2005, 2007, 2008 Free Software Foundation, Inc. Copyright (C) 2002-2014 Free Software Foundation, Inc.
This file is part of the GNU C Library. This file is part of the GNU C Library.
Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>. Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>.
@@ -14,9 +14,8 @@
Lesser General Public License for more details. Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free License along with the GNU C Library; if not, see
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA <http://www.gnu.org/licenses/>. */
02111-1307 USA. */
#ifndef _REGEX_INTERNAL_H #ifndef _REGEX_INTERNAL_H
#define _REGEX_INTERNAL_H 1 #define _REGEX_INTERNAL_H 1
@@ -74,7 +73,7 @@
# ifdef _LIBC # ifdef _LIBC
# undef gettext # undef gettext
# define gettext(msgid) \ # define gettext(msgid) \
INTUSE(__dcgettext) (_libc_intl_domainname, msgid, LC_MESSAGES) __dcgettext (_libc_intl_domainname, msgid, LC_MESSAGES)
# endif # endif
#else #else
# define gettext(msgid) (msgid) # define gettext(msgid) (msgid)
@@ -91,7 +90,7 @@
# define SIZE_MAX ((size_t) -1) # define SIZE_MAX ((size_t) -1)
#endif #endif
#if (defined MB_CUR_MAX && HAVE_LOCALE_H && HAVE_WCTYPE_H && HAVE_WCHAR_H && HAVE_WCRTOMB && HAVE_MBRTOWC && HAVE_WCSCOLL) || _LIBC #if (defined MB_CUR_MAX && HAVE_WCTYPE_H && HAVE_ISWCTYPE) || _LIBC
# define RE_ENABLE_I18N # define RE_ENABLE_I18N
#endif #endif
@@ -99,7 +98,6 @@
# define BE(expr, val) __builtin_expect (expr, val) # define BE(expr, val) __builtin_expect (expr, val)
#else #else
# define BE(expr, val) (expr) # define BE(expr, val) (expr)
# define inline
#endif #endif
/* Number of single byte character. */ /* Number of single byte character. */
@@ -123,10 +121,8 @@
# define attribute_hidden # define attribute_hidden
#endif /* not _LIBC */ #endif /* not _LIBC */
#ifdef __GNUC__ #if __GNUC__ < 3 + (__GNUC_MINOR__ < 1)
# define __attribute(arg) __attribute__ (arg) # define __attribute__(arg)
#else
# define __attribute(arg)
#endif #endif
extern const char __re_error_msgid[] attribute_hidden; extern const char __re_error_msgid[] attribute_hidden;
@@ -380,10 +376,11 @@ typedef struct re_dfa_t re_dfa_t;
#ifndef _LIBC #ifndef _LIBC
# ifdef __i386__ # ifdef __i386__
# define internal_function __attribute ((regparm (3), stdcall)) # define internal_function __attribute__ ((regparm (3), stdcall))
# else # else
# define internal_function # define internal_function
# endif # endif
# define __attribute_warn_unused_result__
#endif #endif
#ifndef NOT_IN_libc #ifndef NOT_IN_libc
@@ -399,7 +396,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 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, static unsigned int re_string_context_at (const re_string_t *input, int idx,
int eflags) int eflags)
internal_function __attribute ((pure)); internal_function __attribute__ ((pure));
#endif #endif
#define re_string_peek_byte(pstr, offset) \ #define re_string_peek_byte(pstr, offset) \
((pstr)->mbs[(pstr)->cur_idx + offset]) ((pstr)->mbs[(pstr)->cur_idx + offset])
@@ -664,7 +661,7 @@ struct re_dfa_t
(re_node_set_remove_at (set, re_node_set_contains (set, id) - 1)) (re_node_set_remove_at (set, re_node_set_contains (set, id) - 1))
#define re_node_set_empty(p) ((p)->nelem = 0) #define re_node_set_empty(p) ((p)->nelem = 0)
#define re_node_set_free(set) re_free ((set)->elems) #define re_node_set_free(set) re_free ((set)->elems)
typedef enum typedef enum
{ {
@@ -688,7 +685,7 @@ typedef struct
/* Inline functions for bitset operation. */ /* Inline functions for bitset operation. */
static inline void static void __attribute__ ((unused))
bitset_not (bitset_t set) bitset_not (bitset_t set)
{ {
int bitset_i; int bitset_i;
@@ -696,7 +693,7 @@ bitset_not (bitset_t set)
set[bitset_i] = ~set[bitset_i]; set[bitset_i] = ~set[bitset_i];
} }
static inline void static void __attribute__ ((unused))
bitset_merge (bitset_t dest, const bitset_t src) bitset_merge (bitset_t dest, const bitset_t src)
{ {
int bitset_i; int bitset_i;
@@ -704,7 +701,7 @@ bitset_merge (bitset_t dest, const bitset_t src)
dest[bitset_i] |= src[bitset_i]; dest[bitset_i] |= src[bitset_i];
} }
static inline void static void __attribute__ ((unused))
bitset_mask (bitset_t dest, const bitset_t src) bitset_mask (bitset_t dest, const bitset_t src)
{ {
int bitset_i; int bitset_i;
@@ -714,8 +711,8 @@ bitset_mask (bitset_t dest, const bitset_t src)
#ifdef RE_ENABLE_I18N #ifdef RE_ENABLE_I18N
/* Inline functions for re_string. */ /* Inline functions for re_string. */
static inline int static int
internal_function __attribute ((pure)) internal_function __attribute__ ((pure, unused))
re_string_char_size_at (const re_string_t *pstr, int idx) re_string_char_size_at (const re_string_t *pstr, int idx)
{ {
int byte_idx; int byte_idx;
@@ -727,8 +724,8 @@ re_string_char_size_at (const re_string_t *pstr, int idx)
return byte_idx; return byte_idx;
} }
static inline wint_t static wint_t
internal_function __attribute ((pure)) internal_function __attribute__ ((pure, unused))
re_string_wchar_at (const re_string_t *pstr, int idx) re_string_wchar_at (const re_string_t *pstr, int idx)
{ {
if (pstr->mb_cur_max == 1) if (pstr->mb_cur_max == 1)
@@ -737,15 +734,17 @@ re_string_wchar_at (const re_string_t *pstr, int idx)
} }
# ifndef NOT_IN_libc # ifndef NOT_IN_libc
# ifdef _LIBC
# include <locale/weight.h>
# endif
static int static int
internal_function __attribute ((pure)) internal_function __attribute__ ((pure, unused))
re_string_elem_size_at (const re_string_t *pstr, int idx) re_string_elem_size_at (const re_string_t *pstr, int idx)
{ {
# ifdef _LIBC # ifdef _LIBC
const unsigned char *p, *extra; const unsigned char *p, *extra;
const int32_t *table, *indirect; const int32_t *table, *indirect;
int32_t tmp;
# include <locale/weight.h>
uint_fast32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); uint_fast32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
if (nrules != 0) if (nrules != 0)
@@ -756,7 +755,7 @@ re_string_elem_size_at (const re_string_t *pstr, int idx)
indirect = (const int32_t *) _NL_CURRENT (LC_COLLATE, indirect = (const int32_t *) _NL_CURRENT (LC_COLLATE,
_NL_COLLATE_INDIRECTMB); _NL_COLLATE_INDIRECTMB);
p = pstr->mbs + idx; p = pstr->mbs + idx;
tmp = findidx (&p); findidx (table, indirect, extra, &p, pstr->len - idx);
return p - pstr->mbs - idx; return p - pstr->mbs - idx;
} }
else else
+92 -46
View File
@@ -1,5 +1,5 @@
/* Extended regular expression matching and search library. /* Extended regular expression matching and search library.
Copyright (C) 2002, 2003, 2004, 2005, 2007, 2009 Free Software Foundation, Inc. Copyright (C) 2002-2014 Free Software Foundation, Inc.
This file is part of the GNU C Library. This file is part of the GNU C Library.
Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>. Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>.
@@ -14,9 +14,10 @@
Lesser General Public License for more details. Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free License along with the GNU C Library; if not, see
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA <http://www.gnu.org/licenses/>. */
02111-1307 USA. */
#include <stdint.h>
static reg_errcode_t match_ctx_init (re_match_context_t *cache, int eflags, static reg_errcode_t match_ctx_init (re_match_context_t *cache, int eflags,
int n) internal_function; int n) internal_function;
@@ -198,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, static int check_node_accept (const re_match_context_t *mctx,
const re_token_t *node, int idx) const re_token_t *node, int idx)
internal_function; 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; internal_function;
/* Entry point for POSIX code. */ /* Entry point for POSIX code. */
@@ -368,16 +369,16 @@ re_search_2_stub (bufp, string1, length1, string2, length2, start, range, regs,
const char *str; const char *str;
int rval; int rval;
int len = length1 + length2; int len = length1 + length2;
int free_str = 0; char *s = NULL;
if (BE (length1 < 0 || length2 < 0 || stop < 0, 0)) if (BE (length1 < 0 || length2 < 0 || stop < 0 || len < length1, 0))
return -2; return -2;
/* Concatenate the strings. */ /* Concatenate the strings. */
if (length2 > 0) if (length2 > 0)
if (length1 > 0) if (length1 > 0)
{ {
char *s = re_malloc (char, len); s = re_malloc (char, len);
if (BE (s == NULL, 0)) if (BE (s == NULL, 0))
return -2; return -2;
@@ -388,17 +389,14 @@ re_search_2_stub (bufp, string1, length1, string2, length2, start, range, regs,
memcpy (s + length1, string2, length2); memcpy (s + length1, string2, length2);
#endif #endif
str = s; str = s;
free_str = 1;
} }
else else
str = string2; str = string2;
else else
str = string1; str = string1;
rval = re_search_stub (bufp, str, len, start, range, stop, regs, rval = re_search_stub (bufp, str, len, start, range, stop, regs, ret_len);
ret_len); re_free (s);
if (free_str)
re_free ((char *) str);
return rval; return rval;
} }
@@ -512,9 +510,14 @@ re_copy_regs (regs, pmatch, nregs, regs_allocated)
if (regs_allocated == REGS_UNALLOCATED) if (regs_allocated == REGS_UNALLOCATED)
{ /* No. So allocate them with malloc. */ { /* No. So allocate them with malloc. */
regs->start = re_malloc (regoff_t, need_regs); regs->start = re_malloc (regoff_t, need_regs);
regs->end = re_malloc (regoff_t, need_regs); if (BE (regs->start == NULL, 0))
if (BE (regs->start == NULL, 0) || BE (regs->end == NULL, 0))
return REGS_UNALLOCATED; return REGS_UNALLOCATED;
regs->end = re_malloc (regoff_t, need_regs);
if (BE (regs->end == NULL, 0))
{
re_free (regs->start);
return REGS_UNALLOCATED;
}
regs->num_regs = need_regs; regs->num_regs = need_regs;
} }
else if (regs_allocated == REGS_REALLOCATE) else if (regs_allocated == REGS_REALLOCATE)
@@ -524,9 +527,15 @@ re_copy_regs (regs, pmatch, nregs, regs_allocated)
if (BE (need_regs > regs->num_regs, 0)) if (BE (need_regs > regs->num_regs, 0))
{ {
regoff_t *new_start = re_realloc (regs->start, regoff_t, need_regs); regoff_t *new_start = re_realloc (regs->start, regoff_t, need_regs);
regoff_t *new_end = re_realloc (regs->end, regoff_t, need_regs); regoff_t *new_end;
if (BE (new_start == NULL, 0) || BE (new_end == NULL, 0)) if (BE (new_start == NULL, 0))
return REGS_UNALLOCATED; return REGS_UNALLOCATED;
new_end = re_realloc (regs->end, regoff_t, need_regs);
if (BE (new_end == NULL, 0))
{
re_free (new_start);
return REGS_UNALLOCATED;
}
regs->start = new_start; regs->start = new_start;
regs->end = new_end; regs->end = new_end;
regs->num_regs = need_regs; regs->num_regs = need_regs;
@@ -617,6 +626,7 @@ re_exec (s)
(START + RANGE >= 0 && START + RANGE <= LENGTH) */ (START + RANGE >= 0 && START + RANGE <= LENGTH) */
static reg_errcode_t static reg_errcode_t
__attribute_warn_unused_result__
re_search_internal (preg, string, length, start, range, stop, nmatch, pmatch, re_search_internal (preg, string, length, start, range, stop, nmatch, pmatch,
eflags) eflags)
const regex_t *preg; const regex_t *preg;
@@ -693,6 +703,13 @@ re_search_internal (preg, string, length, start, range, stop, nmatch, pmatch,
multi character collating element. */ multi character collating element. */
if (nmatch > 1 || dfa->has_mb_node) if (nmatch > 1 || dfa->has_mb_node)
{ {
/* Avoid overflow. */
if (BE (SIZE_MAX / sizeof (re_dfastate_t *) <= mctx.input.bufs_len, 0))
{
err = REG_ESPACE;
goto free_return;
}
mctx.state_log = re_malloc (re_dfastate_t *, mctx.input.bufs_len + 1); mctx.state_log = re_malloc (re_dfastate_t *, mctx.input.bufs_len + 1);
if (BE (mctx.state_log == NULL, 0)) if (BE (mctx.state_log == NULL, 0))
{ {
@@ -936,6 +953,7 @@ re_search_internal (preg, string, length, start, range, stop, nmatch, pmatch,
} }
static reg_errcode_t static reg_errcode_t
__attribute_warn_unused_result__
prune_impossible_nodes (mctx) prune_impossible_nodes (mctx)
re_match_context_t *mctx; re_match_context_t *mctx;
{ {
@@ -950,6 +968,11 @@ prune_impossible_nodes (mctx)
#endif #endif
match_last = mctx->match_last; match_last = mctx->match_last;
halt_node = mctx->last_node; halt_node = mctx->last_node;
/* Avoid overflow. */
if (BE (SIZE_MAX / sizeof (re_dfastate_t *) <= match_last, 0))
return REG_ESPACE;
sifted_states = re_malloc (re_dfastate_t *, match_last + 1); sifted_states = re_malloc (re_dfastate_t *, match_last + 1);
if (BE (sifted_states == NULL, 0)) if (BE (sifted_states == NULL, 0))
{ {
@@ -1069,7 +1092,7 @@ acquire_init_state_context (reg_errcode_t *err, const re_match_context_t *mctx,
index of the buffer. */ index of the buffer. */
static int static int
internal_function internal_function __attribute_warn_unused_result__
check_matching (re_match_context_t *mctx, int fl_longest_match, check_matching (re_match_context_t *mctx, int fl_longest_match,
int *p_match_first) int *p_match_first)
{ {
@@ -1134,11 +1157,12 @@ check_matching (re_match_context_t *mctx, int fl_longest_match,
re_dfastate_t *old_state = cur_state; re_dfastate_t *old_state = cur_state;
int next_char_idx = re_string_cur_idx (&mctx->input) + 1; int next_char_idx = re_string_cur_idx (&mctx->input) + 1;
if (BE (next_char_idx >= mctx->input.bufs_len, 0) if ((BE (next_char_idx >= mctx->input.bufs_len, 0)
&& mctx->input.bufs_len < mctx->input.len)
|| (BE (next_char_idx >= mctx->input.valid_len, 0) || (BE (next_char_idx >= mctx->input.valid_len, 0)
&& mctx->input.valid_len < mctx->input.len)) && 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)) if (BE (err != REG_NOERROR, 0))
{ {
assert (err == REG_ESPACE); assert (err == REG_ESPACE);
@@ -1342,7 +1366,7 @@ proceed_next_node (const re_match_context_t *mctx, int nregs, regmatch_t *regs,
} }
static reg_errcode_t static reg_errcode_t
internal_function internal_function __attribute_warn_unused_result__
push_fail_stack (struct re_fail_stack_t *fs, int str_idx, int dest_node, push_fail_stack (struct re_fail_stack_t *fs, int str_idx, int dest_node,
int nregs, regmatch_t *regs, re_node_set *eps_via_nodes) int nregs, regmatch_t *regs, re_node_set *eps_via_nodes)
{ {
@@ -1389,7 +1413,7 @@ pop_fail_stack (struct re_fail_stack_t *fs, int *pidx, int nregs,
pmatch[i].rm_so == pmatch[i].rm_eo == -1 for 0 < i < nmatch. */ pmatch[i].rm_so == pmatch[i].rm_eo == -1 for 0 < i < nmatch. */
static reg_errcode_t static reg_errcode_t
internal_function internal_function __attribute_warn_unused_result__
set_regs (const regex_t *preg, const re_match_context_t *mctx, size_t nmatch, set_regs (const regex_t *preg, const re_match_context_t *mctx, size_t nmatch,
regmatch_t *pmatch, int fl_backtrack) regmatch_t *pmatch, int fl_backtrack)
{ {
@@ -1643,7 +1667,7 @@ sift_states_backward (const re_match_context_t *mctx, re_sift_context_t *sctx)
} }
static reg_errcode_t static reg_errcode_t
internal_function internal_function __attribute_warn_unused_result__
build_sifted_states (const re_match_context_t *mctx, re_sift_context_t *sctx, build_sifted_states (const re_match_context_t *mctx, re_sift_context_t *sctx,
int str_idx, re_node_set *cur_dest) int str_idx, re_node_set *cur_dest)
{ {
@@ -1710,12 +1734,13 @@ clean_state_log_if_needed (re_match_context_t *mctx, int next_state_log_idx)
{ {
int top = mctx->state_log_top; int top = mctx->state_log_top;
if (next_state_log_idx >= mctx->input.bufs_len if ((next_state_log_idx >= mctx->input.bufs_len
&& mctx->input.bufs_len < mctx->input.len)
|| (next_state_log_idx >= mctx->input.valid_len || (next_state_log_idx >= mctx->input.valid_len
&& mctx->input.valid_len < mctx->input.len)) && mctx->input.valid_len < mctx->input.len))
{ {
reg_errcode_t err; reg_errcode_t err;
err = extend_buffers (mctx); err = extend_buffers (mctx, next_state_log_idx + 1);
if (BE (err != REG_NOERROR, 0)) if (BE (err != REG_NOERROR, 0))
return err; return err;
} }
@@ -1805,7 +1830,7 @@ update_cur_sifted_state (const re_match_context_t *mctx,
} }
static reg_errcode_t static reg_errcode_t
internal_function internal_function __attribute_warn_unused_result__
add_epsilon_src_nodes (const re_dfa_t *dfa, re_node_set *dest_nodes, add_epsilon_src_nodes (const re_dfa_t *dfa, re_node_set *dest_nodes,
const re_node_set *candidates) const re_node_set *candidates)
{ {
@@ -1822,8 +1847,12 @@ add_epsilon_src_nodes (const re_dfa_t *dfa, re_node_set *dest_nodes,
if (BE (err != REG_NOERROR, 0)) if (BE (err != REG_NOERROR, 0))
return REG_ESPACE; return REG_ESPACE;
for (i = 0; i < dest_nodes->nelem; i++) for (i = 0; i < dest_nodes->nelem; i++)
re_node_set_merge (&state->inveclosure, {
err = re_node_set_merge (&state->inveclosure,
dfa->inveclosures + dest_nodes->elems[i]); dfa->inveclosures + dest_nodes->elems[i]);
if (BE (err != REG_NOERROR, 0))
return REG_ESPACE;
}
} }
return re_node_set_add_intersect (dest_nodes, candidates, return re_node_set_add_intersect (dest_nodes, candidates,
&state->inveclosure); &state->inveclosure);
@@ -2114,7 +2143,7 @@ check_subexp_limits (const re_dfa_t *dfa, re_node_set *dest_nodes,
} }
static reg_errcode_t static reg_errcode_t
internal_function internal_function __attribute_warn_unused_result__
sift_states_bkref (const re_match_context_t *mctx, re_sift_context_t *sctx, sift_states_bkref (const re_match_context_t *mctx, re_sift_context_t *sctx,
int str_idx, const re_node_set *candidates) int str_idx, const re_node_set *candidates)
{ {
@@ -2244,7 +2273,7 @@ sift_states_iter_mb (const re_match_context_t *mctx, re_sift_context_t *sctx,
update the destination of STATE_LOG. */ update the destination of STATE_LOG. */
static re_dfastate_t * static re_dfastate_t *
internal_function internal_function __attribute_warn_unused_result__
transit_state (reg_errcode_t *err, re_match_context_t *mctx, transit_state (reg_errcode_t *err, re_match_context_t *mctx,
re_dfastate_t *state) re_dfastate_t *state)
{ {
@@ -2669,7 +2698,7 @@ transit_state_bkref (re_match_context_t *mctx, const re_node_set *nodes)
delay these checking for prune_impossible_nodes(). */ delay these checking for prune_impossible_nodes(). */
static reg_errcode_t static reg_errcode_t
internal_function internal_function __attribute_warn_unused_result__
get_subexp (re_match_context_t *mctx, int bkref_node, int bkref_str_idx) get_subexp (re_match_context_t *mctx, int bkref_node, int bkref_str_idx)
{ {
const re_dfa_t *const dfa = mctx->dfa; const re_dfa_t *const dfa = mctx->dfa;
@@ -2765,7 +2794,7 @@ get_subexp (re_match_context_t *mctx, int bkref_node, int bkref_str_idx)
if (bkref_str_off >= mctx->input.len) if (bkref_str_off >= mctx->input.len)
break; break;
err = extend_buffers (mctx); err = extend_buffers (mctx, bkref_str_off + 1);
if (BE (err != REG_NOERROR, 0)) if (BE (err != REG_NOERROR, 0))
return err; return err;
@@ -2869,7 +2898,7 @@ find_subexp_node (const re_dfa_t *dfa, const re_node_set *nodes,
Return REG_NOERROR if it can arrive, or REG_NOMATCH otherwise. */ Return REG_NOERROR if it can arrive, or REG_NOMATCH otherwise. */
static reg_errcode_t static reg_errcode_t
internal_function internal_function __attribute_warn_unused_result__
check_arrival (re_match_context_t *mctx, state_array_t *path, int top_node, check_arrival (re_match_context_t *mctx, state_array_t *path, int top_node,
int top_str, int last_node, int last_str, int type) int top_str, int last_node, int last_str, int type)
{ {
@@ -3030,7 +3059,7 @@ check_arrival (re_match_context_t *mctx, state_array_t *path, int top_node,
Can't we unify them? */ Can't we unify them? */
static reg_errcode_t static reg_errcode_t
internal_function internal_function __attribute_warn_unused_result__
check_arrival_add_next_nodes (re_match_context_t *mctx, int str_idx, check_arrival_add_next_nodes (re_match_context_t *mctx, int str_idx,
re_node_set *cur_nodes, re_node_set *next_nodes) re_node_set *cur_nodes, re_node_set *next_nodes)
{ {
@@ -3162,7 +3191,7 @@ check_arrival_expand_ecl (const re_dfa_t *dfa, re_node_set *cur_nodes,
problematic append it to DST_NODES. */ problematic append it to DST_NODES. */
static reg_errcode_t static reg_errcode_t
internal_function internal_function __attribute_warn_unused_result__
check_arrival_expand_ecl_sub (const re_dfa_t *dfa, re_node_set *dst_nodes, check_arrival_expand_ecl_sub (const re_dfa_t *dfa, re_node_set *dst_nodes,
int target, int ex_subexp, int type) int target, int ex_subexp, int type)
{ {
@@ -3206,7 +3235,7 @@ check_arrival_expand_ecl_sub (const re_dfa_t *dfa, re_node_set *dst_nodes,
in MCTX->BKREF_ENTS. */ in MCTX->BKREF_ENTS. */
static reg_errcode_t static reg_errcode_t
internal_function internal_function __attribute_warn_unused_result__
expand_bkref_cache (re_match_context_t *mctx, re_node_set *cur_nodes, expand_bkref_cache (re_match_context_t *mctx, re_node_set *cur_nodes,
int cur_str, int subexp_num, int type) int cur_str, int subexp_num, int type)
{ {
@@ -3347,6 +3376,8 @@ build_trtable (const re_dfa_t *dfa, re_dfastate_t *state)
{ {
state->trtable = (re_dfastate_t **) state->trtable = (re_dfastate_t **)
calloc (sizeof (re_dfastate_t *), SBC_MAX); calloc (sizeof (re_dfastate_t *), SBC_MAX);
if (BE (state->trtable == NULL, 0))
return 0;
return 1; return 1;
} }
return 0; return 0;
@@ -3356,6 +3387,13 @@ build_trtable (const re_dfa_t *dfa, re_dfastate_t *state)
if (BE (err != REG_NOERROR, 0)) if (BE (err != REG_NOERROR, 0))
goto out_free; goto out_free;
/* Avoid arithmetic overflow in size calculation. */
if (BE ((((SIZE_MAX - (sizeof (re_node_set) + sizeof (bitset_t)) * SBC_MAX)
/ (3 * sizeof (re_dfastate_t *)))
< ndests),
0))
goto out_free;
if (__libc_use_alloca ((sizeof (re_node_set) + sizeof (bitset_t)) * SBC_MAX if (__libc_use_alloca ((sizeof (re_node_set) + sizeof (bitset_t)) * SBC_MAX
+ ndests * 3 * sizeof (re_dfastate_t *))) + ndests * 3 * sizeof (re_dfastate_t *)))
dest_states = (re_dfastate_t **) dest_states = (re_dfastate_t **)
@@ -3711,6 +3749,10 @@ group_nodes_into_DFAstates (const re_dfa_t *dfa, const re_dfastate_t *state,
one collating element like '.', '[a-z]', opposite to the other nodes one collating element like '.', '[a-z]', opposite to the other nodes
can only accept one byte. */ can only accept one byte. */
# ifdef _LIBC
# include <locale/weight.h>
# endif
static int static int
internal_function internal_function
check_node_accept_bytes (const re_dfa_t *dfa, int node_idx, check_node_accept_bytes (const re_dfa_t *dfa, int node_idx,
@@ -3830,8 +3872,6 @@ check_node_accept_bytes (const re_dfa_t *dfa, int node_idx,
const int32_t *table, *indirect; const int32_t *table, *indirect;
const unsigned char *weights, *extra; const unsigned char *weights, *extra;
const char *collseqwc; const char *collseqwc;
/* This #include defines a local function! */
# include <locale/weight.h>
/* match with collating_symbol? */ /* match with collating_symbol? */
if (cset->ncoll_syms) if (cset->ncoll_syms)
@@ -3887,7 +3927,7 @@ check_node_accept_bytes (const re_dfa_t *dfa, int node_idx,
_NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB); _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB);
indirect = (const int32_t *) indirect = (const int32_t *)
_NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTMB); _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTMB);
int32_t idx = findidx (&cp); int32_t idx = findidx (table, indirect, extra, &cp, elem_len);
if (idx > 0) if (idx > 0)
for (i = 0; i < cset->nequiv_classes; ++i) for (i = 0; i < cset->nequiv_classes; ++i)
{ {
@@ -3998,7 +4038,7 @@ find_collation_sequence_value (const unsigned char *mbs, size_t mbs_len)
/* Skip the collation sequence value. */ /* Skip the collation sequence value. */
idx += sizeof (uint32_t); idx += sizeof (uint32_t);
/* Skip the wide char sequence of the collating element. */ /* Skip the wide char sequence of the collating element. */
idx = idx + sizeof (uint32_t) * (extra[idx] + 1); idx = idx + sizeof (uint32_t) * (*(int32_t *) (extra + idx) + 1);
/* If we found the entry, return the sequence value. */ /* If we found the entry, return the sequence value. */
if (found) if (found)
return *(uint32_t *) (extra + idx); return *(uint32_t *) (extra + idx);
@@ -4065,14 +4105,20 @@ check_node_accept (const re_match_context_t *mctx, const re_token_t *node,
/* Extend the buffers, if the buffers have run out. */ /* Extend the buffers, if the buffers have run out. */
static reg_errcode_t static reg_errcode_t
internal_function 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; reg_errcode_t ret;
re_string_t *pstr = &mctx->input; re_string_t *pstr = &mctx->input;
/* Double the lengthes of the buffers. */ /* Avoid overflow. */
ret = re_string_realloc_buffers (pstr, pstr->bufs_len * 2); if (BE (INT_MAX / 2 / sizeof (re_dfastate_t *) <= pstr->bufs_len, 0))
return REG_ESPACE;
/* 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)) if (BE (ret != REG_NOERROR, 0))
return ret; return ret;
@@ -4124,7 +4170,7 @@ extend_buffers (re_match_context_t *mctx)
/* Initialize MCTX. */ /* Initialize MCTX. */
static reg_errcode_t static reg_errcode_t
internal_function internal_function __attribute_warn_unused_result__
match_ctx_init (re_match_context_t *mctx, int eflags, int n) match_ctx_init (re_match_context_t *mctx, int eflags, int n)
{ {
mctx->eflags = eflags; mctx->eflags = eflags;
@@ -4197,7 +4243,7 @@ match_ctx_free (re_match_context_t *mctx)
*/ */
static reg_errcode_t static reg_errcode_t
internal_function internal_function __attribute_warn_unused_result__
match_ctx_add_entry (re_match_context_t *mctx, int node, int str_idx, int from, match_ctx_add_entry (re_match_context_t *mctx, int node, int str_idx, int from,
int to) int to)
{ {
@@ -4269,7 +4315,7 @@ search_cur_bkref_entry (const re_match_context_t *mctx, int str_idx)
at STR_IDX. */ at STR_IDX. */
static reg_errcode_t static reg_errcode_t
internal_function internal_function __attribute_warn_unused_result__
match_ctx_add_subtop (re_match_context_t *mctx, int node, int str_idx) match_ctx_add_subtop (re_match_context_t *mctx, int node, int str_idx)
{ {
#ifdef DEBUG #ifdef DEBUG