Fix memory leak in Hash#replace

Hash#replace can leak memory if the receiver has an ST table.
This commit is contained in:
Peter Zhu 2023-06-29 15:25:31 -04:00
Родитель 1272865a8e
Коммит d3ff43852b
2 изменённых файлов: 15 добавлений и 2 удалений

15
hash.c
Просмотреть файл

@ -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);

Просмотреть файл

@ -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;