aboutsummaryrefslogtreecommitdiffstats
path: root/hash.c
diff options
context:
space:
mode:
authorPeter Zhu <peter@peterzhu.ca>2023-06-29 09:21:11 -0400
committerPeter Zhu <peter@peterzhu.ca>2023-06-29 11:16:50 -0400
commitf0d08d11dcd404f3146c0d71d6ff743bbc6e7193 (patch)
tree82e6bb0fff741e124915c7a2f6aabe54a484ee71 /hash.c
parentdf2b3a29987e9353596af76ed77f35d7366d654e (diff)
downloadruby-f0d08d11dcd404f3146c0d71d6ff743bbc6e7193.tar.gz
Fix memory leak when copying ST tables
st_copy allocates a st_table, which is not needed for hashes since it is allocated by VWA and embedded, so this causes a memory leak. The following script demonstrates the issue: ```ruby 20.times do 100_000.times do {a: 1, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7, h: 8, i: 9} end puts `ps -o rss= -p #{$$}` end ```
Diffstat (limited to 'hash.c')
-rw-r--r--hash.c7
1 files changed, 5 insertions, 2 deletions
diff --git a/hash.c b/hash.c
index a74db258e4..a779c6f218 100644
--- a/hash.c
+++ b/hash.c
@@ -1482,7 +1482,9 @@ hash_copy(VALUE ret, VALUE hash)
else {
HASH_ASSERT(sizeof(st_table) <= sizeof(ar_table));
- RHASH_ST_TABLE_SET(ret, st_copy(RHASH_ST_TABLE(hash)));
+ RHASH_SET_ST_FLAG(ret);
+ st_replace(RHASH_ST_TABLE(ret), RHASH_ST_TABLE(hash));
+
rb_gc_writebarrier_remember(ret);
}
return ret;
@@ -1776,7 +1778,8 @@ rb_hash_s_create(int argc, VALUE *argv, VALUE klass)
}
else {
hash = hash_alloc(klass);
- hash_copy(hash, tmp);
+ if (!RHASH_EMPTY_P(tmp))
+ hash_copy(hash, tmp);
return hash;
}
}