summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--string.c11
-rw-r--r--test/ruby/test_string.rb9
2 files changed, 17 insertions, 3 deletions
diff --git a/string.c b/string.c
index 386c460740..895fe62952 100644
--- a/string.c
+++ b/string.c
@@ -1505,9 +1505,14 @@ str_duplicate(VALUE klass, VALUE str)
char, embed_size);
if (flags & STR_NOEMBED) {
if (UNLIKELY(!(flags & FL_FREEZE))) {
- str = str_new_frozen(klass, str);
- FL_SET_RAW(str, flags & FL_TAINT);
- flags = FL_TEST_RAW(str, flag_mask);
+ if (FL_TEST_RAW(str, STR_SHARED)) {
+ str = RSTRING(str)->as.heap.aux.shared;
+ }
+ else {
+ str = str_new_frozen(klass, str);
+ FL_SET_RAW(str, flags & FL_TAINT);
+ flags = FL_TEST_RAW(str, flag_mask);
+ }
}
if (flags & STR_NOEMBED) {
RB_OBJ_WRITE(dup, &RSTRING(dup)->as.heap.aux.shared, str);
diff --git a/test/ruby/test_string.rb b/test/ruby/test_string.rb
index d94c4da7ae..f591f7ea9d 100644
--- a/test/ruby/test_string.rb
+++ b/test/ruby/test_string.rb
@@ -2961,6 +2961,15 @@ CODE
end
=end
+ def test_nesting_shared
+ a = ('a' * 24).encode(Encoding::ASCII).gsub('x', '')
+ hash = {}
+ hash[a] = true
+ assert_equal(('a' * 24), a)
+ 4.times { GC.start }
+ assert_equal(('a' * 24), a, '[Bug #15792]')
+ end
+
def test_shared_force_encoding
s = "\u{3066}\u{3059}\u{3068}".gsub(//, '')
h = {}