diff --git a/gc.c b/gc.c index 66cdb2cd4b..41d3d6aba4 100644 --- a/gc.c +++ b/gc.c @@ -1245,6 +1245,8 @@ rb_gc_obj_free_vm_weak_references(VALUE obj) switch (BUILTIN_TYPE(obj)) { case T_STRING: if (FL_TEST(obj, RSTRING_FSTR)) { + RUBY_ASSERT(!FL_TEST(obj, STR_SHARED)); + st_data_t fstr = (st_data_t)obj; st_delete(rb_vm_fstring_table(), &fstr, NULL); RB_DEBUG_COUNTER_INC(obj_str_fstr); diff --git a/string.c b/string.c index 916b675bc8..7a9392d6ae 100644 --- a/string.c +++ b/string.c @@ -1500,7 +1500,7 @@ rb_str_tmp_frozen_no_embed_acquire(VALUE orig) * allocated. If the string is shared then the shared root must be * embedded, so we want to create a copy. If the string is a shared root * then it must be embedded, so we want to create a copy. */ - if (STR_EMBED_P(orig) || FL_TEST_RAW(orig, STR_SHARED | STR_SHARED_ROOT)) { + if (STR_EMBED_P(orig) || FL_TEST_RAW(orig, STR_SHARED | STR_SHARED_ROOT | RSTRING_FSTR)) { RSTRING(str)->as.heap.ptr = rb_xmalloc_mul_add_mul(sizeof(char), capa, sizeof(char), TERM_LEN(orig)); memcpy(RSTRING(str)->as.heap.ptr, RSTRING_PTR(orig), capa); } diff --git a/test/ruby/test_string.rb b/test/ruby/test_string.rb index 0c75852093..f7009b518e 100644 --- a/test/ruby/test_string.rb +++ b/test/ruby/test_string.rb @@ -3438,6 +3438,15 @@ CODE assert_equal(false, str.frozen?) end + def test_uminus_no_embed_gc + pad = "a"*2048 + ("aa".."zz").each do |c| + fstr = -(c + pad).freeze + File.open(IO::NULL, "w").write(fstr) + end + GC.start + end + def test_ord assert_equal(97, S("a").ord) assert_equal(97, S("abc").ord)