From 918c25720da187c5d65d6f51cbb0353105fb1c0e Mon Sep 17 00:00:00 2001 From: Alan Wu Date: Wed, 13 Dec 2023 12:11:49 -0500 Subject: [PATCH] Fix memory leak in Hash#compare_by_identity We didn't free the old ST before overwriting it which caused a leak. Found with RUBY_FREE_ON_EXIT. Co-authored-by: Peter Zhu --- hash.c | 1 + test/ruby/test_hash.rb | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/hash.c b/hash.c index 1545af87b26935..787b824da29da2 100644 --- a/hash.c +++ b/hash.c @@ -4372,6 +4372,7 @@ rb_hash_compare_by_id(VALUE hash) rb_hash_foreach(hash, rb_hash_rehash_i, (VALUE)tmp); + rb_hash_free(hash); RHASH_ST_TABLE_SET(hash, identtable); RHASH_ST_CLEAR(tmp); diff --git a/test/ruby/test_hash.rb b/test/ruby/test_hash.rb index 639707d8eb66a4..8658e6ddc222ae 100644 --- a/test/ruby/test_hash.rb +++ b/test/ruby/test_hash.rb @@ -1909,6 +1909,14 @@ def test_st_literal_memory_leak end; end + def test_compare_by_id_memory_leak + assert_no_memory_leak([], "", <<~RUBY, rss: true) + 1_000_000.times do + {a: 1, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7, h: 8}.compare_by_identity + end + RUBY + end + def test_try_convert assert_equal({1=>2}, Hash.try_convert({1=>2})) assert_equal(nil, Hash.try_convert("1=>2"))