summaryrefslogtreecommitdiff
path: root/regexec.c
diff options
context:
space:
mode:
authorPeter Zhu <[email protected]>2024-07-24 15:16:16 -0400
committerPeter Zhu <[email protected]>2024-07-25 09:23:49 -0400
commit10574857ce167869524b97ee862b610928f6272f (patch)
tree5aaafb2164a82087ef87d2be12a5183d2fab8348 /regexec.c
parent53f0d3b1f7ee9d1f1068b44ef856c557177704a5 (diff)
Fix memory leak in Regexp capture group when timeout
[Bug #20650] The capture group allocates memory that is leaked when it times out. For example: re = Regexp.new("^#{"(a*)" * 10_000}x$", timeout: 0.000001) str = "a" * 1000000 + "x" 10.times do 100.times do re =~ str rescue Regexp::TimeoutError end puts `ps -o rss= -p #{$$}` end Before: 34688 56416 78288 100368 120784 140704 161904 183568 204320 224800 After: 16288 16288 16880 16896 16912 16928 16944 17184 17184 17200
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/11238
Diffstat (limited to 'regexec.c')
-rw-r--r--regexec.c73
1 files changed, 49 insertions, 24 deletions
diff --git a/regexec.c b/regexec.c
index 6d82429e03..9833eeff25 100644
--- a/regexec.c
+++ b/regexec.c
@@ -4220,7 +4220,7 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
xfree(xmalloc_base);
if (stk_base != stk_alloc || IS_NOT_NULL(msa->stack_p))
xfree(stk_base);
- HANDLE_REG_TIMEOUT_IN_MATCH_AT;
+ return ONIGERR_TIMEOUT;
}
@@ -5212,44 +5212,64 @@ onig_search_gpos(regex_t* reg, const UChar* str, const UChar* end,
# ifdef USE_FIND_LONGEST_SEARCH_ALL_OF_RANGE
# define MATCH_AND_RETURN_CHECK(upper_range) \
r = match_at(reg, str, end, (upper_range), s, prev, &msa); \
- if (r != ONIG_MISMATCH) {\
- if (r >= 0) {\
- if (! IS_FIND_LONGEST(reg->options)) {\
- goto match;\
+ switch (r) { \
+ case ONIG_MISMATCH: \
+ break; \
+ case ONIGERR_TIMEOUT: \
+ goto timeout; \
+ default: \
+ if (r >= 0) { \
+ if (! IS_FIND_LONGEST(reg->options)) { \
+ goto match; \
+ }\
}\
- }\
- else goto finish; /* error */ \
+ else goto finish; /* error */ \
}
# else
# define MATCH_AND_RETURN_CHECK(upper_range) \
r = match_at(reg, str, end, (upper_range), s, prev, &msa); \
- if (r != ONIG_MISMATCH) {\
- if (r >= 0) {\
- goto match;\
- }\
- else goto finish; /* error */ \
+ switch (r) { \
+ case ONIG_MISMATCH: \
+ break; \
+ case ONIGERR_TIMEOUT: \
+ goto timeout; \
+ default: \
+ if (r >= 0) { \
+ goto match; \
+ }\
+ else goto finish; /* error */ \
}
# endif /* USE_FIND_LONGEST_SEARCH_ALL_OF_RANGE */
#else
# ifdef USE_FIND_LONGEST_SEARCH_ALL_OF_RANGE
# define MATCH_AND_RETURN_CHECK(none) \
r = match_at(reg, str, end, s, prev, &msa);\
- if (r != ONIG_MISMATCH) {\
- if (r >= 0) {\
- if (! IS_FIND_LONGEST(reg->options)) {\
- goto match;\
- }\
- }\
- else goto finish; /* error */ \
+ switch (r) { \
+ case ONIG_MISMATCH: \
+ break; \
+ case ONIGERR_TIMEOUT: \
+ goto timeout; \
+ default: \
+ if (r >= 0) { \
+ if (! IS_FIND_LONGEST(reg->options)) { \
+ goto match; \
+ } \
+ } \
+ else goto finish; /* error */ \
}
# else
# define MATCH_AND_RETURN_CHECK(none) \
r = match_at(reg, str, end, s, prev, &msa);\
- if (r != ONIG_MISMATCH) {\
- if (r >= 0) {\
- goto match;\
- }\
- else goto finish; /* error */ \
+ switch (r) { \
+ case ONIG_MISMATCH: \
+ break; \
+ case ONIGERR_TIMEOUT: \
+ goto timeout; \
+ default: \
+ if (r >= 0) { \
+ goto match; \
+ } \
+ else goto finish; /* error */ \
}
# endif /* USE_FIND_LONGEST_SEARCH_ALL_OF_RANGE */
#endif /* USE_MATCH_RANGE_MUST_BE_INSIDE_OF_SPECIFIED_RANGE */
@@ -5552,6 +5572,11 @@ onig_search_gpos(regex_t* reg, const UChar* str, const UChar* end,
match:
MATCH_ARG_FREE(msa);
return s - str;
+
+timeout:
+ MATCH_ARG_FREE(msa);
+ onig_region_free(region, false);
+ HANDLE_REG_TIMEOUT_IN_MATCH_AT;
}
extern OnigPosition