summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Zhu <[email protected]>2023-12-23 20:24:15 -0500
committerPeter Zhu <[email protected]>2023-12-24 09:03:55 -0500
commit42442ed7891b1c721b4a306f21ce9548a69e7be3 (patch)
tree1cc6fe34ed7a75a85a38b741634825e7cc8270f8
parent37753f163e461e157e6e224d9d3e5626427a50cc (diff)
Fix Regexp#match for GC compaction
The test fails when RGENGC_CHECK_MODE is turned on: TestRegexp#test_match_under_gc_compact_stress: NoMethodError: undefined method `match' for nil test_regexp.rb:878:in `block in test_match_under_gc_compact_stress'
-rw-r--r--re.c8
-rw-r--r--test/ruby/test_regexp.rb7
2 files changed, 12 insertions, 3 deletions
diff --git a/re.c b/re.c
index e51b782cf6..ef49281454 100644
--- a/re.c
+++ b/re.c
@@ -1581,7 +1581,6 @@ rb_reg_prepare_re(VALUE re, VALUE str)
{
int r;
OnigErrorInfo einfo;
- const char *pattern;
VALUE unescaped;
rb_encoding *fixed_enc = 0;
rb_encoding *enc = rb_reg_prepare_enc(re, str, 1);
@@ -1590,11 +1589,13 @@ rb_reg_prepare_re(VALUE re, VALUE str)
if (reg->enc == enc) return reg;
rb_reg_check(re);
- pattern = RREGEXP_SRC_PTR(re);
+
+ VALUE src_str = RREGEXP_SRC(re);
+ const char *pattern = RSTRING_PTR(src_str);
onig_errmsg_buffer err = "";
unescaped = rb_reg_preprocess(
- pattern, pattern + RREGEXP_SRC_LEN(re), enc,
+ pattern, pattern + RSTRING_LEN(src_str), enc,
&fixed_enc, err, 0);
if (NIL_P(unescaped)) {
@@ -1639,6 +1640,7 @@ rb_reg_prepare_re(VALUE re, VALUE str)
reg->timelimit = timelimit;
RB_GC_GUARD(unescaped);
+ RB_GC_GUARD(src_str);
return reg;
}
diff --git a/test/ruby/test_regexp.rb b/test/ruby/test_regexp.rb
index 77e9ca67f6..c51c61b2a3 100644
--- a/test/ruby/test_regexp.rb
+++ b/test/ruby/test_regexp.rb
@@ -872,6 +872,13 @@ class TestRegexp < Test::Unit::TestCase
$_ = nil; assert_nil(~/./)
end
+ def test_match_under_gc_compact_stress
+ EnvUtil.under_gc_compact_stress do
+ m = /(?<foo>.)(?<n>[^aeiou])?(?<bar>.+)/.match("hoge\u3042")
+ assert_equal("h", m.match(:foo))
+ end
+ end
+
def test_match_p
/backref/ =~ 'backref'
# must match here, but not in a separate method, e.g., assert_send,