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'
This commit is contained in:
Peter Zhu 2023-12-23 20:24:15 -05:00
Родитель 37753f163e
Коммит 42442ed789
2 изменённых файлов: 12 добавлений и 3 удалений

8
re.c
Просмотреть файл

@ -1581,7 +1581,6 @@ rb_reg_prepare_re(VALUE re, VALUE str)
{ {
int r; int r;
OnigErrorInfo einfo; OnigErrorInfo einfo;
const char *pattern;
VALUE unescaped; VALUE unescaped;
rb_encoding *fixed_enc = 0; rb_encoding *fixed_enc = 0;
rb_encoding *enc = rb_reg_prepare_enc(re, str, 1); 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; if (reg->enc == enc) return reg;
rb_reg_check(re); 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 = ""; onig_errmsg_buffer err = "";
unescaped = rb_reg_preprocess( unescaped = rb_reg_preprocess(
pattern, pattern + RREGEXP_SRC_LEN(re), enc, pattern, pattern + RSTRING_LEN(src_str), enc,
&fixed_enc, err, 0); &fixed_enc, err, 0);
if (NIL_P(unescaped)) { if (NIL_P(unescaped)) {
@ -1639,6 +1640,7 @@ rb_reg_prepare_re(VALUE re, VALUE str)
reg->timelimit = timelimit; reg->timelimit = timelimit;
RB_GC_GUARD(unescaped); RB_GC_GUARD(unescaped);
RB_GC_GUARD(src_str);
return reg; return reg;
} }

Просмотреть файл

@ -872,6 +872,13 @@ class TestRegexp < Test::Unit::TestCase
$_ = nil; assert_nil(~/./) $_ = nil; assert_nil(~/./)
end 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 def test_match_p
/backref/ =~ 'backref' /backref/ =~ 'backref'
# must match here, but not in a separate method, e.g., assert_send, # must match here, but not in a separate method, e.g., assert_send,