diff options
author | Peter Zhu <[email protected]> | 2023-12-18 20:55:59 -0500 |
---|---|---|
committer | Peter Zhu <[email protected]> | 2023-12-21 10:39:03 -0500 |
commit | e191bf42d2077a025c21888573f8b81688e5ea28 (patch) | |
tree | 69e009c2b48a2da585672c04b6dfc59b864ef377 /array.c | |
parent | fd4735130e5fdc0a11f970092d5900847a3ce4cf (diff) |
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
Diffstat (limited to 'array.c')
-rw-r--r-- | array.c | 7 |
1 files changed, 6 insertions, 1 deletions
@@ -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]); |