#include <wchar.h>
#include <wctype.h>
#include <limits.h>
+#include <stdint.h>
#include <regex.h>
static void
tre_fill_pmatch(size_t nmatch, regmatch_t pmatch[], int cflags,
- const tre_tnfa_t *tnfa, int *tags, int match_eo);
+ const tre_tnfa_t *tnfa, regoff_t *tags, regoff_t match_eo);
/***********************************************************************
from tre-match-utils.h
#define GET_NEXT_WCHAR() do { \
prev_c = next_c; pos += pos_add_next; \
if ((pos_add_next = mbtowc(&next_c, str_byte, MB_LEN_MAX)) <= 0) { \
- if (pos_add_next < 0) return REG_NOMATCH; \
+ if (pos_add_next < 0) { ret = REG_NOMATCH; goto error_exit; } \
else pos_add_next++; \
} \
str_byte += pos_add_next; \
/* Returns 1 if `t1' wins `t2', 0 otherwise. */
static int
tre_tag_order(int num_tags, tre_tag_direction_t *tag_directions,
- int *t1, int *t2)
+ regoff_t *t1, regoff_t *t2)
{
int i;
for (i = 0; i < num_tags; i++)
typedef struct {
tre_tnfa_transition_t *state;
- int *tags;
+ regoff_t *tags;
} tre_tnfa_reach_t;
typedef struct {
- int pos;
- int **tags;
+ regoff_t pos;
+ regoff_t **tags;
} tre_reach_pos_t;
static reg_errcode_t
tre_tnfa_run_parallel(const tre_tnfa_t *tnfa, const void *string,
- int *match_tags, int eflags,
- int *match_end_ofs)
+ regoff_t *match_tags, int eflags,
+ regoff_t *match_end_ofs)
{
/* State variables required by GET_NEXT_WCHAR. */
tre_char_t prev_c = 0, next_c = 0;
const char *str_byte = string;
- int pos = -1;
- unsigned int pos_add_next = 1;
+ regoff_t pos = -1;
+ regoff_t pos_add_next = 1;
#ifdef TRE_MBSTATE
mbstate_t mbstate;
#endif /* TRE_MBSTATE */
int reg_notbol = eflags & REG_NOTBOL;
int reg_noteol = eflags & REG_NOTEOL;
int reg_newline = tnfa->cflags & REG_NEWLINE;
+ reg_errcode_t ret;
char *buf;
tre_tnfa_transition_t *trans_i;
int *tag_i;
int num_tags, i;
- int match_eo = -1; /* end offset of match (-1 if no match found yet) */
+ regoff_t match_eo = -1; /* end offset of match (-1 if no match found yet) */
int new_match = 0;
- int *tmp_tags = NULL;
- int *tmp_iptr;
+ regoff_t *tmp_tags = NULL;
+ regoff_t *tmp_iptr;
#ifdef TRE_MBSTATE
memset(&mbstate, '\0', sizeof(mbstate));
/* Allocate memory for temporary data required for matching. This needs to
be done for every matching operation to be thread safe. This allocates
- everything in a single large block from the stack frame using alloca()
- or with malloc() if alloca is unavailable. */
+ everything in a single large block with calloc(). */
{
- int tbytes, rbytes, pbytes, xbytes, total_bytes;
+ size_t tbytes, rbytes, pbytes, xbytes, total_bytes;
char *tmp_buf;
+
+ /* Ensure that tbytes and xbytes*num_states cannot overflow, and that
+ * they don't contribute more than 1/8 of SIZE_MAX to total_bytes. */
+ if (num_tags > SIZE_MAX/(8 * sizeof(regoff_t) * tnfa->num_states))
+ return REG_ESPACE;
+
+ /* Likewise check rbytes. */
+ if (tnfa->num_states+1 > SIZE_MAX/(8 * sizeof(*reach_next)))
+ return REG_ESPACE;
+
+ /* Likewise check pbytes. */
+ if (tnfa->num_states > SIZE_MAX/(8 * sizeof(*reach_pos)))
+ return REG_ESPACE;
+
/* Compute the length of the block we need. */
tbytes = sizeof(*tmp_tags) * num_tags;
rbytes = sizeof(*reach_next) * (tnfa->num_states + 1);
pbytes = sizeof(*reach_pos) * tnfa->num_states;
- xbytes = sizeof(int) * num_tags;
+ xbytes = sizeof(regoff_t) * num_tags;
total_bytes =
(sizeof(long) - 1) * 4 /* for alignment paddings */
+ (rbytes + xbytes * tnfa->num_states) * 2 + tbytes + pbytes;
/* Allocate the memory. */
- buf = xmalloc((unsigned)total_bytes);
+ buf = calloc(total_bytes, 1);
if (buf == NULL)
return REG_ESPACE;
- memset(buf, 0, (size_t)total_bytes);
/* Get the various pointers within tmp_buf (properly aligned). */
tmp_tags = (void *)buf;
reach_next_i->state = NULL;
}
- if (buf)
- xfree(buf);
-
*match_end_ofs = match_eo;
- return match_eo >= 0 ? REG_OK : REG_NOMATCH;
+ ret = match_eo >= 0 ? REG_OK : REG_NOMATCH;
+error_exit:
+ xfree(buf);
+ return ret;
}
*/
typedef struct {
- int pos;
+ regoff_t pos;
const char *str_byte;
tre_tnfa_transition_t *state;
int state_id;
int next_c;
- int *tags;
+ regoff_t *tags;
#ifdef TRE_MBSTATE
mbstate_t mbstate;
#endif /* TRE_MBSTATE */
static reg_errcode_t
tre_tnfa_run_backtrack(const tre_tnfa_t *tnfa, const void *string,
- int *match_tags, int eflags, int *match_end_ofs)
+ regoff_t *match_tags, int eflags, regoff_t *match_end_ofs)
{
/* State variables required by GET_NEXT_WCHAR. */
tre_char_t prev_c = 0, next_c = 0;
const char *str_byte = string;
- int pos = 0;
- unsigned int pos_add_next = 1;
+ regoff_t pos = 0;
+ regoff_t pos_add_next = 1;
#ifdef TRE_MBSTATE
mbstate_t mbstate;
#endif /* TRE_MBSTATE */
started from. */
int next_c_start;
const char *str_byte_start;
- int pos_start = -1;
+ regoff_t pos_start = -1;
#ifdef TRE_MBSTATE
mbstate_t mbstate_start;
#endif /* TRE_MBSTATE */
/* End offset of best match so far, or -1 if no match found yet. */
- int match_eo = -1;
+ regoff_t match_eo = -1;
/* Tag arrays. */
- int *next_tags, *tags = NULL;
+ int *next_tags;
+ regoff_t *tags = NULL;
/* Current TNFA state. */
tre_tnfa_transition_t *state;
int *states_seen = NULL;
/* This is a back reference state. All transitions leaving from
this state have the same back reference "assertion". Instead
of reading the next character, we match the back reference. */
- int so, eo, bt = trans_i->u.backref;
- int bt_len;
+ regoff_t so, eo;
+ int bt = trans_i->u.backref;
+ regoff_t bt_len;
int result;
/* Get the substring we need to match against. Remember to
endpoint values. */
static void
tre_fill_pmatch(size_t nmatch, regmatch_t pmatch[], int cflags,
- const tre_tnfa_t *tnfa, int *tags, int match_eo)
+ const tre_tnfa_t *tnfa, regoff_t *tags, regoff_t match_eo)
{
tre_submatch_data_t *submatch_data;
unsigned int i, j;
*/
int
-regexec(const regex_t *preg, const char *string,
- size_t nmatch, regmatch_t pmatch[], int eflags)
+regexec(const regex_t *restrict preg, const char *restrict string,
+ size_t nmatch, regmatch_t pmatch[restrict], int eflags)
{
tre_tnfa_t *tnfa = (void *)preg->TRE_REGEX_T_FIELD;
reg_errcode_t status;
- int *tags = NULL, eo;
+ regoff_t *tags = NULL, eo;
+ if (tnfa->cflags & REG_NOSUB) nmatch = 0;
if (tnfa->num_tags > 0 && nmatch > 0)
{
tags = xmalloc(sizeof(*tags) * tnfa->num_tags);