summaryrefslogtreecommitdiff
path: root/test/ruby
diff options
context:
space:
mode:
authorU.Nakamura <usa@ruby-lang.org>2023-10-17 20:30:28 +0900
committerU.Nakamura <usa@ruby-lang.org>2023-10-17 20:30:28 +0900
commita3e1444663005d3440b56c3a8e1b88bb28935912 (patch)
treea23a03bc08b6fcb852b491d24f739c8f667122e8 /test/ruby
parent84f2aabd272a54e79979795d2d405090704a1d07 (diff)
merge revision(s) 96c5a4be7b0d72502001734770af0f4a735c544c: [Backport #19894]
Fix memory leak in complemented method entries [Bug #19894] When a copy of a complemented method entry is created, there are two issues: 1. IMEMO_FL_USER3 is not copied, so the complemented status is not copied over. 2. In rb_method_entry_clone we increment both alias_count and complemented_count. However, when we free the method entry in rb_method_definition_release, we only decrement one of the two counters, resulting in the rb_method_definition_t being leaked. Co-authored-by: Adam Hess <adamhess1991@gmail.com> --- method.h | 5 +++-- test/ruby/test_module.rb | 29 +++++++++++++++++++++++++++++ vm_method.c | 8 +++++--- 3 files changed, 37 insertions(+), 5 deletions(-)
Diffstat (limited to 'test/ruby')
-rw-r--r--test/ruby/test_module.rb44
1 files changed, 44 insertions, 0 deletions
diff --git a/test/ruby/test_module.rb b/test/ruby/test_module.rb
index fa890c0e40..b5414d139e 100644
--- a/test/ruby/test_module.rb
+++ b/test/ruby/test_module.rb
@@ -3176,6 +3176,50 @@ class TestModule < Test::Unit::TestCase
assert_match(/::Foo$/, mod.name, '[Bug #14895]')
end
+ def test_iclass_memory_leak
+ # [Bug #19550]
+ assert_no_memory_leak([], <<~PREP, <<~CODE, rss: true)
+ code = proc do
+ mod = Module.new
+ Class.new do
+ include mod
+ end
+ end
+ 1_000.times(&code)
+ PREP
+ 3_000_000.times(&code)
+ CODE
+ end
+
+ def test_complemented_method_entry_memory_leak
+ # [Bug #19894]
+ assert_no_memory_leak([], <<~PREP, <<~CODE, rss: true)
+ code = proc do
+ $c = Class.new do
+ def foo; end
+ end
+
+ $m = Module.new do
+ refine $c do
+ def foo; end
+ end
+ end
+
+ Class.new do
+ using $m
+
+ def initialize
+ o = $c.new
+ o.method(:foo).unbind
+ end
+ end.new
+ end
+ 1_000.times(&code)
+ PREP
+ 100_000.times(&code)
+ CODE
+ end
+
private
def assert_top_method_is_private(method)