str_duplicate: Don't share with a frozen shared string
This is a follow up for 3f9562015e651735bfc2fdd14e8f6963b673e22a.
Before this commit, it was possible to create a shared string which
shares with another shared string by passing a frozen shared string
to str_duplicate.
This is bad news because rb_fstring(shared2) can make shared1
independent, which severs the reference from shared1 to root:
/* from fstr_update_callback() */str=str_new_frozen(rb_cString,shared2);/* can return shared1 */if(STR_SHARED_P(str)){/* shared1 is also a shared string */str_make_independent(str);/* no frozen check */}
If shared1 was the only reference to root, then root can be
reclaimed by the GC, leaving shared2 in a corrupted state:
str_duplicate: Don't share with a frozen shared string
This is a follow up for 3f9562015e651735bfc2fdd14e8f6963b673e22a.
Before this commit, it was possible to create a shared string which
shares with another shared string by passing a frozen shared string
to
str_duplicate
.Such string looks like:
This is bad news because
rb_fstring(shared2)
can makeshared1
independent, which severs the reference from
shared1
toroot
:If
shared1
was the only reference toroot
, thenroot
can bereclaimed by the GC, leaving
shared2
in a corrupted state:Here is a reproduction script for the situation this commit fixes.
the original is a shared string.
rb_str_dup
to makesure it does not try to share with a shared string.
[Bug #15792]
Closes: https://github.com/ruby/ruby/pull/2159