1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

[Bug #19029] Don't start GC during compaction

RARRAY_PTR when called with a transient array detransients the array
before returning its pointer which allocates in the heap.

Because RARRAY_PTR was being used during compaction (when re-embedding
arrays that have moved between size pools) this introduces the
possibility that we can hit a malloc threshold, triggering GC, while in
the middle of compaction.

We should avoid this by using safer functions to get hold of the
pointer. Since we know that the array is not embedded here, we can use
ARY_HEAP_PTR and ARY_EMBED_PTR directly
This commit is contained in:
Matt Valentine-House 2022-09-28 14:45:43 +01:00 committed by Peter Zhu
parent 4ced7bfb23
commit 892f350a7d
Notes: git 2022-09-29 22:22:37 +09:00

12
array.c
View file

@ -505,17 +505,21 @@ rb_ary_make_embedded(VALUE ary)
{ {
assert(rb_ary_embeddable_p(ary)); assert(rb_ary_embeddable_p(ary));
if (!ARY_EMBED_P(ary)) { if (!ARY_EMBED_P(ary)) {
VALUE *buf = RARRAY_PTR(ary); const VALUE *buf = ARY_HEAP_PTR(ary);
long len = RARRAY_LEN(ary); long len = ARY_HEAP_LEN(ary);
bool was_transient = RARRAY_TRANSIENT_P(ary);
// FL_SET_EMBED also unsets the transient flag
FL_SET_EMBED(ary); FL_SET_EMBED(ary);
ARY_SET_EMBED_LEN(ary, len); ARY_SET_EMBED_LEN(ary, len);
RARY_TRANSIENT_UNSET(ary);
memmove(RARRAY_PTR(ary), buf, len * sizeof(VALUE)); MEMCPY((void *)ARY_EMBED_PTR(ary), (void *)buf, VALUE, len);
if (!was_transient) {
ary_heap_free_ptr(ary, buf, len * sizeof(VALUE)); ary_heap_free_ptr(ary, buf, len * sizeof(VALUE));
} }
} }
}
static void static void
ary_resize_capa(VALUE ary, long capacity) ary_resize_capa(VALUE ary, long capacity)