Guard match from GC when scanning string
We need to guard match from GC because otherwise it could end up being reclaimed or moved in compaction.
This commit is contained in:
parent
1acea50100
commit
94015e0dce
18
string.c
18
string.c
@ -9973,11 +9973,11 @@ rb_str_strip(VALUE str)
|
|||||||
static VALUE
|
static VALUE
|
||||||
scan_once(VALUE str, VALUE pat, long *start, int set_backref_str)
|
scan_once(VALUE str, VALUE pat, long *start, int set_backref_str)
|
||||||
{
|
{
|
||||||
VALUE result, match;
|
VALUE result = Qnil;
|
||||||
struct re_registers *regs;
|
|
||||||
int i;
|
|
||||||
long end, pos = rb_pat_search(pat, str, *start, set_backref_str);
|
long end, pos = rb_pat_search(pat, str, *start, set_backref_str);
|
||||||
if (pos >= 0) {
|
if (pos >= 0) {
|
||||||
|
VALUE match;
|
||||||
|
struct re_registers *regs;
|
||||||
if (BUILTIN_TYPE(pat) == T_STRING) {
|
if (BUILTIN_TYPE(pat) == T_STRING) {
|
||||||
regs = NULL;
|
regs = NULL;
|
||||||
end = pos + RSTRING_LEN(pat);
|
end = pos + RSTRING_LEN(pat);
|
||||||
@ -9988,6 +9988,7 @@ scan_once(VALUE str, VALUE pat, long *start, int set_backref_str)
|
|||||||
pos = BEG(0);
|
pos = BEG(0);
|
||||||
end = END(0);
|
end = END(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pos == end) {
|
if (pos == end) {
|
||||||
rb_encoding *enc = STR_ENC_GET(str);
|
rb_encoding *enc = STR_ENC_GET(str);
|
||||||
/*
|
/*
|
||||||
@ -10002,23 +10003,28 @@ scan_once(VALUE str, VALUE pat, long *start, int set_backref_str)
|
|||||||
else {
|
else {
|
||||||
*start = end;
|
*start = end;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!regs || regs->num_regs == 1) {
|
if (!regs || regs->num_regs == 1) {
|
||||||
result = rb_str_subseq(str, pos, end - pos);
|
result = rb_str_subseq(str, pos, end - pos);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
result = rb_ary_new2(regs->num_regs);
|
result = rb_ary_new2(regs->num_regs);
|
||||||
for (i=1; i < regs->num_regs; i++) {
|
for (int i = 1; i < regs->num_regs; i++) {
|
||||||
VALUE s = Qnil;
|
VALUE s = Qnil;
|
||||||
if (BEG(i) >= 0) {
|
if (BEG(i) >= 0) {
|
||||||
s = rb_str_subseq(str, BEG(i), END(i)-BEG(i));
|
s = rb_str_subseq(str, BEG(i), END(i)-BEG(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
rb_ary_push(result, s);
|
rb_ary_push(result, s);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RB_GC_GUARD(match);
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
return Qnil;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1622,6 +1622,10 @@ CODE
|
|||||||
assert_equal(%w[1 2 3], S("a1 a2 a3").scan(/a\K./))
|
assert_equal(%w[1 2 3], S("a1 a2 a3").scan(/a\K./))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_scan_gc_compact_stress
|
||||||
|
EnvUtil.under_gc_compact_stress { assert_equal([["1a"], ["2b"], ["3c"]], S("1a2b3c").scan(/(\d.)/)) }
|
||||||
|
end
|
||||||
|
|
||||||
def test_scan_segv
|
def test_scan_segv
|
||||||
bug19159 = '[Bug #19159]'
|
bug19159 = '[Bug #19159]'
|
||||||
assert_nothing_raised(Exception, bug19159) do
|
assert_nothing_raised(Exception, bug19159) do
|
||||||
|
Loading…
x
Reference in New Issue
Block a user