X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=src%2Fregex%2Fregexec.c;h=dd52319581a8e36e2b9344cf6d56d4a48b443b9d;hb=c3edc06d1e1360f3570db9155d6b318ae0d0f0f7;hp=855cef573ae94a12370492a4da433a39dff37856;hpb=400c5e5c8307a2ebe44ef1f203f5a15669f20347;p=musl diff --git a/src/regex/regexec.c b/src/regex/regexec.c index 855cef57..dd523195 100644 --- a/src/regex/regexec.c +++ b/src/regex/regexec.c @@ -34,6 +34,7 @@ #include #include #include +#include #include @@ -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; \ @@ -181,6 +182,7 @@ tre_tnfa_run_parallel(const tre_tnfa_t *tnfa, const void *string, 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; @@ -205,11 +207,24 @@ 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(int) * tnfa->num_states)) + goto error_exit; + + /* Likewise check rbytes. */ + if (tnfa->num_states+1 > SIZE_MAX/(8 * sizeof(*reach_next))) + goto error_exit; + + /* Likewise check pbytes. */ + if (tnfa->num_states > SIZE_MAX/(8 * sizeof(*reach_pos))) + goto error_exit; + /* Compute the length of the block we need. */ tbytes = sizeof(*tmp_tags) * num_tags; rbytes = sizeof(*reach_next) * (tnfa->num_states + 1); @@ -220,10 +235,9 @@ tre_tnfa_run_parallel(const tre_tnfa_t *tnfa, const void *string, + (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; } @@ -983,6 +997,7 @@ regexec(const regex_t *restrict preg, const char *restrict string, tre_tnfa_t *tnfa = (void *)preg->TRE_REGEX_T_FIELD; reg_errcode_t status; int *tags = NULL, eo; + if (tnfa->cflags & REG_NOSUB) nmatch = 0; if (tnfa->num_tags > 0 && nmatch > 0) { tags = xmalloc(sizeof(*tags) * tnfa->num_tags);