ruby-changes:56137
From: Nobuyoshi <ko1@a...>
Date: Wed, 19 Jun 2019 09:57:35 +0900 (JST)
Subject: [ruby-changes:56137] Nobuyoshi Nakada: 28678997e4 (trunk): Preserve the string content at self-copying
https://git.ruby-lang.org/ruby.git/commit/?id=28678997e4 From 28678997e40869f5591eae60edd9757334426ffb Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada <nobu@r...> Date: Wed, 19 Jun 2019 09:44:26 +0900 Subject: Preserve the string content at self-copying * string.c (rb_str_init): preserve the embedded content when self-copying with a capacity. [Bug #15937] diff --git a/string.c b/string.c index fdb7e40..e402a5a 100644 --- a/string.c +++ b/string.c @@ -1331,6 +1331,7 @@ str_new_empty(VALUE str) https://github.com/ruby/ruby/blob/trunk/string.c#L1331 } #define STR_BUF_MIN_SIZE 127 +STATIC_ASSERT(STR_BUF_MIN_SIZE, STR_BUF_MIN_SIZE > RSTRING_EMBED_LEN_MAX); VALUE rb_str_buf_new(long capa) @@ -1611,7 +1612,9 @@ rb_str_init(int argc, VALUE *argv, VALUE str) https://github.com/ruby/ruby/blob/trunk/string.c#L1612 } str_modifiable(str); if (STR_EMBED_P(str)) { /* make noembed always */ - RSTRING(str)->as.heap.ptr = ALLOC_N(char, (size_t)capa + termlen); + 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 (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 35f27c8..1d81d24 100644 --- a/test/ruby/test_string.rb +++ b/test/ruby/test_string.rb @@ -68,6 +68,15 @@ class TestString < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_string.rb#L68 assert_raise(FrozenError){ str.__send__(:initialize, encoding: 'euc-jp') } assert_raise(FrozenError){ str.__send__(:initialize, 'abc', encoding: 'euc-jp') } assert_raise(FrozenError){ str.__send__(:initialize, 'abc', capacity: 1000, encoding: 'euc-jp') } + + str = S("") + assert_equal("mystring", str.__send__(:initialize, "mystring")) + str = S("mystring") + assert_equal("mystring", str.__send__(:initialize, str)) + str = S("") + assert_equal("mystring", str.__send__(:initialize, "mystring", capacity: 1000)) + str = S("mystring") + assert_equal("mystring", str.__send__(:initialize, str, capacity: 1000)) end def test_initialize_nonstring -- cgit v0.10.2 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/