summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--string.c9
-rw-r--r--test/ruby/test_string.rb5
2 files changed, 14 insertions, 0 deletions
diff --git a/string.c b/string.c
index e402a5a7aa..3feeb8c705 100644
--- a/string.c
+++ b/string.c
@@ -1615,6 +1615,15 @@ rb_str_init(int argc, VALUE *argv, VALUE str)
char *new_ptr = ALLOC_N(char, (size_t)capa + termlen);
memcpy(new_ptr, RSTRING(str)->as.ary, RSTRING_EMBED_LEN_MAX + 1);
RSTRING(str)->as.heap.ptr = new_ptr;
+ }
+ else if (FL_TEST(str, STR_SHARED|STR_NOFREE)) {
+ const size_t size = (size_t)capa + termlen;
+ const char *const old_ptr = RSTRING_PTR(str);
+ const size_t osize = RSTRING(str)->as.heap.len + TERM_LEN(str);
+ char *new_ptr = ALLOC_N(char, (size_t)capa + termlen);
+ memcpy(new_ptr, old_ptr, osize < size ? osize : size);
+ FL_UNSET_RAW(str, STR_SHARED);
+ RSTRING(str)->as.heap.ptr = new_ptr;
}
else if (STR_HEAP_SIZE(str) != (size_t)capa + termlen) {
SIZED_REALLOC_N(RSTRING(str)->as.heap.ptr, char,
diff --git a/test/ruby/test_string.rb b/test/ruby/test_string.rb
index 1d81d24dba..afa3803023 100644
--- a/test/ruby/test_string.rb
+++ b/test/ruby/test_string.rb
@@ -79,6 +79,11 @@ class TestString < Test::Unit::TestCase
assert_equal("mystring", str.__send__(:initialize, str, capacity: 1000))
end
+ def test_initialize_shared
+ String.new(str = "mystring" * 10).__send__(:initialize, capacity: str.bytesize)
+ assert_equal("mystring", str[0, 8])
+ end
+
def test_initialize_nonstring
assert_raise(TypeError) {
S(1)