8000 [Bug #20228] Fix memory leak in Regexp timeout by peterzhu2118 · Pull Request #9765 · ruby/ruby · GitHub
[go: up one dir, main page]

Skip to content

[Bug #20228] Fix memory leak in Regexp timeout #9765

8000
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Feb 2, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Fix memory leak in stk_base when Regexp timeout
[Bug #20228]

If rb_reg_check_timeout raises a Regexp::TimeoutError, then the stk_base
will leak.
  • Loading branch information
peterzhu2118 committed Jan 31, 2024
8000 commit 193c680c66649a3d7fa4d78fa54af1fdea0eed38
16 changes: 12 additions & 4 deletions re.c
Original file line number Diff line number Diff line change
Expand Up @@ -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_;

Expand All @@ -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");
}

/*
Expand Down
7 changes: 6 additions & 1 deletion regexec.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}


Expand Down
20 changes: 13 additions & 7 deletions regint.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
0