X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=src%2Fregex%2Fregexec.c;h=253b0e1495601567cca31ea27dceca744fcdbfcb;hb=9432bbd4e880850357fd0a81b429499451eb2084;hp=79874ca5522849425e7af58ed05dee16d85d2a3f;hpb=ad47d45e9da8df364cb0a61b6146d51c196c8891;p=musl diff --git a/src/regex/regexec.c b/src/regex/regexec.c index 79874ca5..253b0e14 100644 --- a/src/regex/regexec.c +++ b/src/regex/regexec.c @@ -34,6 +34,7 @@ #include #include #include +#include #include @@ -43,7 +44,7 @@ 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 @@ -52,7 +53,7 @@ tre_fill_pmatch(size_t nmatch, regmatch_t pmatch[], int cflags, #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; \ @@ -96,7 +97,7 @@ tre_fill_pmatch(size_t nmatch, regmatch_t pmatch[], int cflags, /* 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++) @@ -156,31 +157,32 @@ tre_neg_char_classes_match(tre_ctype_t *classes, tre_cint_t wc, int icase) 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; @@ -189,10 +191,10 @@ tre_tnfa_run_parallel(const tre_tnfa_t *tnfa, const void *string, 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)); @@ -205,25 +207,37 @@ tre_tnfa_run_parallel(const tre_tnfa_t *tnfa, const void *string, /* 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; @@ -439,11 +453,11 @@ tre_tnfa_run_parallel(const tre_tnfa_t *tnfa, const void *string, 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; } @@ -476,12 +490,12 @@ tre_tnfa_run_parallel(const tre_tnfa_t *tnfa, const void *string, */ 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 */ @@ -577,13 +591,13 @@ typedef struct tre_backtrack_struct { 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 */ @@ -596,15 +610,16 @@ tre_tnfa_run_backtrack(const tre_tnfa_t *tnfa, const void *string, 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; @@ -754,8 +769,9 @@ tre_tnfa_run_backtrack(const tre_tnfa_t *tnfa, const void *string, /* 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 @@ -912,7 +928,7 @@ tre_tnfa_run_backtrack(const tre_tnfa_t *tnfa, const void *string, 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; @@ -977,12 +993,13 @@ tre_fill_pmatch(size_t nmatch, regmatch_t pmatch[], int cflags, */ 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);