[#97536] [Ruby master Bug#16694] JIT vs hardened GCC with PCH — v.ondruch@...
Issue #16694 has been reported by vo.x (Vit Ondruch).
11 messages
2020/03/18
[ruby-core:97630] [Ruby master Bug#15935] Memory leak triggered by String#encode, possibly elsewhere too
From:
usa@...
Date:
2020-03-30 21:11:46 UTC
List:
ruby-core #97630
Issue #15935 has been updated by usa (Usaku NAKAMURA).
Backport changed from 2.4: UNKNOWN, 2.5: REQUIRED, 2.6: DONE to 2.4: UNKNOWN, 2.5: DONE, 2.6: DONE
ruby_2_5 r67860 merged revision(s) 78ef2d0f331c3e056ee367214710b41722de2fe0.
----------------------------------------
Bug #15935: Memory leak triggered by String#encode, possibly elsewhere too
https://bugs.ruby-lang.org/issues/15935#change-84823
* Author: luke-gru (Luke Gruber)
* Status: Closed
* Priority: Normal
* Backport: 2.4: UNKNOWN, 2.5: DONE, 2.6: DONE
----------------------------------------
Hi, I've found a leak that can be reproduced in the following way:
```ruby
loop do
puts "running..."
50.times do
File.open("./test/rexml/data/utf16.xml", external_encoding: 'UTF-16LE', binmode: true) do |f| # must be in ruby's srcdir
while line = f.readline()
line.encode("UTF-8", "UTF-16LE")
end
end
rescue EOFError
end
end
```
It seems to be due to `rb_enc_associate_index()`, in encoding.c, which can call `rb_str_change_terminator_length()` with
the given string. Under certain conditions, `str_make_independent_expand()` is called in this function. This function
can allocate a new heap buffer if the string is large enough to not be embeddable, but does not free the previous one, if
necessary.
The following patch seems to fix the leak:
```c
oldptr = RSTRING_PTR(str);
if (oldptr) {
memcpy(ptr, oldptr, len);
}
if (!str_dependent_p(str) && !FL_TEST(str, STR_NOFREE) && FL_TEST(str, STR_NOEMBED)) {
xfree(oldptr);
}
```
I can add PR if you want, or you can fix it as you see fit with whichever code you prefer.
NOTE: I found this leak by adding more debug assertions to string.c. Basically I added the same code as above, except instead of `xfree` I asserted that the string should never
have a freeable buffer, as this is the assumption the function seemed to make.
Then, when running make test-all, I run into this failed assertion a bunch, especially in rexml tests. This also causes the leak:
```ruby
loop do
File.open("./test/rexml/data/utf16.xml") do |f|
REXML::Document.new(f)
end
end
```
Thanks for your time :)
--
https://bugs.ruby-lang.org/
Unsubscribe: <mailto:ruby-core-request@ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>