diff options
author | Peter Zhu <peter@peterzhu.ca> | 2022-03-12 12:15:04 -0500 |
---|---|---|
committer | Peter Zhu <peter@peterzhu.ca> | 2022-03-12 12:15:24 -0500 |
commit | 06594e713416fad35b6241fed802607682d7cea6 (patch) | |
tree | 4f1831ee4b63e8d5d65fc116448714dec76f59ee | |
parent | 83fabfccf5d45312325bab83de2cf62ea54fa020 (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.c | 9 |
1 files changed, 6 insertions, 3 deletions
@@ -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)); } |