diff --git a/re.c b/re.c index 2f515779c7..2256a0655d 100644 --- a/re.c +++ b/re.c @@ -4605,8 +4605,8 @@ re_warn(const char *s) rb_hrtime_t rb_reg_match_time_limit = 0; // This function is periodically called during regexp matching -void -rb_reg_check_timeout(regex_t *reg, void *end_time_) +bool +rb_reg_timeout_p(regex_t *reg, void *end_time_) { rb_hrtime_t *end_time = (rb_hrtime_t *)end_time_; @@ -4631,10 +4631,18 @@ rb_reg_check_timeout(regex_t *reg, void *end_time_) } else { if (*end_time < rb_hrtime_now()) { - // timeout is exceeded - rb_raise(rb_eRegexpTimeoutError, "regexp match timeout"); + // Timeout has exceeded + return true; } } + + return false; +} + +void +rb_reg_raise_timeout(void) +{ + rb_raise(rb_eRegexpTimeoutError, "regexp match timeout"); } /* diff --git a/regexec.c b/regexec.c index 150d36ccc8..81d0ea6a6b 100644 --- a/regexec.c +++ b/regexec.c @@ -2293,7 +2293,7 @@ match_at(regex_t* reg, const UChar* str, const UChar* end, UChar *pkeep; char *alloca_base; char *xmalloc_base = NULL; - OnigStackType *stk_alloc, *stk_base, *stk, *stk_end; + OnigStackType *stk_alloc, *stk_base = NULL, *stk, *stk_end; OnigStackType *stkp; /* used as any purpose. */ OnigStackIndex si; OnigStackIndex *repeat_stk; @@ -4202,6 +4202,11 @@ match_at(regex_t* reg, const UChar* str, const UChar* end, STACK_SAVE; xfree(xmalloc_base); return ONIGERR_UNEXPECTED_BYTECODE; + + timeout: + xfree(xmalloc_base); + xfree(stk_base); + HANDLE_REG_TIMEOUT_IN_MATCH_AT; } diff --git a/regint.h b/regint.h index 034a31426c..57cbb81654 100644 --- a/regint.h +++ b/regint.h @@ -154,13 +154,18 @@ #ifdef RUBY # define CHECK_INTERRUPT_IN_MATCH_AT do { \ - msa->counter++; \ - if (msa->counter >= 128) { \ - msa->counter = 0; \ - rb_reg_check_timeout(reg, &msa->end_time); \ - rb_thread_check_ints(); \ - } \ + msa->counter++; \ + if (msa->counter >= 128) { \ + msa->counter = 0; \ + if (rb_reg_timeout_p(reg, &msa->end_time)) { \ + goto timeout; \ + } \ + rb_thread_check_ints(); \ + } \ } while(0) +# define HANDLE_REG_TIMEOUT_IN_MATCH_AT do { \ + rb_reg_raise_timeout(); \ +} while (0) # define onig_st_init_table st_init_table # define onig_st_init_table_with_size st_init_table_with_size # define onig_st_init_numtable st_init_numtable @@ -996,7 +1001,8 @@ extern int onig_st_insert_strend(hash_table_type* table, const UChar* str_key, c #ifdef RUBY extern size_t onig_memsize(const regex_t *reg); extern size_t onig_region_memsize(const struct re_registers *regs); -void rb_reg_check_timeout(regex_t *reg, void *end_time); +bool rb_reg_timeout_p(regex_t *reg, void *end_time); +NORETURN(void rb_reg_raise_timeout(void)); #endif RUBY_SYMBOL_EXPORT_END