diff --git a/string.c b/string.c index d8c2a9108502ff..a4ba85f42e2a07 100644 --- a/string.c +++ b/string.c @@ -1877,17 +1877,13 @@ rb_str_init(int argc, VALUE *argv, VALUE str) if (orig == str) n = 0; } str_modifiable(str); - if (STR_EMBED_P(str)) { /* make noembed always */ - char *new_ptr = ALLOC_N(char, (size_t)capa + termlen); - RUBY_ASSERT(RSTRING_LEN(str) + 1 <= str_embed_capa(str)); - memcpy(new_ptr, RSTRING(str)->as.embed.ary, RSTRING_LEN(str) + 1); - RSTRING(str)->as.heap.ptr = new_ptr; - } - else if (FL_TEST(str, STR_SHARED|STR_NOFREE)) { + if (STR_EMBED_P(str) || FL_TEST(str, STR_SHARED|STR_NOFREE)) { + /* make noembed always */ const size_t size = (size_t)capa + termlen; const char *const old_ptr = RSTRING_PTR(str); const size_t osize = RSTRING_LEN(str) + TERM_LEN(str); - char *new_ptr = ALLOC_N(char, (size_t)capa + termlen); + char *new_ptr = ALLOC_N(char, size); + if (STR_EMBED_P(str)) RUBY_ASSERT(osize <= str_embed_capa(str)); memcpy(new_ptr, old_ptr, osize < size ? osize : size); FL_UNSET_RAW(str, STR_SHARED|STR_NOFREE); RSTRING(str)->as.heap.ptr = new_ptr; diff --git a/test/ruby/test_string.rb b/test/ruby/test_string.rb index 42f2544b5a8692..85a72b09ccfeda 100644 --- a/test/ruby/test_string.rb +++ b/test/ruby/test_string.rb @@ -80,6 +80,13 @@ def test_initialize assert_equal("mystring", str.__send__(:initialize, "mystring", capacity: 1000)) str = S("mystring") assert_equal("mystring", str.__send__(:initialize, str, capacity: 1000)) + + if @cls == String + 100.times { + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa". + __send__(:initialize, capacity: -1) + } + end end def test_initialize_shared