[#105450] [Ruby master Feature#18228] Add a `timeout` option to `IO.copy_stream` — "byroot (Jean Boussier)" <noreply@...>
SXNzdWUgIzE4MjI4IGhhcyBiZWVuIHJlcG9ydGVkIGJ5IGJ5cm9vdCAoSmVhbiBCb3Vzc2llciku
11 messages
2021/09/27
[ruby-core:105196] [Ruby master Bug#18154] String#initialize leaks memory for STR_NOFREE strings
From:
"nagachika (Tomoyuki Chikanaga)" <noreply@...>
Date:
2021-09-11 05:19:14 UTC
List:
ruby-core #105196
Issue #18154 has been updated by nagachika (Tomoyuki Chikanaga).
Backport changed from 2.6: REQUIRED, 2.7: REQUIRED, 3.0: REQUIRED to 2.6: REQUIRED, 2.7: REQUIRED, 3.0: DONE
ruby_3_0 650af7d29d98de6a3c2631e31edc6fbe435ece89 merged revision(s) 5d815542815fe8b939239750bba7f8f0b79c97d6.
----------------------------------------
Bug #18154: String#initialize leaks memory for STR_NOFREE strings
https://bugs.ruby-lang.org/issues/18154#change-93602
* Author: peterzhu2118 (Peter Zhu)
* Status: Closed
* Priority: Normal
* Backport: 2.6: REQUIRED, 2.7: REQUIRED, 3.0: DONE
----------------------------------------
# GitHub PR: https://github.com/ruby/ruby/pull/4814
There is a memory leak in calling the constructor on a string that is marked `STR_NOFREE` (e.g. a string created from a C string literal). The script below reproduces the memory leak. This is reproducible on all maintained Rubies (2.6.8, 2.7.4, 3.0.2, master) on Ubuntu 20.04.
We create a string marked `STR_NOFREE` with `0.to_s`. `to_s` for Fixnum has a [special optimization](https://github.com/ruby/ruby/blob/26153667f91f0c883f6af6b61fac2c0df5312b45/numeric.c#L3393) for the value `0` (it directly converts it to a C string literal). When we call `String#initialize` with a capacity it creates a buffer using `malloc` but does not unset the `STR_NOFREE` flag. This causes the buffer to be permanently leaked.
```ruby
100.times do
1000.times do
# 0.to_s is a special case that creates a string from a C string literal.
# https://github.com/ruby/ruby/blob/26153667f91f0c883f6af6b61fac2c0df5312b45/numeric.c#L3393
# C string literals are always marked STR_NOFREE.
str = 0.to_s
# Call String#initialize again to create a buffer with a capacity of 10000
# characters.
str.send(:initialize, capacity: 10000)
end
# Output the Resident Set Size (memory usage, in KB) of the current Ruby process.
puts `ps -o rss= -p #{$$}`
end
```
We can see the leak through the following graph of the Resident Set Size (RSS) comparing the branch vs. master (at commit 26153667f91f0c883f6af6b61fac2c0df5312b45).

--
https://bugs.ruby-lang.org/
Unsubscribe: <mailto:[email protected]?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>