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(offset+len <= RARRAY_LEN(ary));
|
||||||
assert(step != 0);
|
assert(step != 0);
|
||||||
|
|
||||||
const VALUE *values = RARRAY_CONST_PTR(ary);
|
|
||||||
const long orig_len = len;
|
const long orig_len = len;
|
||||||
|
|
||||||
if (step > 0 && step >= len) {
|
if (step > 0 && step >= len) {
|
||||||
VALUE result = ary_new(klass, 1);
|
VALUE result = ary_new(klass, 1);
|
||||||
VALUE *ptr = (VALUE *)ARY_EMBED_PTR(result);
|
VALUE *ptr = (VALUE *)ARY_EMBED_PTR(result);
|
||||||
|
const VALUE *values = RARRAY_CONST_PTR(ary);
|
||||||
|
|
||||||
RB_OBJ_WRITE(result, ptr, values[offset]);
|
RB_OBJ_WRITE(result, ptr, values[offset]);
|
||||||
ARY_SET_EMBED_LEN(result, 1);
|
ARY_SET_EMBED_LEN(result, 1);
|
||||||
return result;
|
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);
|
VALUE result = ary_new(klass, len);
|
||||||
if (ARY_EMBED_P(result)) {
|
if (ARY_EMBED_P(result)) {
|
||||||
VALUE *ptr = (VALUE *)ARY_EMBED_PTR(result);
|
VALUE *ptr = (VALUE *)ARY_EMBED_PTR(result);
|
||||||
|
const VALUE *values = RARRAY_CONST_PTR(ary);
|
||||||
|
|
||||||
for (i = 0; i < len; ++i) {
|
for (i = 0; i < len; ++i) {
|
||||||
RB_OBJ_WRITE(result, ptr+i, values[j]);
|
RB_OBJ_WRITE(result, ptr+i, values[j]);
|
||||||
j += step;
|
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);
|
ARY_SET_EMBED_LEN(result, len);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
const VALUE *values = RARRAY_CONST_PTR(ary);
|
||||||
|
|
||||||
RARRAY_PTR_USE(result, ptr, {
|
RARRAY_PTR_USE(result, ptr, {
|
||||||
for (i = 0; i < len; ++i) {
|
for (i = 0; i < len; ++i) {
|
||||||
RB_OBJ_WRITE(result, ptr+i, values[j]);
|
RB_OBJ_WRITE(result, ptr+i, values[j]);
|
||||||
|
@ -1704,6 +1704,10 @@ class TestArray < Test::Unit::TestCase
|
|||||||
|
|
||||||
def test_slice_gc_compact_stress
|
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 { 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
|
end
|
||||||
|
|
||||||
def test_slice!
|
def test_slice!
|
||||||
|
Loading…
x
Reference in New Issue
Block a user