summaryrefslogtreecommitdiff
path: root/string.c
diff options
context:
space:
mode:
authorNobuyoshi Nakada <nobu@ruby-lang.org>2019-04-27 21:21:55 +0900
committerNobuyoshi Nakada <nobu@ruby-lang.org>2019-04-27 21:26:42 +0900
commit3f9562015e651735bfc2fdd14e8f6963b673e22a (patch)
treee3b5107346fcd0bbff7576bd2f511f90194dc1d3 /string.c
parentafb361dfd0811f96f601d8d6492f9e1a0321ea01 (diff)
Get rid of indirect sharing
* string.c (str_duplicate): share the root shared string if the original string is already sharing, so that all shared strings refer the root shared string directly. indirect sharing can cause a dangling pointer. [Bug #15792]
Diffstat (limited to 'string.c')
-rw-r--r--string.c11
1 files changed, 8 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);