Fix ary_make_partial_step for compaction
ary could change embeddedness due to compaction, so we should only get the pointer after allocations. The included test was crashing with: TestArray#test_slice_gc_compact_stress ruby/lib/pp.rb:192: [BUG] Segmentation fault at 0x0000000000000038
This commit is contained in:
parent
fd4735130e
commit
e191bf42d2
7
array.c
7
array.c
@ -1231,12 +1231,13 @@ ary_make_partial_step(VALUE ary, VALUE klass, long offset, long len, long step)
|
||||
assert(offset+len <= RARRAY_LEN(ary));
|
||||
assert(step != 0);
|
||||
|
||||
const VALUE *values = RARRAY_CONST_PTR(ary);
|
||||
const long orig_len = len;
|
||||
|
||||
if (step > 0 && step >= len) {
|
||||
VALUE result = ary_new(klass, 1);
|
||||
VALUE *ptr = (VALUE *)ARY_EMBED_PTR(result);
|
||||
const VALUE *values = RARRAY_CONST_PTR(ary);
|
||||
|
||||
RB_OBJ_WRITE(result, ptr, values[offset]);
|
||||
ARY_SET_EMBED_LEN(result, 1);
|
||||
return result;
|
||||
@ -1254,6 +1255,8 @@ ary_make_partial_step(VALUE ary, VALUE klass, long offset, long len, long step)
|
||||
VALUE result = ary_new(klass, len);
|
||||
if (ARY_EMBED_P(result)) {
|
||||
VALUE *ptr = (VALUE *)ARY_EMBED_PTR(result);
|
||||
const VALUE *values = RARRAY_CONST_PTR(ary);
|
||||
|
||||
for (i = 0; i < len; ++i) {
|
||||
RB_OBJ_WRITE(result, ptr+i, values[j]);
|
||||
j += step;
|
||||
@ -1261,6 +1264,8 @@ ary_make_partial_step(VALUE ary, VALUE klass, long offset, long len, long step)
|
||||
ARY_SET_EMBED_LEN(result, len);
|
||||
}
|
||||
else {
|
||||
const VALUE *values = RARRAY_CONST_PTR(ary);
|
||||
|
||||
RARRAY_PTR_USE(result, ptr, {
|
||||
for (i = 0; i < len; ++i) {
|
||||
RB_OBJ_WRITE(result, ptr+i, values[j]);
|
||||
|
@ -1704,6 +1704,10 @@ class TestArray < Test::Unit::TestCase
|
||||
|
||||
def test_slice_gc_compact_stress
|
||||
EnvUtil.under_gc_compact_stress { assert_equal([1, 2, 3, 4, 5], (0..10).to_a[1, 5]) }
|
||||
EnvUtil.under_gc_compact_stress do
|
||||
a = [0, 1, 2, 3, 4, 5]
|
||||
assert_equal([2, 1, 0], a.slice((2..).step(-1)))
|
||||
end
|
||||
end
|
||||
|
||||
def test_slice!
|
||||
|
Loading…
x
Reference in New Issue
Block a user