1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00
ruby--ruby/ext/-test-
Alan Wu c06ddfee87
str_duplicate: Don't share with a frozen shared string
This is a follow up for 3f9562015e.
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:

```
 --------                    -----------------
 | root | ------ owns -----> | root's buffer |
 --------                    -----------------
     ^                             ^   ^
 -----------                       |   |
 | shared1 | ------ references -----   |
 -----------                           |
     ^                                 |
 -----------                           |
 | shared2 | ------ references ---------
 -----------
```

This is bad news because `rb_fstring(shared2)` can make `shared1`
independent, which severs the reference from `shared1` to `root`:

```c
/* 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:

```
 -----------                         --------------------
 | shared1 | -------- owns --------> | shared1's buffer |
 -----------                         --------------------
      ^
      |
 -----------                         -------------------------
 | shared2 | ------ references ----> | root's buffer (freed) |
 -----------                         -------------------------
```

Here is a reproduction script for the situation this commit fixes.

```ruby
a = ('a' * 24).strip.freeze.strip
-a
p a
4.times { GC.start }
p a
```

 - string.c (str_duplicate): always share with the root string when
   the original is a shared string.
 - test_rb_str_dup.rb: specifically test `rb_str_dup` to make
   sure it does not try to share with a shared string.

[Bug #15792]

Closes: https://github.com/ruby/ruby/pull/2159
2019-05-09 10:04:19 +09:00
..
arith_seq/extract ../arith_seq/../extract.c: remove unused variable 2018-12-21 16:19:31 +00:00
array/resize
bignum Use $(hdrdir) for include/ruby.h, as well as r67033 2019-02-11 13:43:14 +00:00
bug-3571
bug-5832
bug_reporter
class Use $(hdrdir) for include/ruby.h, as well as r67033 2019-02-11 13:43:14 +00:00
debug Use $(hdrdir) for include/ruby.h, as well as r67033 2019-02-11 13:43:14 +00:00
dln/empty
exception Use $(hdrdir) for include/ruby.h, as well as r67033 2019-02-11 13:43:14 +00:00
fatal
file Use $(hdrdir) for include/ruby.h, as well as r67033 2019-02-11 13:43:14 +00:00
float
funcall ruby.h: relax rb_funcall check on extra args for clang 2018-01-30 23:55:49 +00:00
gvl/call_without_gvl Suppress a warning 2019-02-13 15:20:50 +00:00
hash
integer numeric.c: fix infinite loop 2019-03-11 01:37:16 +00:00
iseq_load
iter UNREACHABLE_RETURN 2018-07-24 05:38:07 +00:00
load
marshal
memory_status
method
notimplement Add more assertions for NotImplementedError of instance method 2018-08-21 14:57:56 +00:00
num2int
path_to_class
popen_deadlock
postponed_job
printf
proc
rational Use $(hdrdir) for include/ruby.h, as well as r67033 2019-02-11 13:43:14 +00:00
recursion
regexp
scan_args
st
string str_duplicate: Don't share with a frozen shared string 2019-05-09 10:04:19 +09:00
struct Use $(hdrdir) for include/ruby.h, as well as r67033 2019-02-11 13:43:14 +00:00
symbol
thread_fd_close
time Use $(hdrdir) for include/ruby.h, as well as r67033 2019-02-11 13:43:14 +00:00
tracepoint
typeddata
vm
wait_for_single_fd -test-/wait_for_single_fd: fix -Wformat-security warning 2018-05-15 01:29:14 +00:00
win32 test_console_attr.rb: fix test 2018-01-15 12:25:24 +00:00
auto_ext.rb