diff options
Diffstat (limited to 'posix')
-rw-r--r-- | posix/regexec.c | 46 |
1 files changed, 37 insertions, 9 deletions
diff --git a/posix/regexec.c b/posix/regexec.c index 3cc9288a67..fa4f218df3 100644 --- a/posix/regexec.c +++ b/posix/regexec.c @@ -2551,7 +2551,6 @@ get_subexp (mctx, bkref_node, bkref_str_idx) re_sub_match_top_t *sub_top = mctx->sub_tops[sub_top_idx]; re_sub_match_last_t *sub_last; int sub_last_idx, sl_str, bkref_str_off; - const char *bkref_str; if (dfa->nodes[sub_top->node].opr.idx != subexp_num) continue; /* It isn't related. */ @@ -2567,9 +2566,24 @@ get_subexp (mctx, bkref_node, bkref_str_idx) sl_str_diff = sub_last->str_idx - sl_str; /* The matched string by the sub expression match with the substring at the back reference? */ - if (sl_str_diff > 0 - && memcmp (buf + bkref_str_off, buf + sl_str, sl_str_diff) != 0) - break; /* We don't need to search this sub expression any more. */ + if (sl_str_diff > 0) + { + if (BE (bkref_str_off + sl_str_diff > mctx->input.valid_len, 0)) + { + /* Not enough chars for a successful match. */ + if (bkref_str_off + sl_str_diff > mctx->input.len) + break; + + err = clean_state_log_if_needed (mctx, + bkref_str_off + + sl_str_diff); + if (BE (err != REG_NOERROR, 0)) + return err; + buf = (const char *) re_string_get_buffer (&mctx->input); + } + if (memcmp (buf + bkref_str_off, buf + sl_str, sl_str_diff) != 0) + break; /* We don't need to search this sub expression any more. */ + } bkref_str_off += sl_str_diff; sl_str += sl_str_diff; err = get_subexp_sub (mctx, sub_top, sub_last, bkref_node, @@ -2584,7 +2598,6 @@ get_subexp (mctx, bkref_node, bkref_str_idx) if (BE (err != REG_NOERROR, 0)) return err; } - bkref_str = buf + bkref_str_off; if (sub_last_idx < sub_top->nlasts) continue; @@ -2598,8 +2611,24 @@ get_subexp (mctx, bkref_node, bkref_str_idx) sl_str_off = sl_str - sub_top->str_idx; /* The matched string by the sub expression match with the substring at the back reference? */ - if (sl_str_off > 0 && *bkref_str++ != buf[sl_str - 1]) - break; /* We don't need to search this sub expression any more. */ + if (sl_str_off > 0) + { + if (BE (bkref_str_off >= mctx->input.valid_len, 0)) + { + /* If we are at the end of the input, we cannot match. */ + if (bkref_str_off >= mctx->input.len) + break; + + err = extend_buffers (mctx); + if (BE (err != REG_NOERROR, 0)) + return err; + + buf = (const char *) re_string_get_buffer (&mctx->input); + } + if (buf [bkref_str_off++] != buf[sl_str - 1]) + break; /* We don't need to search this sub expression + any more. */ + } if (mctx->state_log[sl_str] == NULL) continue; /* Does this state have a ')' of the sub expression? */ @@ -2659,8 +2688,7 @@ get_subexp_sub (mctx, sub_top, sub_last, bkref_node, bkref_str) if (BE (err != REG_NOERROR, 0)) return err; to_idx = bkref_str + sub_last->str_idx - sub_top->str_idx; - clean_state_log_if_needed (mctx, to_idx); - return REG_NOERROR; + return clean_state_log_if_needed (mctx, to_idx); } /* Find the first node which is '(' or ')' and whose index is SUBEXP_IDX. |