diff options
| author | Peter Zhu <peter@peterzhu.ca> | 2023-06-29 15:25:31 -0400 |
|---|---|---|
| committer | Peter Zhu <peter@peterzhu.ca> | 2023-06-29 19:07:26 -0400 |
| commit | d3ff43852b22f5463d22aab390ef340d9ebe4b06 (patch) | |
| tree | c99959edf8a7a0b0ea445f090208433a4f8ba386 | |
| parent | 1272865a8ee948816ee9f5484f8adba8e26f45e2 (diff) | |
Fix memory leak in Hash#replace
Hash#replace can leak memory if the receiver has an ST table.
Notes
Notes:
Merged: https://github.com/ruby/ruby/pull/8001
| -rw-r--r-- | hash.c | 15 | ||||
| -rw-r--r-- | test/ruby/test_hash.rb | 2 |
2 files changed, 15 insertions, 2 deletions
@@ -1158,6 +1158,19 @@ ar_clear(VALUE hash) } } +static void +st_free_and_clear_table(VALUE hash) +{ + HASH_ASSERT(RHASH_ST_TABLE_P(hash)); + + st_table *tab = RHASH_ST_TABLE(hash); + + if (tab->bins != NULL) free(tab->bins); + free(tab->entries); + + RHASH_ST_CLEAR(hash); +} + typedef int st_foreach_func(st_data_t, st_data_t, st_data_t); struct foreach_safe_arg { @@ -2894,7 +2907,7 @@ rb_hash_replace(VALUE hash, VALUE hash2) ar_free_and_clear_table(hash); } else { - RHASH_ST_CLEAR(hash); + st_free_and_clear_table(hash); } hash_copy(hash, hash2); diff --git a/test/ruby/test_hash.rb b/test/ruby/test_hash.rb index e66beef29f..9121f3539e 100644 --- a/test/ruby/test_hash.rb +++ b/test/ruby/test_hash.rb @@ -1325,7 +1325,7 @@ class TestHash < Test::Unit::TestCase end def test_replace_memory_leak - assert_no_memory_leak([], "#{<<-"begin;"}", "#{<<-'end;'}") + assert_no_memory_leak([], "#{<<-"begin;"}", "#{<<-'end;'}", rss: true) h = ("aa".."zz").each_with_index.to_h 10_000.times {h.dup} begin; |
