diff options
author | Nobuyoshi Nakada <nobu@ruby-lang.org> | 2019-06-19 14:03:02 +0900 |
---|---|---|
committer | Nobuyoshi Nakada <nobu@ruby-lang.org> | 2019-06-19 14:39:19 +0900 |
commit | 8797f48373dcfa3ff8e748667732dea8aea4347e (patch) | |
tree | 4a8a7e05b3e015b0c2e5e73328b05357d97c743c | |
parent | 148f50fc789d59319113a1fd2897dbe552e73e73 (diff) |
New buffer for shared string
* string.c (rb_str_init): allocate new buffer if the string is
shared. [Bug #15937]
-rw-r--r-- | string.c | 9 | ||||
-rw-r--r-- | test/ruby/test_string.rb | 5 |
2 files changed, 14 insertions, 0 deletions
@@ -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) |