summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Zhu <peter@peterzhu.ca>2022-03-12 12:15:04 -0500
committerPeter Zhu <peter@peterzhu.ca>2022-03-12 12:15:24 -0500
commit06594e713416fad35b6241fed802607682d7cea6 (patch)
tree4f1831ee4b63e8d5d65fc116448714dec76f59ee
parent83fabfccf5d45312325bab83de2cf62ea54fa020 (diff)
Fix crash on GC stress and RGENGC_CHECK_MODE=2
rb_ary_reset could leave the array in a bad state since it frees memory but does not unset any flags. This can cause a crash on GC stress. This commit changes rb_ary_reset to set the array as an empty embedded array.
-rw-r--r--array.c9
1 files changed, 6 insertions, 3 deletions
diff --git a/array.c b/array.c
index 2790c2a61f..ae2ba38cbe 100644
--- a/array.c
+++ b/array.c
@@ -537,6 +537,9 @@ rb_ary_reset(VALUE ary)
else if (ARY_SHARED_P(ary)) {
rb_ary_unshare(ary);
}
+
+ FL_SET_EMBED(ary);
+ ARY_SET_EMBED_LEN(ary, 0);
}
static VALUE
@@ -1079,8 +1082,8 @@ rb_ary_initialize(int argc, VALUE *argv, VALUE ary)
rb_ary_modify(ary);
if (argc == 0) {
rb_ary_reset(ary);
- FL_SET_EMBED(ary);
- ARY_SET_EMBED_LEN(ary, 0);
+ assert(ARY_EMBED_P(ary));
+ assert(ARY_EMBED_LEN(ary) == 0);
if (rb_block_given_p()) {
rb_warning("given block not used");
}
@@ -4394,7 +4397,7 @@ rb_ary_replace(VALUE copy, VALUE orig)
rb_ary_reset(copy);
if (RARRAY_LEN(orig) <= RARRAY_EMBED_LEN_MAX) {
- FL_SET_EMBED(copy);
+ assert(ARY_EMBED_P(copy));
ary_memcpy(copy, 0, RARRAY_LEN(orig), RARRAY_CONST_PTR_TRANSIENT(orig));
ARY_SET_LEN(copy, RARRAY_LEN(orig));
}